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)
|
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];
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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. :)
|
||||||
|
|
Loading…
Reference in New Issue