void CUCode_AXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume, bool upload_auxc) { u16 volume_ramp[96]; GenerateVolumeRamp(volume_ramp, m_last_main_volume, volume, 96); m_last_main_volume = volume; int upload_buffer[3 * 32] = { 0 }; for (u32 i = 0; i < 3 * 32; ++i) upload_buffer[i] = Common::swap32(m_samples_surround[i]); memcpy(HLEMemory_Get_Pointer(surround_addr), upload_buffer, sizeof (upload_buffer)); if (upload_auxc) { surround_addr += sizeof (upload_buffer); for (u32 i = 0; i < 3 * 32; ++i) upload_buffer[i] = Common::swap32(m_samples_auxC_left[i]); memcpy(HLEMemory_Get_Pointer(surround_addr), upload_buffer, sizeof (upload_buffer)); } short buffer[3 * 32 * 2]; // Clamp internal buffers to 16 bits. for (u32 i = 0; i < 3 * 32; ++i) { int left = m_samples_left[i]; int right = m_samples_right[i]; // Apply global volume. Cast to s64 to avoid overflow. left = ((s64)left * volume_ramp[i]) >> 15; right = ((s64)right * volume_ramp[i]) >> 15; if (left < -32767) left = -32767; if (left > 32767) left = 32767; if (right < -32767) right = -32767; if (right > 32767) right = 32767; m_samples_left[i] = left; m_samples_right[i] = right; } for (u32 i = 0; i < 3 * 32; ++i) { buffer[2 * i] = Common::swap16(m_samples_right[i]); buffer[2 * i + 1] = Common::swap16(m_samples_left[i]); } memcpy(HLEMemory_Get_Pointer(lr_addr), buffer, sizeof (buffer)); // There should be a DSP_SYNC message sent here. However, it looks like not // sending it does not cause any issue, and sending it actually causes some // sounds to go at half speed. I have no idea why. }
void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr, u16 volume) { u16 volume_ramp[96]; GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, 96); m_last_aux_volumes[aux_id] = volume; int* buffers[3] = { 0 }; int* main_buffers[3] = { m_samples_left, m_samples_right, m_samples_surround }; switch (aux_id) { case 0: buffers[0] = m_samples_auxA_left; buffers[1] = m_samples_auxA_right; buffers[2] = m_samples_auxA_surround; break; case 1: buffers[0] = m_samples_auxB_left; buffers[1] = m_samples_auxB_right; buffers[2] = m_samples_auxB_surround; break; case 2: buffers[0] = m_samples_auxC_left; buffers[1] = m_samples_auxC_right; buffers[2] = m_samples_auxC_surround; break; } // Send the content of AUX buffers to the CPU if (write_addr) { int* ptr = (int*)HLEMemory_Get_Pointer(write_addr); for (auto& buffer : buffers) for (u32 j = 0; j < 3 * 32; ++j) *ptr++ = Common::swap32(buffer[j]); } // Then read the buffers from the CPU and add to our main buffers. int* ptr = (int*)HLEMemory_Get_Pointer(read_addr); for (auto& main_buffer : main_buffers) for (u32 j = 0; j < 3 * 32; ++j) { s64 sample = (s64)(s32)Common::swap32(*ptr++); sample *= volume_ramp[j]; main_buffer[j] += (s32)(sample >> 15); } }
void AXWiiUCode::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume, bool upload_auxc) { u16 volume_ramp[96]; GenerateVolumeRamp(volume_ramp, m_last_main_volume, volume, ArraySize(volume_ramp)); m_last_main_volume = volume; int upload_buffer[3 * 32] = { 0 }; for (u32 i = 0; i < 3 * 32; ++i) upload_buffer[i] = Common::swap32(m_samples_surround[i]); memcpy(HLEMemory_Get_Pointer(surround_addr), upload_buffer, sizeof(upload_buffer)); if (upload_auxc) { surround_addr += sizeof(upload_buffer); for (u32 i = 0; i < 3 * 32; ++i) upload_buffer[i] = Common::swap32(m_samples_auxC_left[i]); memcpy(HLEMemory_Get_Pointer(surround_addr), upload_buffer, sizeof(upload_buffer)); } short buffer[3 * 32 * 2]; // Clamp internal buffers to 16 bits. for (u32 i = 0; i < 3 * 32; ++i) { int left = m_samples_left[i]; int right = m_samples_right[i]; // Apply global volume. Cast to s64 to avoid overflow. left = ((s64)left * volume_ramp[i]) >> 15; right = ((s64)right * volume_ramp[i]) >> 15; m_samples_left[i] = MathUtil::Clamp(left, -32767, 32767); m_samples_right[i] = MathUtil::Clamp(right, -32767, 32767); } for (u32 i = 0; i < 3 * 32; ++i) { buffer[2 * i] = Common::swap16(m_samples_right[i]); buffer[2 * i + 1] = Common::swap16(m_samples_left[i]); } memcpy(HLEMemory_Get_Pointer(lr_addr), buffer, sizeof(buffer)); m_mail_handler.PushMail(DSP_SYNC, true); }
void CUCode_AXWii::UploadAUXMixLRSC(int aux_id, u32* addresses, u16 volume) { int* aux_left = aux_id ? m_samples_auxB_left : m_samples_auxA_left; int* aux_right = aux_id ? m_samples_auxB_right : m_samples_auxA_right; int* aux_surround = aux_id ? m_samples_auxB_surround : m_samples_auxA_surround; int* auxc_buffer = aux_id ? m_samples_auxC_surround : m_samples_auxC_right; int* upload_ptr = (int*)HLEMemory_Get_Pointer(addresses[0]); for (u32 i = 0; i < 96; ++i) *upload_ptr++ = Common::swap32(aux_left[i]); for (u32 i = 0; i < 96; ++i) *upload_ptr++ = Common::swap32(aux_right[i]); for (u32 i = 0; i < 96; ++i) *upload_ptr++ = Common::swap32(aux_surround[i]); upload_ptr = (int*)HLEMemory_Get_Pointer(addresses[1]); for (u32 i = 0; i < 96; ++i) *upload_ptr++ = Common::swap32(auxc_buffer[i]); u16 volume_ramp[96]; GenerateVolumeRamp(volume_ramp, m_last_aux_volumes[aux_id], volume, 96); m_last_aux_volumes[aux_id] = volume; int* mix_dest[4] = { m_samples_left, m_samples_right, m_samples_surround, m_samples_auxC_left }; for (u32 mix_i = 0; mix_i < 4; ++mix_i) { int* dl_ptr = (int*)HLEMemory_Get_Pointer(addresses[2 + mix_i]); for (u32 i = 0; i < 96; ++i) aux_left[i] = Common::swap32(dl_ptr[i]); for (u32 i = 0; i < 96; ++i) { s64 sample = (s64)(s32)aux_left[i]; sample *= volume_ramp[i]; mix_dest[mix_i][i] += (s32)(sample >> 15); } } }