From 245edd94d78c995f84509eaa19d8d5d29f22b239 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 17 Oct 2020 22:44:57 +1000 Subject: [PATCH] SPU: Eliminiate conditional in interpolation --- src/core/spu.cpp | 34 +++++++++++----------------------- src/core/spu.h | 5 ++--- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/core/spu.cpp b/src/core/spu.cpp index 0272144bc..2b496f15c 100644 --- a/src/core/spu.cpp +++ b/src/core/spu.cpp @@ -92,7 +92,6 @@ void SPU::Reset() v.counter.bits = 0; v.current_block_flags.bits = 0; v.current_block_samples.fill(s16(0)); - v.previous_block_last_samples.fill(s16(0)); v.adpcm_last_samples.fill(s32(0)); v.adsr_envelope.Reset(0, false, false); v.adsr_phase = ADSRPhase::Off; @@ -151,8 +150,8 @@ bool SPU::DoState(StateWrapper& sw) sw.DoArray(v.regs.index, NUM_VOICE_REGISTERS); sw.Do(&v.counter.bits); sw.Do(&v.current_block_flags.bits); - sw.Do(&v.current_block_samples); - sw.Do(&v.previous_block_last_samples); + sw.DoArray(&v.current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK], NUM_SAMPLES_PER_ADPCM_BLOCK); + sw.DoArray(&v.current_block_samples[0], NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK); sw.Do(&v.adpcm_last_samples); sw.Do(&v.last_volume); sw.DoPOD(&v.left_volume); @@ -1313,9 +1312,9 @@ void SPU::Voice::DecodeBlock(const ADPCMBlock& block) static constexpr std::array filter_table_neg = {{0, 0, -52, -55, -60}}; // store samples needed for interpolation - previous_block_last_samples[2] = current_block_samples[NUM_SAMPLES_PER_ADPCM_BLOCK - 1]; - previous_block_last_samples[1] = current_block_samples[NUM_SAMPLES_PER_ADPCM_BLOCK - 2]; - previous_block_last_samples[0] = current_block_samples[NUM_SAMPLES_PER_ADPCM_BLOCK - 3]; + current_block_samples[2] = current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + NUM_SAMPLES_PER_ADPCM_BLOCK - 1]; + current_block_samples[1] = current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + NUM_SAMPLES_PER_ADPCM_BLOCK - 2]; + current_block_samples[0] = current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + NUM_SAMPLES_PER_ADPCM_BLOCK - 3]; // pre-lookup const u8 shift = block.GetShift(); @@ -1333,24 +1332,13 @@ void SPU::Voice::DecodeBlock(const ADPCMBlock& block) sample += (last_samples[1] * filter_neg) >> 6; last_samples[1] = last_samples[0]; - current_block_samples[i] = last_samples[0] = static_cast(Clamp16(sample)); + current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + i] = last_samples[0] = static_cast(Clamp16(sample)); } std::copy(last_samples, last_samples + countof(last_samples), adpcm_last_samples.begin()); current_block_flags.bits = block.flags.bits; } -s16 SPU::Voice::SampleBlock(s32 index) const -{ - if (index < 0) - { - DebugAssert(index >= -3); - return previous_block_last_samples[index + 3]; - } - - return current_block_samples[index]; -} - s32 SPU::Voice::Interpolate() const { static constexpr std::array gauss = {{ @@ -1421,12 +1409,12 @@ s32 SPU::Voice::Interpolate() const }}; const u8 i = counter.interpolation_index; - const s32 s = static_cast(ZeroExtend32(counter.sample_index.GetValue())); + const u32 s = NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + ZeroExtend32(counter.sample_index.GetValue()); - s32 out = s32(gauss[0x0FF - i]) * s32(SampleBlock(s - 3)); - out += s32(gauss[0x1FF - i]) * s32(SampleBlock(s - 2)); - out += s32(gauss[0x100 + i]) * s32(SampleBlock(s - 1)); - out += s32(gauss[0x000 + i]) * s32(SampleBlock(s - 0)); + s32 out = s32(gauss[0x0FF - i]) * s32(current_block_samples[s - 3]); + out += s32(gauss[0x1FF - i]) * s32(current_block_samples[s - 2]); + out += s32(gauss[0x100 + i]) * s32(current_block_samples[s - 1]); + out += s32(gauss[0x000 + i]) * s32(current_block_samples[s - 0]); return out >> 15; } diff --git a/src/core/spu.h b/src/core/spu.h index 2b88c1062..b3c08b9cb 100644 --- a/src/core/spu.h +++ b/src/core/spu.h @@ -55,6 +55,7 @@ private: static constexpr u32 NUM_VOICE_REGISTERS = 8; static constexpr u32 VOICE_ADDRESS_SHIFT = 3; static constexpr u32 NUM_SAMPLES_PER_ADPCM_BLOCK = 28; + static constexpr u32 NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK = 3; static constexpr u32 SAMPLE_RATE = 44100; static constexpr u32 SYSCLK_TICKS_PER_SPU_TICK = System::MASTER_CLOCK / SAMPLE_RATE; // 0x300 static constexpr s16 ENVELOPE_MIN_VOLUME = 0; @@ -243,8 +244,7 @@ private: VoiceRegisters regs; VoiceCounter counter; ADPCMFlags current_block_flags; - std::array current_block_samples; - std::array previous_block_last_samples; + std::array current_block_samples; std::array adpcm_last_samples; s32 last_volume; @@ -264,7 +264,6 @@ private: void ForceOff(); void DecodeBlock(const ADPCMBlock& block); - s16 SampleBlock(s32 index) const; s32 Interpolate() const; // Switches to the specified phase, filling in target.