Skip to content

Commit

Permalink
[SAVEVERSION+] SPU: Revork reverb buffer logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Ziemas authored and refractionpcsx2 committed Sep 21, 2023
1 parent 5c6f72a commit 2a3ba03
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 280 deletions.
8 changes: 0 additions & 8 deletions pcsx2/SPU2/Mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,14 +576,6 @@ StereoOut32 V_Core::Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, c
//
// On the other hand, updating the buffer is cheap and easy, so might as well. ;)

Reverb_AdvanceBuffer(); // Updates the reverb work area as well, if needed.

// ToDo:
// Bad EndA causes memory corruption. Bad for us, unknown on PS2!
// According to no$psx, effects always run but don't always write back, so the FxEnable check may be wrong
if (!FxEnable || EffectsEndA >= 0x100000)
return TD;

StereoOut32 TW;

// Mix Input, Voice, and External data:
Expand Down
16 changes: 8 additions & 8 deletions pcsx2/SPU2/RegTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PVCA(0, 12), PVCA(0, 13), PVCA(0, 14), PVCA(0, 15), PVCA(0, 16), PVCA(0, 17),
PVCA(0, 18), PVCA(0, 19), PVCA(0, 20), PVCA(0, 21), PVCA(0, 22), PVCA(0, 23),

PCORE(0, ExtEffectsStartA) + 1,
PCORE(0, ExtEffectsStartA),
PCORE(0, EffectsStartA) + 1,
PCORE(0, EffectsStartA),

PREVB_REG(0, APF1_SIZE),
PREVB_REG(0, APF2_SIZE),
Expand All @@ -126,8 +126,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PREVB_REG(0, APF2_L_DST),
PREVB_REG(0, APF2_R_DST),

PCORE(0, ExtEffectsEndA) + 1,
PCORE(0, ExtEffectsEndA),
PCORE(0, EffectsEndA) + 1,
PCORE(0, EffectsEndA),

PCORE(0, Regs.ENDX),
PCORE(0, Regs.ENDX) + 1,
Expand Down Expand Up @@ -203,8 +203,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PVCA(1, 12), PVCA(1, 13), PVCA(1, 14), PVCA(1, 15), PVCA(1, 16), PVCA(1, 17),
PVCA(1, 18), PVCA(1, 19), PVCA(1, 20), PVCA(1, 21), PVCA(1, 22), PVCA(1, 23),

PCORE(1, ExtEffectsStartA) + 1,
PCORE(1, ExtEffectsStartA),
PCORE(1, EffectsStartA) + 1,
PCORE(1, EffectsStartA),

PREVB_REG(1, APF1_SIZE),
PREVB_REG(1, APF2_SIZE),
Expand All @@ -229,8 +229,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PREVB_REG(1, APF2_L_DST),
PREVB_REG(1, APF2_R_DST),

PCORE(1, ExtEffectsEndA) + 1,
PCORE(1, ExtEffectsEndA),
PCORE(1, EffectsEndA) + 1,
PCORE(1, EffectsEndA),

PCORE(1, Regs.ENDX),
PCORE(1, Regs.ENDX) + 1,
Expand Down
106 changes: 59 additions & 47 deletions pcsx2/SPU2/Reverb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,42 @@
#include "Global.h"
#include <array>

__forceinline s32 V_Core::RevbGetIndexer(s32 offset)
{
u32 pos = ReverbX + offset;

// Fast and simple single step wrapping, made possible by the preparation of the
// effects buffer addresses.

if (pos > EffectsEndA)
{
pos -= EffectsEndA + 1;
pos += EffectsStartA;
}

assert(pos >= EffectsStartA && pos <= EffectsEndA);
return pos;
}

