diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index dff3744fd..b21e5b9fa 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -527,7 +527,18 @@ void CDROM::WriteRegister(u32 offset, u8 value) case 11: { Log_DebugPrintf("Audio volume apply changes <- 0x%02X", value); - m_adpcm_muted = ConvertToBoolUnchecked(value & u8(0x01)); + + const bool adpcm_muted = ConvertToBoolUnchecked(value & u8(0x01)); + if (adpcm_muted != m_adpcm_muted || + (value & 0x20 && std::memcmp(m_cd_audio_volume_matrix.data(), m_next_cd_audio_volume_matrix.data(), + sizeof(m_cd_audio_volume_matrix)) != 0)) + { + if (HasPendingDiscEvent()) + m_drive_event->InvokeEarly(); + g_spu.GeneratePendingSamples(); + } + + m_adpcm_muted = adpcm_muted; if (value & 0x20) m_cd_audio_volume_matrix = m_next_cd_audio_volume_matrix; return; @@ -640,6 +651,11 @@ void CDROM::UpdateInterruptRequest() g_interrupt_controller.InterruptRequest(InterruptController::IRQ::CDROM); } +bool CDROM::HasPendingDiscEvent() const +{ + return (m_drive_event->IsActive() && m_drive_event->GetTicksUntilNextExecution() <= 0); +} + TickCount CDROM::GetAckDelayForCommand(Command command) { if (command == Command::Init) @@ -2072,16 +2088,6 @@ static s16 ZigZagInterpolate(const s16* ringbuf, const s16* table, u8 p) return static_cast(std::clamp(sum, -0x8000, 0x7FFF)); } -static constexpr s32 ApplyVolume(s16 sample, u8 volume) -{ - return s32(sample) * static_cast(ZeroExtend32(volume)) >> 7; -} - -static constexpr s16 SaturateVolume(s32 volume) -{ - return static_cast(std::clamp(volume, -0x8000, 0x7FFF)); -} - template void CDROM::ResampleXAADPCM(const s16* frames_in, u32 num_frames_in) { @@ -2123,12 +2129,7 @@ void CDROM::ResampleXAADPCM(const s16* frames_in, u32 num_frames_in) { const s16 left_interp = ZigZagInterpolate(left_ringbuf, s_zigzag_table[j].data(), p); const s16 right_interp = STEREO ? ZigZagInterpolate(right_ringbuf, s_zigzag_table[j].data(), p) : left_interp; - - const s16 left_out = SaturateVolume(ApplyVolume(left_interp, m_cd_audio_volume_matrix[0][0]) + - ApplyVolume(right_interp, m_cd_audio_volume_matrix[1][0])); - const s16 right_out = SaturateVolume(ApplyVolume(left_interp, m_cd_audio_volume_matrix[0][1]) + - ApplyVolume(right_interp, m_cd_audio_volume_matrix[1][1])); - AddCDAudioFrame(left_out, right_out); + AddCDAudioFrame(left_interp, right_interp); } } } @@ -2333,12 +2334,7 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ& std::memcpy(&samp_left, sector_ptr, sizeof(samp_left)); std::memcpy(&samp_right, sector_ptr + sizeof(s16), sizeof(samp_right)); sector_ptr += sizeof(s16) * 2; - - const s16 left = SaturateVolume(ApplyVolume(samp_left, m_cd_audio_volume_matrix[0][0]) + - ApplyVolume(samp_right, m_cd_audio_volume_matrix[1][0])); - const s16 right = SaturateVolume(ApplyVolume(samp_left, m_cd_audio_volume_matrix[0][1]) + - ApplyVolume(samp_right, m_cd_audio_volume_matrix[1][1])); - AddCDAudioFrame(left, right); + AddCDAudioFrame(samp_left, samp_right); } } diff --git a/src/core/cdrom.h b/src/core/cdrom.h index 2a74d079d..8affe7683 100644 --- a/src/core/cdrom.h +++ b/src/core/cdrom.h @@ -49,7 +49,13 @@ public: ALWAYS_INLINE std::tuple GetAudioFrame() { const u32 frame = m_audio_fifo.IsEmpty() ? 0u : m_audio_fifo.Pop(); - return std::tuple(static_cast(frame), static_cast(frame >> 16)); + const s16 left = static_cast(Truncate16(frame)); + const s16 right = static_cast(Truncate16(frame >> 16)); + const s16 left_out = SaturateVolume(ApplyVolume(left, m_cd_audio_volume_matrix[0][0]) + + ApplyVolume(right, m_cd_audio_volume_matrix[1][0])); + const s16 right_out = SaturateVolume(ApplyVolume(left, m_cd_audio_volume_matrix[0][1]) + + ApplyVolume(right, m_cd_audio_volume_matrix[1][1])); + return std::tuple(left_out, right_out); } private: @@ -230,6 +236,15 @@ private: { m_audio_fifo.Push(ZeroExtend32(static_cast(left)) | (ZeroExtend32(static_cast(right)) << 16)); } + ALWAYS_INLINE static constexpr s32 ApplyVolume(s16 sample, u8 volume) + { + return s32(sample) * static_cast(ZeroExtend32(volume)) >> 7; + } + + ALWAYS_INLINE static constexpr s16 SaturateVolume(s32 volume) + { + return static_cast((volume < -0x8000) ? -0x8000 : ((volume > 0x7FFF) ? 0x7FFF : volume)); + } void SetInterrupt(Interrupt interrupt); void SetAsyncInterrupt(Interrupt interrupt); @@ -240,6 +255,7 @@ private: void SendAsyncErrorResponse(u8 stat_bits = STAT_ERROR, u8 reason = 0x80); void UpdateStatusRegister(); void UpdateInterruptRequest(); + bool HasPendingDiscEvent() const; TickCount GetAckDelayForCommand(Command command); TickCount GetTicksForRead();