From 9e2561d12175c8297cca7e3bf74d32c1d1a1514a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 30 Mar 2014 22:53:43 +0400 Subject: [PATCH] Downmixing/upmixing --- rpcs3/Emu/GS/RSXThread.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 132 ++++++++++++++++------- rpcs3/Emu/SysCalls/Modules/libmixer.cpp | 118 ++++++++++---------- 3 files changed, 155 insertions(+), 97 deletions(-) diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 43ff7272fe..af7402cab9 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -652,7 +652,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 case NV4097_SET_SHADER_PROGRAM: { m_cur_shader_prog = &m_shader_progs[m_cur_shader_prog_num]; - m_cur_shader_prog_num = (m_cur_shader_prog_num + 1) % 16; + //m_cur_shader_prog_num = (m_cur_shader_prog_num + 1) % 16; u32 a0 = ARGS(0); m_cur_shader_prog->offset = a0 & ~0x3; m_cur_shader_prog->addr = GetAddress(m_cur_shader_prog->offset, (a0 & 0x3) - 1); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 73f3d17984..ddd8fb6079 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -53,13 +53,9 @@ int cellAudioInit() m_dump.WriteHeader(); float buffer[2*256]; // intermediate buffer for 2 channels - be_t buffer2[8*256]; // buffer for 8 channels (max count) - //u16 oal_buffer[2*256]; // buffer for OpenAL - memset(buffer, 0, sizeof(buffer)); - memset(buffer2, 0, sizeof(buffer2)); uint oal_buffer_offset = 0; - uint oal_buffer_size = 2 * 256; + uint oal_buffer_size = sizeof(buffer) / sizeof(float); std::unique_ptr oal_buffer[32]; SQueue queue; for (u32 i = 0; i < queue.GetSize(); i++) @@ -68,8 +64,6 @@ int cellAudioInit() memset(oal_buffer[i].get(), 0, oal_buffer_size * sizeof(u16)); } queue.Clear(); - //std::unique_ptr oal_buf(new u16[oal_buffer_size]); - //memset(oal_buffer.get(), 0, oal_buffer_size * sizeof(u16)); Array keys; @@ -141,57 +135,103 @@ int cellAudioInit() AudioPortConfig& port = m_config.m_ports[i]; const u32 block_size = port.channel * 256; + const u32 position = port.tag % port.block; // old value + const u32 buf_addr = m_config.m_buffer + (i * 128 * 1024) + (position * block_size * sizeof(float)); - u32 position = port.tag % port.block; // old value + auto buf = (be_t*)&Memory[buf_addr]; - u32 buf_addr = m_config.m_buffer + (i * 128 * 1024) + (position * block_size * sizeof(float)); - - memcpy(buffer2, Memory + buf_addr, block_size * sizeof(float)); - memset(Memory + buf_addr, 0, block_size * sizeof(float)); - - const u32 k = port.channel / 2; - - if (first_mix) + if (port.channel == 2) { - for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) + if (first_mix) { - // reverse byte order - buffer[i] = buffer2[i*k]; - buffer[i+1] = buffer2[i*k+1]; - // TODO: use port.m_param.level - // TODO: downmix channels that are ignored (?) or implement surround sound + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + { + // reverse byte order + buffer[i] = buf[i]; + // TODO: use port.m_param.level + } + first_mix = false; } - - first_mix = false; - } - else - { - for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) + else { - buffer[i] += buffer2[i*k]; - buffer[i+1] += buffer2[i*k+1]; + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + { + buffer[i] += buf[i]; + } } } + else if (port.channel == 6) + { + if (first_mix) + { + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) + { + const float center = (buf[i*3+2] + buf[i*3+3]) * 0.708f; + buffer[i] = (buf[i*3] + buf[i*3+4] + center) * 0.5f; + buffer[i+1] = (buf[i*3+1] + buf[i*3+5] + center) * 0.5f; + } + first_mix = false; + } + else + { + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) + { + const float center = (buf[i*3+2] + buf[i*3+3]) * 0.708f; + buffer[i] += (buf[i*3] + buf[i*3+4] + center) * 0.5f; + buffer[i+1] += (buf[i*3+1] + buf[i*3+5] + center) * 0.5f; + } + } + } + else if (port.channel == 8) + { + if (first_mix) + { + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) + { + const float center = (buf[i*4+2] + buf[i*4+3]) * 0.708f; + buffer[i] = (buf[i*4] + buf[i*4+4] + buf[i*4+6] + center) * 0.5f; + buffer[i+1] = (buf[i*4+1] + buf[i*4+5] + buf[i*4+7] + center) * 0.5f; + } + first_mix = false; + } + else + { + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) + { + const float center = (buf[i*4+2] + buf[i*4+3]) * 0.708f; + buffer[i] += (buf[i*4] + buf[i*4+4] + buf[i*4+6] + center) * 0.5f; + buffer[i+1] += (buf[i*4+1] + buf[i*4+5] + buf[i*4+7] + center) * 0.5f; + } + } + } + + memset(buf, 0, block_size * sizeof(float)); } // convert the data from float to u16 and clip: - for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + if (!first_mix) { - oal_buffer[oal_pos][oal_buffer_offset + i] = (s16)(min(max(buffer[i] * 0x8000, -0x8000), 0x7fff)); + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + { + oal_buffer[oal_pos][oal_buffer_offset + i] = (s16)(min(max(buffer[i] * 0x8000, -0x8000), 0x7fff)); + } } const u64 stamp1 = get_system_time(); - oal_buffer_offset += sizeof(buffer) / sizeof(float); - - if(oal_buffer_offset >= oal_buffer_size) + if (!first_mix) { - if(m_audio_out) - { - queue.Push(&oal_buffer[oal_pos][0]); - } + oal_buffer_offset += sizeof(buffer) / sizeof(float); - oal_buffer_offset = 0; + if(oal_buffer_offset >= oal_buffer_size) + { + if(m_audio_out) + { + queue.Push(&oal_buffer[oal_pos][0]); + } + + oal_buffer_offset = 0; + } } const u64 stamp2 = get_system_time(); @@ -224,7 +264,7 @@ int cellAudioInit() const u64 stamp3 = get_system_time(); - if(do_dump) + if (do_dump && !first_mix) { if (m_dump.WriteData(&buffer, sizeof(buffer)) != sizeof(buffer)) // write file data { @@ -247,6 +287,15 @@ abort: m_config.m_is_audio_initialized = false; + m_config.m_keys.Clear(); + for (u32 i = 0; i < m_config.AUDIO_PORT_COUNT; i++) + { + AudioPortConfig& port = m_config.m_ports[i]; + port.m_is_audio_port_opened = false; + port.m_is_audio_port_started = false; + } + m_config.m_port_in_use = 0; + while (!internal_finished) { Sleep(1); @@ -418,6 +467,7 @@ int cellAudioPortClose(u32 portNum) } m_config.m_ports[portNum].m_is_audio_port_started = false; + m_config.m_ports[portNum].m_is_audio_port_opened = false; m_config.m_port_in_use--; return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp index d74d6b2bbf..10b8037b59 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp @@ -13,8 +13,7 @@ CellSurMixerConfig surMixer; u32 surMixerCb = 0; u32 surMixerCbArg = 0; SMutex mixer_mutex; -bool mixfirst; -float mixdata[2*256]; +float mixdata[8*256]; u64 mixcount = 0; int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 samples) @@ -28,11 +27,11 @@ int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 sampl case 2: if (port >= surMixer.chStrips2) ch = 0; break; case 6: - if (port >= surMixer.chStrips6) ch = 0; break; + /*if (port >= surMixer.chStrips6)*/ ch = 0; break; case 8: if (port >= surMixer.chStrips8) ch = 0; break; default: - ch = 0; + ch = 0; break; } if (aan_handle == 0x11111111 && samples == 256 && ch && offset == 0) @@ -50,24 +49,52 @@ int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, u32 addr, u32 sampl SMutexLocker lock(mixer_mutex); - const u32 k = ch / 2; - - if (mixfirst) + if (ch == 1) { - for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i += 2) + // mono upmixing + for (u32 i = 0; i < samples; i++) { - // reverse byte order and mix - mixdata[i] = *(be_t*)&Memory[addr + i * k * sizeof(float)]; - mixdata[i + 1] = *(be_t*)&Memory[addr + (i * k + 1) * sizeof(float)]; - } - mixfirst = false; + const float center = *(be_t*)&Memory[addr + i * sizeof(float)]; + mixdata[i*8+0] += center * 2; + mixdata[i*8+1] += center * 2; + } } - else + else if (ch == 2) { - for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i += 2) + // stereo upmixing + for (u32 i = 0; i < samples; i++) { - mixdata[i] += *(be_t*)&Memory[addr + i * k * sizeof(float)]; - mixdata[i + 1] += *(be_t*)&Memory[addr + (i * k + 1) * sizeof(float)]; + const float left = *(be_t*)&Memory[addr + i * 2 * sizeof(float)]; + const float right = *(be_t*)&Memory[addr + (i * 2 + 1) * sizeof(float)]; + mixdata[i*8+0] += left * 2; + mixdata[i*8+1] += right * 2; + } + } + else if (ch == 6) + { + // 5.1 upmixing + for (u32 i = 0; i < samples; i++) + { + const float left = *(be_t*)&Memory[addr + i * 6 * sizeof(float)]; + const float right = *(be_t*)&Memory[addr + (i * 6 + 1) * sizeof(float)]; + const float center = *(be_t*)&Memory[addr + (i * 6 + 2) * sizeof(float)]; + const float low_freq = *(be_t*)&Memory[addr + (i * 6 + 3) * sizeof(float)]; + const float rear_left = *(be_t*)&Memory[addr + (i * 6 + 4) * sizeof(float)]; + const float rear_right = *(be_t*)&Memory[addr + (i * 6 + 5) * sizeof(float)]; + mixdata[i*8+0] += left; + mixdata[i*8+1] += right; + mixdata[i*8+2] += center; + mixdata[i*8+3] += low_freq; + mixdata[i*8+4] += rear_left; + mixdata[i*8+5] += rear_right; + } + } + else if (ch == 8) + { + // 7.1 + for (u32 i = 0; i < samples * 8; i++) + { + mixdata[i] += *(be_t*)&Memory[addr + i * sizeof(float)]; } } @@ -180,7 +207,7 @@ int cellSurMixerStart() return CELL_LIBMIXER_ERROR_FULL; } - port.channel = 2; + port.channel = 8; port.block = 16; port.attr = 0; port.level = 1.0f; @@ -218,24 +245,17 @@ int cellSurMixerStart() u64 stamp0 = get_system_time(); - mixfirst = true; + memset(mixdata, 0, sizeof(mixdata)); mixerCb->ExecAsCallback(surMixerCb, true, surMixerCbArg, mixcount, 256); u64 stamp1 = get_system_time(); - auto buf = (be_t*)&Memory[m_config.m_buffer + (128 * 1024 * SUR_PORT) + (mixcount % 16) * 2 * 256 * sizeof(float)]; + auto buf = (be_t*)&Memory[m_config.m_buffer + (128 * 1024 * SUR_PORT) + (mixcount % port.block) * port.channel * 256 * sizeof(float)]; - if (!mixfirst) + for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++) { - for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++) - { - // reverse byte order - buf[i] = mixdata[i]; - } - } - else - { - // no data? + // reverse byte order + buf[i] = mixdata[i]; } u64 stamp2 = get_system_time(); @@ -255,7 +275,7 @@ int cellSurMixerStart() int cellSurMixerSetParameter(u32 param, float value) { - libmixer.Warning("cellSurMixerSetParameter(param=0x%x, value=%f)", param, value); + libmixer.Error("cellSurMixerSetParameter(param=0x%x, value=%f)", param, value); return CELL_OK; } @@ -265,9 +285,12 @@ int cellSurMixerFinalize() AudioPortConfig& port = m_config.m_ports[SUR_PORT]; - port.m_is_audio_port_started = false; - port.m_is_audio_port_opened = false; - m_config.m_port_in_use--; + if (port.m_is_audio_port_opened) + { + port.m_is_audio_port_started = false; + port.m_is_audio_port_opened = false; + m_config.m_port_in_use--; + } return CELL_OK; } @@ -284,29 +307,14 @@ int cellSurMixerSurBusAddData(u32 busNo, u32 offset, u32 addr, u32 samples) Emu.Pause(); return CELL_OK; } - - if (busNo > 1) // channels from 3 to 8 ignored (TODO) - { - return CELL_OK; - } SMutexLocker lock(mixer_mutex); - if (mixfirst) + for (u32 i = 0; i < samples; i++) { - for (u32 i = 0; i < samples; i++) - { - // reverse byte order and mix - mixdata[i * 2 + busNo] = *(be_t*)&Memory[addr + i * sizeof(float)]; - } - mixfirst = false; - } - else - { - for (u32 i = 0; i < samples; i++) - { - mixdata[i * 2 + busNo] += *(be_t*)&Memory[addr + i * sizeof(float)]; - } + // reverse byte order and mix + u32 v = Memory.Read32(addr + i * sizeof(float)); + mixdata[i*8+busNo] += (float&)v; } return CELL_OK; @@ -685,7 +693,7 @@ void libmixer_init() libmixer.AddFuncSub("surmx___", cellSurMixerFinalize_table, "cellSurMixerFinalize", cellSurMixerFinalize); static const u64 cellSurMixerSurBusAddData_table[] = { - // first instruction ignored + 0xff00000081428250, 0xffffffff7c0802a6, 0xfffffffff821ff91, 0xfffffffff8010080, @@ -716,7 +724,7 @@ void libmixer_init() libmixer.AddFuncSub("surmx___", cellSurMixerSurBusAddData_table, "cellSurMixerSurBusAddData", cellSurMixerSurBusAddData); static const u64 cellSurMixerChStripSetParameter_table[] = { - // first instruction ignored + 0xff00000081028250, 0xffffffff7c6b1b78, 0xffffffff3c608031, 0xffffffff7c8a2378,