void V_Core::Reverb_AdvanceBuffer()
void V_Core::AnalyzeReverbPreset()
{
if (RevBuffers.NeedsUpdated)
UpdateEffectsBufferSize();

if ((Cycles & 1) && (EffectsBufferSize > 0))
{
ReverbX += 1;
if (ReverbX >= (u32)EffectsBufferSize)
ReverbX = 0;
}
Console.WriteLn("Reverb Parameter Update for Core %d:", Index);
Console.WriteLn("----------------------------------------------------------");

Console.WriteLn(" IN_COEF_L, IN_COEF_R 0x%08x, 0x%08x", Revb.IN_COEF_L, Revb.IN_COEF_R);
Console.WriteLn(" APF1_SIZE, APF2_SIZE 0x%08x, 0x%08x", Revb.APF1_SIZE, Revb.APF2_SIZE);
Console.WriteLn(" APF1_VOL, APF2_VOL 0x%08x, 0x%08x", Revb.APF1_VOL, Revb.APF2_VOL);

Console.WriteLn(" COMB1_VOL 0x%08x", Revb.COMB1_VOL);
Console.WriteLn(" COMB2_VOL 0x%08x", Revb.COMB2_VOL);
Console.WriteLn(" COMB3_VOL 0x%08x", Revb.COMB3_VOL);
Console.WriteLn(" COMB4_VOL 0x%08x", Revb.COMB4_VOL);

Console.WriteLn(" COMB1_L_SRC, COMB1_R_SRC 0x%08x, 0x%08x", Revb.COMB1_L_SRC, Revb.COMB1_R_SRC);
Console.WriteLn(" COMB2_L_SRC, COMB2_R_SRC 0x%08x, 0x%08x", Revb.COMB2_L_SRC, Revb.COMB2_R_SRC);
Console.WriteLn(" COMB3_L_SRC, COMB3_R_SRC 0x%08x, 0x%08x", Revb.COMB3_L_SRC, Revb.COMB3_R_SRC);
Console.WriteLn(" COMB4_L_SRC, COMB4_R_SRC 0x%08x, 0x%08x", Revb.COMB4_L_SRC, Revb.COMB4_R_SRC);

Console.WriteLn(" SAME_L_SRC, SAME_R_SRC 0x%08x, 0x%08x", Revb.SAME_L_SRC, Revb.SAME_R_SRC);
Console.WriteLn(" DIFF_L_SRC, DIFF_R_SRC 0x%08x, 0x%08x", Revb.DIFF_L_SRC, Revb.DIFF_R_SRC);
Console.WriteLn(" SAME_L_DST, SAME_R_DST 0x%08x, 0x%08x", Revb.SAME_L_DST, Revb.SAME_R_DST);
Console.WriteLn(" DIFF_L_DST, DIFF_R_DST 0x%08x, 0x%08x", Revb.DIFF_L_DST, Revb.DIFF_R_DST);
Console.WriteLn(" IIR_VOL, WALL_VOL 0x%08x, 0x%08x", Revb.IIR_VOL, Revb.WALL_VOL);

Console.WriteLn(" APF1_L_DST 0x%08x", Revb.APF1_L_DST);
Console.WriteLn(" APF1_R_DST 0x%08x", Revb.APF1_R_DST);
Console.WriteLn(" APF2_L_DST 0x%08x", Revb.APF2_L_DST);
Console.WriteLn(" APF2_R_DST 0x%08x", Revb.APF2_R_DST);

Console.WriteLn(" EffectStartA 0x%x", EffectsStartA & 0x3f'ffff);
Console.WriteLn(" EffectsEndA 0x%x", EffectsEndA & 0x3f'ffff);
Console.WriteLn("----------------------------------------------------------");
}



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 = {
Expand Down Expand Up @@ -112,7 +116,6 @@ s32 __forceinline V_Core::ReverbDownsample(bool right)
return out;
}


StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
{
s32 ls = 0, rs = 0;
Expand All @@ -124,7 +127,6 @@ StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
}
else
{

for (u32 i = 0; i < (NUM_TAPS >> 1) + 1; i++)
{
ls += RevbUpBuf[0][(((RevbSampleBufPos - NUM_TAPS) >> 1) + i) & 63] * filter_coefs[i * 2];
Expand All @@ -140,14 +142,24 @@ StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
rs >>= 14;
rs = std::clamp<s32>(rs, INT16_MIN, INT16_MAX);

return StereoOut32(ls, rs);
return {ls, rs};
}

/////////////////////////////////////////////////////////////////////////////////////////
__forceinline s32 V_Core::RevbGetIndexer(s32 offset)
{
u32 start = EffectsStartA & 0x3f'ffff;
u32 end = (EffectsEndA & 0x3f'ffff) | 0xffff;

u32 x = ((Cycles >> 1) + offset) % ((end - start) + 1);

x += start;

return x & 0xf'ffff;
}

StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
{
if (EffectsBufferSize <= 0)
if (EffectsStartA >= EffectsEndA)
{
return StereoOut32::Empty;
}
Expand All @@ -159,23 +171,23 @@ StereoOut32 V_Core::DoReverb(const StereoOut32& Input)

// Calculate the read/write addresses we'll be needing for this session of reverb.

const u32 same_src = RevbGetIndexer(R ? RevBuffers.SAME_R_SRC : RevBuffers.SAME_L_SRC);
const u32 same_dst = RevbGetIndexer(R ? RevBuffers.SAME_R_DST : RevBuffers.SAME_L_DST);
const u32 same_prv = RevbGetIndexer(R ? RevBuffers.SAME_R_PRV : RevBuffers.SAME_L_PRV);
const u32 same_src = RevbGetIndexer(R ? Revb.SAME_R_SRC : Revb.SAME_L_SRC);
const u32 same_dst = RevbGetIndexer(R ? Revb.SAME_R_DST : Revb.SAME_L_DST);
const u32 same_prv = RevbGetIndexer(R ? Revb.SAME_R_DST - 1 : Revb.SAME_L_DST - 1);

const u32 diff_src = RevbGetIndexer(R ? RevBuffers.DIFF_L_SRC : RevBuffers.DIFF_R_SRC);
const u32 diff_dst = RevbGetIndexer(R ? RevBuffers.DIFF_R_DST : RevBuffers.DIFF_L_DST);
const u32 diff_prv = RevbGetIndexer(R ? RevBuffers.DIFF_R_PRV : RevBuffers.DIFF_L_PRV);
const u32 diff_src = RevbGetIndexer(R ? Revb.DIFF_L_SRC : Revb.DIFF_R_SRC);
const u32 diff_dst = RevbGetIndexer(R ? Revb.DIFF_R_DST : Revb.DIFF_L_DST);
const u32 diff_prv = RevbGetIndexer(R ? Revb.DIFF_R_DST - 1 : Revb.DIFF_L_DST - 1);

const u32 comb1_src = RevbGetIndexer(R ? RevBuffers.COMB1_R_SRC : RevBuffers.COMB1_L_SRC);
const u32 comb2_src = RevbGetIndexer(R ? RevBuffers.COMB2_R_SRC : RevBuffers.COMB2_L_SRC);
const u32 comb3_src = RevbGetIndexer(R ? RevBuffers.COMB3_R_SRC : RevBuffers.COMB3_L_SRC);
const u32 comb4_src = RevbGetIndexer(R ? RevBuffers.COMB4_R_SRC : RevBuffers.COMB4_L_SRC);
const u32 comb1_src = RevbGetIndexer(R ? Revb.COMB1_R_SRC : Revb.COMB1_L_SRC);
const u32 comb2_src = RevbGetIndexer(R ? Revb.COMB2_R_SRC : Revb.COMB2_L_SRC);
const u32 comb3_src = RevbGetIndexer(R ? Revb.COMB3_R_SRC : Revb.COMB3_L_SRC);
const u32 comb4_src = RevbGetIndexer(R ? Revb.COMB4_R_SRC : Revb.COMB4_L_SRC);

const u32 apf1_src = RevbGetIndexer(R ? RevBuffers.APF1_R_SRC : RevBuffers.APF1_L_SRC);
const u32 apf1_dst = RevbGetIndexer(R ? RevBuffers.APF1_R_DST : RevBuffers.APF1_L_DST);
const u32 apf2_src = RevbGetIndexer(R ? RevBuffers.APF2_R_SRC : RevBuffers.APF2_L_SRC);
const u32 apf2_dst = RevbGetIndexer(R ? RevBuffers.APF2_R_DST : RevBuffers.APF2_L_DST);
const u32 apf1_src = RevbGetIndexer(R ? (Revb.APF1_R_DST - Revb.APF1_SIZE) : (Revb.APF1_L_DST - Revb.APF1_SIZE));
const u32 apf1_dst = RevbGetIndexer(R ? Revb.APF1_R_DST : Revb.APF1_L_DST);
const u32 apf2_src = RevbGetIndexer(R ? (Revb.APF2_R_DST - Revb.APF2_SIZE) : (Revb.APF2_L_DST - Revb.APF2_SIZE));
const u32 apf2_dst = RevbGetIndexer(R ? Revb.APF2_R_DST : Revb.APF2_L_DST);

// -----------------------------------------
// Optimized IRQ Testing !
Expand Down
51 changes: 0 additions & 51 deletions pcsx2/SPU2/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,44 +279,6 @@ struct V_Reverb
u32 APF2_R_DST;
};

struct V_ReverbBuffers
{
s32 SAME_L_SRC;
s32 SAME_R_SRC;
s32 DIFF_R_SRC;
s32 DIFF_L_SRC;
s32 SAME_L_DST;
s32 SAME_R_DST;
s32 DIFF_L_DST;
s32 DIFF_R_DST;

s32 COMB1_L_SRC;
s32 COMB1_R_SRC;
s32 COMB2_L_SRC;
s32 COMB2_R_SRC;
s32 COMB3_L_SRC;
s32 COMB3_R_SRC;
s32 COMB4_L_SRC;
s32 COMB4_R_SRC;

s32 APF1_L_DST;
s32 APF1_R_DST;
s32 APF2_L_DST;
s32 APF2_R_DST;

s32 SAME_L_PRV;
s32 SAME_R_PRV;
s32 DIFF_L_PRV;
s32 DIFF_R_PRV;

s32 APF1_L_SRC;
s32 APF1_R_SRC;
s32 APF2_L_SRC;
s32 APF2_R_SRC;

bool NeedsUpdated;
};

struct V_SPDIF
{
u16 Out;
Expand Down Expand Up @@ -425,22 +387,12 @@ struct V_Core
u32 InputDataProgress;

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;
u32 ExtEffectsEndA;
u32 ReverbX;

// Current size of and position of the effects buffer. Pre-caculated when the effects start
// or end position registers are written. CAN BE NEGATIVE OR ZERO, in which
// case reverb should be disabled.
s32 EffectsBufferSize;
u32 EffectsBufferStart;

V_CoreRegs Regs; // Registers

Expand Down Expand Up @@ -490,8 +442,6 @@ struct V_Core
void UpdateEffectsBufferSize();
void AnalyzeReverbPreset();

s32 EffectsBufferIndexer(s32 offset) const;

void WriteRegPS1(u32 mem, u16 value);
u16 ReadRegPS1(u32 mem);

Expand All @@ -500,7 +450,6 @@ struct V_Core
// --------------------------------------------------------------------------------------

StereoOut32 Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext);
void Reverb_AdvanceBuffer();
StereoOut32 DoReverb(const StereoOut32& Input);
s32 RevbGetIndexer(s32 offset);

Expand Down
Loading

0 comments on commit 2a3ba03

Please sign in to comment.