SPU2-X: Reverted back to the last version of the reverb engine before the rewrite plus some backwards lerp fixes (accident in optimisation in r2089). Thanks to gigaherz (I guess? This is mostly your fault.)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4762 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
sudonim1@gmail.com 2011-06-24 23:55:19 +00:00
parent 297843ddaf
commit 373c2cd47f
2 changed files with 34 additions and 68 deletions

View File

@ -26,7 +26,7 @@
__forceinline s32 V_Core::RevbGetIndexer( s32 offset )
{
u32 pos = ReverbX + offset; // Apparently some reverb presets use offsets outside of the ps2 memory ...
u32 pos = ReverbX + offset;
// Fast and simple single step wrapping, made possible by the preparation of the
// effects buffer addresses.
@ -177,99 +177,65 @@ StereoOut32 V_Core::DoReverb( const StereoOut32& Input )
INPUT_SAMPLE.Right += (downbuf[(dbpos+x)&7].Right * downcoeffs[x]);
}
// This is gotta be a Schroeder Reverberator:
// http://cnx.org/content/m15491/latest/
//////////////////////////////////////////////////////////////
// Part 1: Input filter block (FIR filter)
// Purpose: Filter and write data to the sample queues for the echos below
INPUT_SAMPLE.Left >>= 16;
INPUT_SAMPLE.Right >>= 16;
s32 input_L = (INPUT_SAMPLE.Left * Revb.IN_COEF_L);
s32 input_R = (INPUT_SAMPLE.Right * Revb.IN_COEF_R);
const s32 IIR_A0 = (_spu2mem[src_a0] * Revb.IIR_COEF) + input_L;
const s32 IIR_A1 = (_spu2mem[src_a1] * Revb.IIR_COEF) + input_R;
const s32 IIR_B0 = (_spu2mem[src_b0] * Revb.IIR_COEF) + input_L;
const s32 IIR_B1 = (_spu2mem[src_b1] * Revb.IIR_COEF) + input_R;
const s32 IIR_INPUT_A0 = ((_spu2mem[src_a0] * Revb.IIR_COEF) + input_L)>>16;
const s32 IIR_INPUT_A1 = ((_spu2mem[src_a1] * Revb.IIR_COEF) + input_L)>>16;
const s32 IIR_INPUT_B0 = ((_spu2mem[src_b0] * Revb.IIR_COEF) + input_R)>>16;
const s32 IIR_INPUT_B1 = ((_spu2mem[src_b1] * Revb.IIR_COEF) + input_R)>>16;
const s32 IIR_C0 = _spu2mem[dest_a0]* Revb.IIR_ALPHA;
const s32 IIR_C1 = _spu2mem[dest_a1]* Revb.IIR_ALPHA;
const s32 IIR_D0 = _spu2mem[dest_b0]* Revb.IIR_ALPHA;
const s32 IIR_D1 = _spu2mem[dest_b1]* Revb.IIR_ALPHA;
const s32 src_dest_a0 = _spu2mem[dest_a0];
const s32 src_dest_a1 = _spu2mem[dest_a1];
const s32 src_dest_b0 = _spu2mem[dest_b0];
const s32 src_dest_b1 = _spu2mem[dest_b1];
_spu2mem[dest2_a0] = clamp_mix( (IIR_A0-IIR_C0) >> 16 );
_spu2mem[dest2_a1] = clamp_mix( (IIR_A1-IIR_C1) >> 16 );
_spu2mem[dest2_b0] = clamp_mix( (IIR_B0-IIR_D0) >> 16 );
_spu2mem[dest2_b1] = clamp_mix( (IIR_B1-IIR_D1) >> 16 );
// This section differs from Neill's doc as it uses single-mul interpolation instead
// of 0x8000-val inversion. (same result, faster)
const s32 IIR_A0 = src_dest_a0 + (((IIR_INPUT_A0 - src_dest_a0) * Revb.IIR_ALPHA)>>16);
const s32 IIR_A1 = src_dest_a1 + (((IIR_INPUT_A1 - src_dest_a1) * Revb.IIR_ALPHA)>>16);
const s32 IIR_B0 = src_dest_b0 + (((IIR_INPUT_B0 - src_dest_b0) * Revb.IIR_ALPHA)>>16);
const s32 IIR_B1 = src_dest_b1 + (((IIR_INPUT_B1 - src_dest_b1) * Revb.IIR_ALPHA)>>16);
_spu2mem[dest2_a0] = clamp_mix( IIR_A0 );
_spu2mem[dest2_a1] = clamp_mix( IIR_A1 );
_spu2mem[dest2_b0] = clamp_mix( IIR_B0 );
_spu2mem[dest2_b1] = clamp_mix( IIR_B1 );
//////////////////////////////////////////////////////////////
// Part 2: Comb filters (echos)
// Purpose: Create the primary reflections on the virtual walls
s32 ACC0 = (
const s32 ACC0 = (
((_spu2mem[acc_src_a0] * Revb.ACC_COEF_A)) +
((_spu2mem[acc_src_b0] * Revb.ACC_COEF_B)) +
((_spu2mem[acc_src_c0] * Revb.ACC_COEF_C)) +
((_spu2mem[acc_src_d0] * Revb.ACC_COEF_D))
); // >> 16;
s32 ACC1 = (
const s32 ACC1 = (
((_spu2mem[acc_src_a1] * Revb.ACC_COEF_A)) +
((_spu2mem[acc_src_b1] * Revb.ACC_COEF_B)) +
((_spu2mem[acc_src_c1] * Revb.ACC_COEF_C)) +
((_spu2mem[acc_src_d1] * Revb.ACC_COEF_D))
); // >> 16;
// The following code differs from Neill's doc as it uses the more natural single-mul
// interpolative, instead of the funky ^0x8000 stuff. (better result, faster)
//////////////////////////////////////////////////////////////
// Part 3: All-pass filters
// Purpose: Create actual reverberation sound effect
const s32 FB_A0 = _spu2mem[fb_src_a0];
const s32 FB_A1 = _spu2mem[fb_src_a1];
// First
_spu2mem[mix_dest_a0] = clamp_mix( (ACC0 - FB_A0 * Revb.FB_ALPHA) >> 16 );
_spu2mem[mix_dest_a1] = clamp_mix( (ACC1 - FB_A1 * Revb.FB_ALPHA) >> 16 );
// Take delayed input
s32 FB_A0 = _spu2mem[fb_src_a0]; // 16
s32 FB_A1 = _spu2mem[fb_src_a1];
const s32 acc_fb_mix_a = (FB_A0<<16) + ( ((ACC0>>16) - FB_A0) * Revb.FB_ALPHA );
const s32 acc_fb_mix_b = (FB_A0<<16) + ( ((ACC1>>16) - FB_A0) * Revb.FB_ALPHA );
// Apply gain and add to input
s32 MIX_A0 = (ACC0 + FB_A0 * Revb.FB_ALPHA)>>16; // 32 + 16*16 = 32
s32 MIX_A1 = (ACC1 + FB_A1 * Revb.FB_ALPHA)>>16;
// Write to queue
_spu2mem[mix_dest_a0] = clamp_mix(MIX_A0);
_spu2mem[mix_dest_a1] = clamp_mix(MIX_A1);
// Apply second gain and add
ACC0 += (FB_A0 << 16) - MIX_A0 * Revb.FB_ALPHA;
ACC1 += (FB_A1 << 16) - MIX_A1 * Revb.FB_ALPHA;
//////////////////////////////////////////////////////////////
// Second
// Take delayed input
s32 FB_B0 = _spu2mem[fb_src_b0]; // 16
s32 FB_B1 = _spu2mem[fb_src_b1];
// Apply gain and add to input
s32 MIX_B0 = (ACC0 + FB_B0 * Revb.FB_X)>>16; // 32 + 16*16 = 32
s32 MIX_B1 = (ACC1 + FB_B1 * Revb.FB_X)>>16;
// Write to queue
_spu2mem[mix_dest_b0] = clamp_mix(MIX_B0);
_spu2mem[mix_dest_b1] = clamp_mix(MIX_B1);
// Apply second gain and add
ACC0 += (FB_B0 << 16) - MIX_B0 * Revb.FB_X;
ACC1 += (FB_B1 << 16) - MIX_B1 * Revb.FB_X;
_spu2mem[mix_dest_b0] = clamp_mix( ( acc_fb_mix_a - (_spu2mem[fb_src_b0] * Revb.FB_X) ) >> 16 );
_spu2mem[mix_dest_b1] = clamp_mix( ( acc_fb_mix_b - (_spu2mem[fb_src_b1] * Revb.FB_X) ) >> 16 );
upbuf[ubpos] = clamp_mix( StereoOut32(
ACC0>>16, // left
ACC1>>16 // right
(_spu2mem[mix_dest_a0] + _spu2mem[mix_dest_b0]), // left
(_spu2mem[mix_dest_a1] + _spu2mem[mix_dest_b1]) // right
) );
}

View File

@ -227,7 +227,7 @@ s32 V_Core::EffectsBufferIndexer( s32 offset ) const
// already x4'd. It doesn't really make sense that we should x4 them again, and this
// seems to work. (feedback-free in bios and DDS) --air
u32 pos = EffectsStartA + offset & 0xFFFFF;
u32 pos = EffectsStartA + offset;
// Need to use modulus here, because games can and will drop the buffer size
// without notice, and it leads to offsets several times past the end of the buffer.