mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
bbf248fc46
commit
390391e119
|
@ -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)
|
||||
|
@ -55,6 +122,11 @@ StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
|
|||
return StereoOut32::Empty;
|
||||
}
|
||||
|
||||
RevbSampleBufPos++;
|
||||
|
||||
RevbDownBuf[0][RevbSampleBufPos & 63] = Input.Left;
|
||||
RevbDownBuf[1][RevbSampleBufPos & 63] = Input.Right;
|
||||
|
||||
bool R = Cycles & 1;
|
||||
|
||||
// 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;
|
||||
|
||||
#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];
|
||||
diff = MUL(Revb.IIR_VOL, in + MUL(Revb.WALL_VOL, _spu2mem[diff_src]) - _spu2mem[diff_prv]) + _spu2mem[diff_prv];
|
||||
|
|
|
@ -416,6 +416,10 @@ struct V_Core
|
|||
|
||||
V_Reverb Revb; // Reverb Registers
|
||||
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 EffectsEndA;
|
||||
u32 ExtEffectsStartA;
|
||||
|
@ -492,6 +496,9 @@ struct V_Core
|
|||
StereoOut32 DoReverb(const StereoOut32& Input);
|
||||
s32 RevbGetIndexer(s32 offset);
|
||||
|
||||
s32 ReverbDownsample(bool right);
|
||||
s32 ReverbUpsample();
|
||||
|
||||
StereoOut32 ReadInput();
|
||||
StereoOut32 ReadInput_HiFi();
|
||||
|
||||
|
|
|
@ -222,6 +222,10 @@ void V_Core::Init(int index)
|
|||
Regs.ENDX = 0xffffff; // PS2 confirmed
|
||||
|
||||
RevBuffers.NeedsUpdated = true;
|
||||
RevbSampleBufPos = 0;
|
||||
memset(RevbDownBuf, 0, sizeof(RevbDownBuf));
|
||||
memset(RevbUpBuf, 0, sizeof(RevbUpBuf));
|
||||
|
||||
UpdateEffectsBufferSize();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// 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.
|
||||
|
||||
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
|
||||
// between the GS saving function and the MTGS's needs. :)
|
||||
|
|
Loading…
Reference in New Issue