From 41eb6d44614ae3e8f4ee0c3e62533b07beb14679 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 1 Jun 2020 12:19:47 +0200 Subject: [PATCH] cellAudio improvements - use CELL_AUDIO_BLOCK_32 where possible - use CELL_AUDIO_BLOCK_SAMPLES where possible - remove redundant logging - return CELL_AUDIO_ERROR_AUDIOSYSTEM in cellAudioGetPortConfig (probably unreachable code anyway) - return CELL_AUDIO_ERROR_PORT_OPEN in cellAudioPortOpen - stub cellAudioSetPersonalDevice cellAudioUnsetPersonalDevice and cellAudioMiscSetAccessoryVolume --- rpcs3/Emu/Cell/Modules/cellAudio.cpp | 111 +++++++++++++++++++-------- rpcs3/Emu/Cell/Modules/cellAudio.h | 13 +++- 2 files changed, 92 insertions(+), 32 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp index 6cf695c3a4..6e69533e71 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -1039,16 +1039,16 @@ error_code cellAudioPortOpen(vm::ptr audioParam, vm::ptr audioParam, vm::ptr(1, num_channels); port->num_channels = ::narrow(num_channels); port->num_blocks = ::narrow(num_blocks); @@ -1115,6 +1118,11 @@ error_code cellAudioPortOpen(vm::ptr audioParam, vm::ptrlevel_set.store({ port->level, 0.0f }); + if (port->level <= -1.0f) + { + return CELL_AUDIO_ERROR_PORT_OPEN; + } + *portNum = port->number; return CELL_OK; } @@ -1143,10 +1151,18 @@ error_code cellAudioGetPortConfig(u32 portNum, vm::ptr port switch (auto state = port.state.load()) { - case audio_port_state::closed: portConfig->status = CELL_AUDIO_STATUS_CLOSE; break; - case audio_port_state::opened: portConfig->status = CELL_AUDIO_STATUS_READY; break; - case audio_port_state::started: portConfig->status = CELL_AUDIO_STATUS_RUN; break; - default: fmt::throw_exception("Invalid port state (%d: %d)", portNum, static_cast(state)); + case audio_port_state::closed: + portConfig->status = CELL_AUDIO_STATUS_CLOSE; + break; + case audio_port_state::opened: + portConfig->status = CELL_AUDIO_STATUS_READY; + break; + case audio_port_state::started: + portConfig->status = CELL_AUDIO_STATUS_RUN; + break; + default: + cellAudio.error("Invalid port state (%d: %d)", portNum, static_cast(state)); + return CELL_AUDIO_ERROR_AUDIOSYSTEM; } portConfig->nChannel = port.num_channels; @@ -1264,12 +1280,13 @@ error_code cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr stamp) if (port.global_counter < tag) { - cellAudio.error("cellAudioGetPortTimestamp(portNum=%d, tag=0x%llx, stamp=*0x%x) -> CELL_AUDIO_ERROR_TAG_NOT_FOUND", portNum, tag, stamp); return CELL_AUDIO_ERROR_TAG_NOT_FOUND; } - u64 delta_tag = port.global_counter - tag; - u64 delta_tag_stamp = delta_tag * g_audio->cfg.audio_block_period; + const u64 delta_tag = port.global_counter - tag; + const u64 delta_tag_stamp = delta_tag * g_audio->cfg.audio_block_period; + + // Apparently no error is returned if stamp is null *stamp = port.timestamp - delta_tag_stamp; return CELL_OK; @@ -1305,6 +1322,7 @@ error_code cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, vm::ptr tag) return CELL_AUDIO_ERROR_PARAM; } + // Apparently no error is returned if tag is null *tag = port.global_counter + blockNo - port.cur_pos; return CELL_OK; @@ -1511,18 +1529,11 @@ error_code cellAudioAddData(u32 portNum, vm::ptr src, u32 samples, float return CELL_AUDIO_ERROR_NOT_INIT; } - if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) + if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned() || samples != CELL_AUDIO_BLOCK_SAMPLES) { return CELL_AUDIO_ERROR_PARAM; } - if (samples != 256) - { - // despite the docs, seems that only fixed value is supported - cellAudio.error("cellAudioAddData(): invalid samples value (%d)", samples); - return CELL_AUDIO_ERROR_PARAM; - } - const audio_port& port = g_audio->ports[portNum]; const auto dst = port.get_vm_ptr(); @@ -1552,18 +1563,11 @@ error_code cellAudioAdd2chData(u32 portNum, vm::ptr src, u32 samples, flo return CELL_AUDIO_ERROR_NOT_INIT; } - if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned()) + if (portNum >= AUDIO_PORT_COUNT || !src || !src.aligned() || samples != CELL_AUDIO_BLOCK_SAMPLES) { return CELL_AUDIO_ERROR_PARAM; } - if (samples != 256) - { - // despite the docs, seems that only fixed value is supported - cellAudio.error("cellAudioAdd2chData(): invalid samples value (%d)", samples); - return CELL_AUDIO_ERROR_PARAM; - } - const audio_port& port = g_audio->ports[portNum]; const auto dst = port.get_vm_ptr(); @@ -1642,7 +1646,7 @@ error_code cellAudioAdd6chData(u32 portNum, vm::ptr src, float volume) if (port.num_channels == 6) { - for (u32 i = 0; i < 256; i++) + for (u32 i = 0; i < CELL_AUDIO_BLOCK_SAMPLES; i++) { dst[i * 6 + 0] += src[i * 6 + 0] * volume; // mix L ch dst[i * 6 + 1] += src[i * 6 + 1] * volume; // mix R ch @@ -1654,7 +1658,7 @@ error_code cellAudioAdd6chData(u32 portNum, vm::ptr src, float volume) } else if (port.num_channels == 8) { - for (u32 i = 0; i < 256; i++) + for (u32 i = 0; i < CELL_AUDIO_BLOCK_SAMPLES; i++) { dst[i * 8 + 0] += src[i * 6 + 0] * volume; // mix L ch dst[i * 8 + 1] += src[i * 6 + 1] * volume; // mix R ch @@ -1677,6 +1681,18 @@ error_code cellAudioAdd6chData(u32 portNum, vm::ptr src, float volume) error_code cellAudioMiscSetAccessoryVolume(u32 devNum, float volume) { cellAudio.todo("cellAudioMiscSetAccessoryVolume(devNum=%d, volume=%f)", devNum, volume); + + const auto g_audio = g_fxo->get(); + + std::unique_lock lock(g_audio->mutex); + + if (!g_audio->init) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + // TODO + return CELL_OK; } @@ -1689,12 +1705,47 @@ error_code cellAudioSendAck(u64 data3) error_code cellAudioSetPersonalDevice(s32 iPersonalStream, s32 iDevice) { cellAudio.todo("cellAudioSetPersonalDevice(iPersonalStream=%d, iDevice=%d)", iPersonalStream, iDevice); + + const auto g_audio = g_fxo->get(); + + std::unique_lock lock(g_audio->mutex); + + if (!g_audio->init) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (iPersonalStream < 0 || iPersonalStream >= 4 || + (iDevice != CELL_AUDIO_PERSONAL_DEVICE_PRIMARY && (iDevice < 0 || iDevice >= 5))) + { + return CELL_AUDIO_ERROR_PARAM; + } + + // TODO + return CELL_OK; } error_code cellAudioUnsetPersonalDevice(s32 iPersonalStream) { cellAudio.todo("cellAudioUnsetPersonalDevice(iPersonalStream=%d)", iPersonalStream); + + const auto g_audio = g_fxo->get(); + + std::unique_lock lock(g_audio->mutex); + + if (!g_audio->init) + { + return CELL_AUDIO_ERROR_NOT_INIT; + } + + if (iPersonalStream < 0 || iPersonalStream >= 4) + { + return CELL_AUDIO_ERROR_PARAM; + } + + // TODO + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h index 70b00e033b..bff53fa9fc 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -29,23 +29,31 @@ enum CellAudioError : u32 // constants enum { - CELL_AUDIO_BLOCK_16 = 16, CELL_AUDIO_BLOCK_8 = 8, + CELL_AUDIO_BLOCK_16 = 16, + CELL_AUDIO_BLOCK_32 = 32, CELL_AUDIO_BLOCK_SAMPLES = 256, + CELL_AUDIO_CREATEEVENTFLAG_SPU = 0x00000001, - CELL_AUDIO_EVENT_HEADPHONE = 1, + CELL_AUDIO_EVENT_MIX = 0, + CELL_AUDIO_EVENT_HEADPHONE = 1, + CELL_AUDIO_EVENTFLAG_BEFOREMIX = 0x80000000, CELL_AUDIO_EVENTFLAG_DECIMATE_2 = 0x08000000, CELL_AUDIO_EVENTFLAG_DECIMATE_4 = 0x10000000, CELL_AUDIO_EVENTFLAG_HEADPHONE = 0x20000000, CELL_AUDIO_EVENTFLAG_NOMIX = 0x40000000, + CELL_AUDIO_MAX_PORT = 4, CELL_AUDIO_MAX_PORT_2 = 8, + CELL_AUDIO_MISC_ACCVOL_ALLDEVICE = 0x0000ffffUL, CELL_AUDIO_PERSONAL_DEVICE_PRIMARY = 0x8000, + CELL_AUDIO_PORT_2CH = 2, CELL_AUDIO_PORT_8CH = 8, + CELL_AUDIO_PORTATTR_BGM = 0x0000000000000010ULL, CELL_AUDIO_PORTATTR_INITLEVEL = 0x0000000000001000ULL, CELL_AUDIO_PORTATTR_OUT_NO_ROUTE = 0x0000000000100000ULL, @@ -54,6 +62,7 @@ enum CELL_AUDIO_PORTATTR_OUT_PERSONAL_2 = 0x0000000004000000ULL, CELL_AUDIO_PORTATTR_OUT_PERSONAL_3 = 0x0000000008000000ULL, CELL_AUDIO_PORTATTR_OUT_SECONDARY = 0x0000000000000001ULL, + CELL_AUDIO_STATUS_CLOSE = 0x1010, CELL_AUDIO_STATUS_READY = 1, CELL_AUDIO_STATUS_RUN = 2,