SPU: Eliminiate conditional in interpolation

This commit is contained in:
Connor McLaughlin 2020-10-17 22:44:57 +10:00
parent e8d77448c7
commit 245edd94d7
2 changed files with 13 additions and 26 deletions

View file

@ -92,7 +92,6 @@ void SPU::Reset()
v.counter.bits = 0; v.counter.bits = 0;
v.current_block_flags.bits = 0; v.current_block_flags.bits = 0;
v.current_block_samples.fill(s16(0)); v.current_block_samples.fill(s16(0));
v.previous_block_last_samples.fill(s16(0));
v.adpcm_last_samples.fill(s32(0)); v.adpcm_last_samples.fill(s32(0));
v.adsr_envelope.Reset(0, false, false); v.adsr_envelope.Reset(0, false, false);
v.adsr_phase = ADSRPhase::Off; v.adsr_phase = ADSRPhase::Off;
@ -151,8 +150,8 @@ bool SPU::DoState(StateWrapper& sw)
sw.DoArray(v.regs.index, NUM_VOICE_REGISTERS); sw.DoArray(v.regs.index, NUM_VOICE_REGISTERS);
sw.Do(&v.counter.bits); sw.Do(&v.counter.bits);
sw.Do(&v.current_block_flags.bits); sw.Do(&v.current_block_flags.bits);
sw.Do(&v.current_block_samples); sw.DoArray(&v.current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK], NUM_SAMPLES_PER_ADPCM_BLOCK);
sw.Do(&v.previous_block_last_samples); sw.DoArray(&v.current_block_samples[0], NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK);
sw.Do(&v.adpcm_last_samples); sw.Do(&v.adpcm_last_samples);
sw.Do(&v.last_volume); sw.Do(&v.last_volume);
sw.DoPOD(&v.left_volume); sw.DoPOD(&v.left_volume);
@ -1313,9 +1312,9 @@ void SPU::Voice::DecodeBlock(const ADPCMBlock& block)
static constexpr std::array<s32, 5> filter_table_neg = {{0, 0, -52, -55, -60}}; static constexpr std::array<s32, 5> filter_table_neg = {{0, 0, -52, -55, -60}};
// store samples needed for interpolation // store samples needed for interpolation
previous_block_last_samples[2] = current_block_samples[NUM_SAMPLES_PER_ADPCM_BLOCK - 1]; current_block_samples[2] = current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + NUM_SAMPLES_PER_ADPCM_BLOCK - 1];
previous_block_last_samples[1] = current_block_samples[NUM_SAMPLES_PER_ADPCM_BLOCK - 2]; current_block_samples[1] = current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + NUM_SAMPLES_PER_ADPCM_BLOCK - 2];
previous_block_last_samples[0] = current_block_samples[NUM_SAMPLES_PER_ADPCM_BLOCK - 3]; current_block_samples[0] = current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + NUM_SAMPLES_PER_ADPCM_BLOCK - 3];
// pre-lookup // pre-lookup
const u8 shift = block.GetShift(); const u8 shift = block.GetShift();
@ -1333,24 +1332,13 @@ void SPU::Voice::DecodeBlock(const ADPCMBlock& block)
sample += (last_samples[1] * filter_neg) >> 6; sample += (last_samples[1] * filter_neg) >> 6;
last_samples[1] = last_samples[0]; last_samples[1] = last_samples[0];
current_block_samples[i] = last_samples[0] = static_cast<s16>(Clamp16(sample)); current_block_samples[NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + i] = last_samples[0] = static_cast<s16>(Clamp16(sample));
} }
std::copy(last_samples, last_samples + countof(last_samples), adpcm_last_samples.begin()); std::copy(last_samples, last_samples + countof(last_samples), adpcm_last_samples.begin());
current_block_flags.bits = block.flags.bits; 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 s32 SPU::Voice::Interpolate() const
{ {
static constexpr std::array<s16, 0x200> gauss = {{ static constexpr std::array<s16, 0x200> gauss = {{
@ -1421,12 +1409,12 @@ s32 SPU::Voice::Interpolate() const
}}; }};
const u8 i = counter.interpolation_index; const u8 i = counter.interpolation_index;
const s32 s = static_cast<s32>(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)); s32 out = s32(gauss[0x0FF - i]) * s32(current_block_samples[s - 3]);
out += s32(gauss[0x1FF - i]) * s32(SampleBlock(s - 2)); out += s32(gauss[0x1FF - i]) * s32(current_block_samples[s - 2]);
out += s32(gauss[0x100 + i]) * s32(SampleBlock(s - 1)); out += s32(gauss[0x100 + i]) * s32(current_block_samples[s - 1]);
out += s32(gauss[0x000 + i]) * s32(SampleBlock(s - 0)); out += s32(gauss[0x000 + i]) * s32(current_block_samples[s - 0]);
return out >> 15; return out >> 15;
} }

View file

@ -55,6 +55,7 @@ private:
static constexpr u32 NUM_VOICE_REGISTERS = 8; static constexpr u32 NUM_VOICE_REGISTERS = 8;
static constexpr u32 VOICE_ADDRESS_SHIFT = 3; static constexpr u32 VOICE_ADDRESS_SHIFT = 3;
static constexpr u32 NUM_SAMPLES_PER_ADPCM_BLOCK = 28; 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 SAMPLE_RATE = 44100;
static constexpr u32 SYSCLK_TICKS_PER_SPU_TICK = System::MASTER_CLOCK / SAMPLE_RATE; // 0x300 static constexpr u32 SYSCLK_TICKS_PER_SPU_TICK = System::MASTER_CLOCK / SAMPLE_RATE; // 0x300
static constexpr s16 ENVELOPE_MIN_VOLUME = 0; static constexpr s16 ENVELOPE_MIN_VOLUME = 0;
@ -243,8 +244,7 @@ private:
VoiceRegisters regs; VoiceRegisters regs;
VoiceCounter counter; VoiceCounter counter;
ADPCMFlags current_block_flags; ADPCMFlags current_block_flags;
std::array<s16, NUM_SAMPLES_PER_ADPCM_BLOCK> current_block_samples; std::array<s16, NUM_SAMPLES_FROM_LAST_ADPCM_BLOCK + NUM_SAMPLES_PER_ADPCM_BLOCK> current_block_samples;
std::array<s16, 3> previous_block_last_samples;
std::array<s16, 2> adpcm_last_samples; std::array<s16, 2> adpcm_last_samples;
s32 last_volume; s32 last_volume;
@ -264,7 +264,6 @@ private:
void ForceOff(); void ForceOff();
void DecodeBlock(const ADPCMBlock& block); void DecodeBlock(const ADPCMBlock& block);
s16 SampleBlock(s32 index) const;
s32 Interpolate() const; s32 Interpolate() const;
// Switches to the specified phase, filling in target. // Switches to the specified phase, filling in target.