SPU: Run muted voices when IRQ is enabled

Fixes SPU timeout in Casper. We can still optimize for most games where
interrupts are not used by completely ignoring muted voices in those.
This commit is contained in:
Connor McLaughlin 2020-03-27 01:42:43 +10:00
parent 54abd37daa
commit 08ad5aad53
1 changed files with 21 additions and 11 deletions

View File

@ -1225,7 +1225,7 @@ void SPU::ReadADPCMBlock(u16 address, ADPCMBlock* block)
std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
{
Voice& voice = m_voices[voice_index];
if (!voice.IsOn())
if (!voice.IsOn() && !m_SPUCNT.irq9_enable)
{
voice.last_volume = 0;
return {};
@ -1245,18 +1245,28 @@ std::tuple<s32, s32> SPU::SampleVoice(u32 voice_index)
}
}
// interpolate/sample and apply ADSR volume
s16 sample;
if (IsVoiceNoiseEnabled(voice_index))
sample = GetVoiceNoiseLevel();
else
sample = voice.Interpolate();
// skip interpolation when the volume is muted anyway
s32 volume;
if (voice.regs.adsr_volume != 0)
{
// interpolate/sample and apply ADSR volume
s16 sample;
if (IsVoiceNoiseEnabled(voice_index))
sample = GetVoiceNoiseLevel();
else
sample = voice.Interpolate();
volume = ApplyVolume(sample, voice.regs.adsr_volume);
}
else
{
volume = 0;
}
const s32 volume = ApplyVolume(sample, voice.regs.adsr_volume);
// if (voice_index == 3 || voice_index == 4)
// Log_WarningPrintf("voice %u %d", voice_index, volume);
voice.last_volume = volume;
voice.TickADSR();
if (voice.adsr_phase != ADSRPhase::Off)
voice.TickADSR();
// Pitch modulation
u16 step = voice.regs.adpcm_sample_rate;