diff --git a/src/core/spu.cpp b/src/core/spu.cpp index 57a6e21a2..bb835d797 100644 --- a/src/core/spu.cpp +++ b/src/core/spu.cpp @@ -439,6 +439,14 @@ void SPU::WriteRegister(u32 offset, u16 value) m_transfer_fifo.Clear(); } + if (!new_value.enable && m_SPUCNT.enable) + { + // Mute all voices. + // Interestingly, hardware tests found this seems to happen immediately, not on the next 44100hz cycle. + for (u32 i = 0; i < NUM_VOICES; i++) + m_voices[i].ForceOff(); + } + m_SPUCNT.bits = new_value.bits; m_SPUSTAT.mode = m_SPUCNT.mode.GetValue(); @@ -1047,6 +1055,15 @@ void SPU::Voice::KeyOff() SetADSRPhase(ADSRPhase::Release); } +void SPU::Voice::ForceOff() +{ + if (adsr_phase == ADSRPhase::Off) + return; + + regs.adsr_volume = 0; + SetADSRPhase(ADSRPhase::Off); +} + SPU::ADSRPhase SPU::GetNextADSRPhase(ADSRPhase phase) { switch (phase) @@ -1461,8 +1478,7 @@ std::tuple SPU::SampleVoice(u32 voice_index) { Log_TracePrintf("Voice %u loop end+mute @ 0x%08X", voice_index, ZeroExtend32(voice.current_address)); m_endx_register |= (u32(1) << voice_index); - voice.regs.adsr_volume = 0; - voice.SetADSRPhase(ADSRPhase::Off); + voice.ForceOff(); } else { diff --git a/src/core/spu.h b/src/core/spu.h index d87f3d0d3..777b659fb 100644 --- a/src/core/spu.h +++ b/src/core/spu.h @@ -270,6 +270,7 @@ private: void KeyOn(); void KeyOff(); + void ForceOff(); void DecodeBlock(const ADPCMBlock& block); s16 SampleBlock(s32 index) const;