SPU2: Downsample reverb input

These filter coefficients come from mednafen, I think they were
originally found by Neill Corlett.

I have not personally verified their accuracy.
This commit is contained in:
Ziemas 2021-02-13 21:00:01 +01:00 committed by refractionpcsx2
parent bbf248fc46
commit 390391e119
4 changed files with 85 additions and 2 deletions

View File

@ -46,6 +46,73 @@ void V_Core::Reverb_AdvanceBuffer()
} }
} }
static constexpr u32 NUM_TAPS = 39;
// 39 tap filter, the 0's could be optimized out
static constexpr std::array<s32, NUM_TAPS> filter_coefs = {
-1,
0,
2,
0,
-10,
0,
35,
0,
-103,
0,
266,
0,
-616,
0,
1332,
0,
-2960,
0,
10246,
16384,
10246,
0,
-2960,
0,
1332,
0,
-616,
0,
266,
0,
-103,
0,
35,
0,
-10,
0,
2,
0,
-1,
};
s32 V_Core::ReverbDownsample(bool right)
{
s32 out = 0;
for (u32 i = 0; i < NUM_TAPS; i++)
{
out += RevbDownBuf[right][((RevbSampleBufPos - NUM_TAPS) + i) & 63] * filter_coefs[i];
}
out >>= 15;
Clampify(out, INT16_MIN, INT16_MAX);
return out;
}
s32 V_Core::ReverbUpsample()
{
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////
StereoOut32 V_Core::DoReverb(const StereoOut32& Input) StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
@ -55,6 +122,11 @@ StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
return StereoOut32::Empty; return StereoOut32::Empty;
} }
RevbSampleBufPos++;
RevbDownBuf[0][RevbSampleBufPos & 63] = Input.Left;
RevbDownBuf[1][RevbSampleBufPos & 63] = Input.Right;
bool R = Cycles & 1; bool R = Cycles & 1;
// Calculate the read/write addresses we'll be needing for this session of reverb. // Calculate the read/write addresses we'll be needing for this session of reverb.
@ -112,7 +184,7 @@ StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
s32 in, same, diff, apf1, apf2, out; s32 in, same, diff, apf1, apf2, out;
#define MUL(x, y) ((x) * (y) >> 15) #define MUL(x, y) ((x) * (y) >> 15)
in = MUL(R ? Revb.IN_COEF_R : Revb.IN_COEF_L, R ? Input.Right : Input.Left); in = MUL(R ? Revb.IN_COEF_R : Revb.IN_COEF_L, ReverbDownsample(R));
same = MUL(Revb.IIR_VOL, in + MUL(Revb.WALL_VOL, _spu2mem[same_src]) - _spu2mem[same_prv]) + _spu2mem[same_prv]; same = MUL(Revb.IIR_VOL, in + MUL(Revb.WALL_VOL, _spu2mem[same_src]) - _spu2mem[same_prv]) + _spu2mem[same_prv];
diff = MUL(Revb.IIR_VOL, in + MUL(Revb.WALL_VOL, _spu2mem[diff_src]) - _spu2mem[diff_prv]) + _spu2mem[diff_prv]; diff = MUL(Revb.IIR_VOL, in + MUL(Revb.WALL_VOL, _spu2mem[diff_src]) - _spu2mem[diff_prv]) + _spu2mem[diff_prv];

View File

@ -416,6 +416,10 @@ struct V_Core
V_Reverb Revb; // Reverb Registers V_Reverb Revb; // Reverb Registers
V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped. V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped.
s32 RevbDownBuf[2][64]; // Downsample buffer for reverb, one for each channel
s32 RevbUpBuf[2][64]; // Upsample buffer for reverb, one for each channel
u32 RevbSampleBufPos;
u32 EffectsStartA; u32 EffectsStartA;
u32 EffectsEndA; u32 EffectsEndA;
u32 ExtEffectsStartA; u32 ExtEffectsStartA;
@ -492,6 +496,9 @@ struct V_Core
StereoOut32 DoReverb(const StereoOut32& Input); StereoOut32 DoReverb(const StereoOut32& Input);
s32 RevbGetIndexer(s32 offset); s32 RevbGetIndexer(s32 offset);
s32 ReverbDownsample(bool right);
s32 ReverbUpsample();
StereoOut32 ReadInput(); StereoOut32 ReadInput();
StereoOut32 ReadInput_HiFi(); StereoOut32 ReadInput_HiFi();

View File

@ -222,6 +222,10 @@ void V_Core::Init(int index)
Regs.ENDX = 0xffffff; // PS2 confirmed Regs.ENDX = 0xffffff; // PS2 confirmed
RevBuffers.NeedsUpdated = true; RevBuffers.NeedsUpdated = true;
RevbSampleBufPos = 0;
memset(RevbDownBuf, 0, sizeof(RevbDownBuf));
memset(RevbUpBuf, 0, sizeof(RevbUpBuf));
UpdateEffectsBufferSize(); UpdateEffectsBufferSize();
} }

View File

@ -24,7 +24,7 @@
// the lower 16 bit value. IF the change is breaking of all compatibility with old // the lower 16 bit value. IF the change is breaking of all compatibility with old
// states, increment the upper 16 bit value, and clear the lower 16 bits to 0. // states, increment the upper 16 bit value, and clear the lower 16 bits to 0.
static const u32 g_SaveVersion = (0x9A1C << 16) | 0x0000; static const u32 g_SaveVersion = (0x9A1D << 16) | 0x0000;
// this function is meant to be used in the place of GSfreeze, and provides a safe layer // this function is meant to be used in the place of GSfreeze, and provides a safe layer
// between the GS saving function and the MTGS's needs. :) // between the GS saving function and the MTGS's needs. :)