spu: rework reverb according to nocash docs
authornotaz <notasas@gmail.com>
Mon, 20 Jan 2025 23:12:35 +0000 (01:12 +0200)
committernotaz <notasas@gmail.com>
Wed, 22 Jan 2025 02:36:09 +0000 (04:36 +0200)
rpi4 performs about the same

plugins/dfsound/externals.h
plugins/dfsound/registers.c
plugins/dfsound/reverb.c

index 6dbbac6..6fdef9d 100644 (file)
@@ -128,43 +128,45 @@ typedef struct
  int VolLeft;\r
  int VolRight;\r
 \r
- int FB_SRC_A;       // (offset)\r
- int FB_SRC_B;       // (offset)\r
- int IIR_ALPHA;      // (coef.)\r
- int ACC_COEF_A;     // (coef.)\r
- int ACC_COEF_B;     // (coef.)\r
- int ACC_COEF_C;     // (coef.)\r
- int ACC_COEF_D;     // (coef.)\r
- int IIR_COEF;       // (coef.)\r
- int FB_ALPHA;       // (coef.)\r
- int FB_X;           // (coef.)\r
- int IIR_DEST_A0;    // (offset)\r
- int IIR_DEST_A1;    // (offset)\r
- int ACC_SRC_A0;     // (offset)\r
- int ACC_SRC_A1;     // (offset)\r
- int ACC_SRC_B0;     // (offset)\r
- int ACC_SRC_B1;     // (offset)\r
- int IIR_SRC_A0;     // (offset)\r
- int IIR_SRC_A1;     // (offset)\r
- int IIR_DEST_B0;    // (offset)\r
- int IIR_DEST_B1;    // (offset)\r
- int ACC_SRC_C0;     // (offset)\r
- int ACC_SRC_C1;     // (offset)\r
- int ACC_SRC_D0;     // (offset)\r
- int ACC_SRC_D1;     // (offset)\r
- int IIR_SRC_B1;     // (offset)\r
- int IIR_SRC_B0;     // (offset)\r
- int MIX_DEST_A0;    // (offset)\r
- int MIX_DEST_A1;    // (offset)\r
- int MIX_DEST_B0;    // (offset)\r
- int MIX_DEST_B1;    // (offset)\r
- int IN_COEF_L;      // (coef.)\r
- int IN_COEF_R;      // (coef.)\r
-\r
- int dirty;          // registers changed\r
-\r
- // MIX_DEST_xx - FB_SRC_x\r
- int FB_SRC_A0, FB_SRC_A1, FB_SRC_B0, FB_SRC_B1;\r
+ // directly from nocash docs\r
+ //int dAPF1; // 1DC0 disp    Reverb APF Offset 1\r
+ //int dAPF2; // 1DC2 disp    Reverb APF Offset 2\r
+ int vIIR;    // 1DC4 volume  Reverb Reflection Volume 1\r
+ int vCOMB1;  // 1DC6 volume  Reverb Comb Volume 1\r
+ int vCOMB2;  // 1DC8 volume  Reverb Comb Volume 2\r
+ int vCOMB3;  // 1DCA volume  Reverb Comb Volume 3\r
+ int vCOMB4;  // 1DCC volume  Reverb Comb Volume 4\r
+ int vWALL;   // 1DCE volume  Reverb Reflection Volume 2\r
+ int vAPF1;   // 1DD0 volume  Reverb APF Volume 1\r
+ int vAPF2;   // 1DD2 volume  Reverb APF Volume 2\r
+ int mLSAME;  // 1DD4 src/dst Reverb Same Side Reflection Address 1 Left\r
+ int mRSAME;  // 1DD6 src/dst Reverb Same Side Reflection Address 1 Right\r
+ int mLCOMB1; // 1DD8 src     Reverb Comb Address 1 Left\r
+ int mRCOMB1; // 1DDA src     Reverb Comb Address 1 Right\r
+ int mLCOMB2; // 1DDC src     Reverb Comb Address 2 Left\r
+ int mRCOMB2; // 1DDE src     Reverb Comb Address 2 Right\r
+ int dLSAME;  // 1DE0 src     Reverb Same Side Reflection Address 2 Left\r
+ int dRSAME;  // 1DE2 src     Reverb Same Side Reflection Address 2 Right\r
+ int mLDIFF;  // 1DE4 src/dst Reverb Different Side Reflect Address 1 Left\r
+ int mRDIFF;  // 1DE6 src/dst Reverb Different Side Reflect Address 1 Right\r
+ int mLCOMB3; // 1DE8 src     Reverb Comb Address 3 Left\r
+ int mRCOMB3; // 1DEA src     Reverb Comb Address 3 Right\r
+ int mLCOMB4; // 1DEC src     Reverb Comb Address 4 Left\r
+ int mRCOMB4; // 1DEE src     Reverb Comb Address 4 Right\r
+ int dLDIFF;  // 1DF0 src     Reverb Different Side Reflect Address 2 Left\r
+ int dRDIFF;  // 1DF2 src     Reverb Different Side Reflect Address 2 Right\r
+ int mLAPF1;  // 1DF4 src/dst Reverb APF Address 1 Left\r
+ int mRAPF1;  // 1DF6 src/dst Reverb APF Address 1 Right\r
+ int mLAPF2;  // 1DF8 src/dst Reverb APF Address 2 Left\r
+ int mRAPF2;  // 1DFA src/dst Reverb APF Address 2 Right\r
+ int vLIN;    // 1DFC volume  Reverb Input Volume Left\r
+ int vRIN;    // 1DFE volume  Reverb Input Volume Right\r
+\r
+ // subtracted offsets\r
+ int mLAPF1_dAPF1, mRAPF1_dAPF1, mLAPF2_dAPF2, mRAPF2_dAPF2;\r
+\r
+ int dirty;   // registers changed\r
+\r
 } REVERBInfo;\r
 \r
 ///////////////////////////////////////////////////////////\r
index 6d72d3c..75e7d7a 100644 (file)
@@ -278,38 +278,38 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val,
       ReverbOn(16,24,val);\r
       break;\r
     //-------------------------------------------------//\r
-    case H_Reverb+0   : goto rvbd;\r
-    case H_Reverb+2   : goto rvbd;\r
-    case H_Reverb+4   : spu.rvb->IIR_ALPHA=(short)val;   break;\r
-    case H_Reverb+6   : spu.rvb->ACC_COEF_A=(short)val;  break;\r
-    case H_Reverb+8   : spu.rvb->ACC_COEF_B=(short)val;  break;\r
-    case H_Reverb+10  : spu.rvb->ACC_COEF_C=(short)val;  break;\r
-    case H_Reverb+12  : spu.rvb->ACC_COEF_D=(short)val;  break;\r
-    case H_Reverb+14  : spu.rvb->IIR_COEF=(short)val;    break;\r
-    case H_Reverb+16  : spu.rvb->FB_ALPHA=(short)val;    break;\r
-    case H_Reverb+18  : spu.rvb->FB_X=(short)val;        break;\r
-    case H_Reverb+20  : goto rvbd;\r
-    case H_Reverb+22  : goto rvbd;\r
-    case H_Reverb+24  : goto rvbd;\r
-    case H_Reverb+26  : goto rvbd;\r
-    case H_Reverb+28  : goto rvbd;\r
-    case H_Reverb+30  : goto rvbd;\r
-    case H_Reverb+32  : goto rvbd;\r
-    case H_Reverb+34  : goto rvbd;\r
-    case H_Reverb+36  : goto rvbd;\r
-    case H_Reverb+38  : goto rvbd;\r
-    case H_Reverb+40  : goto rvbd;\r
-    case H_Reverb+42  : goto rvbd;\r
-    case H_Reverb+44  : goto rvbd;\r
-    case H_Reverb+46  : goto rvbd;\r
-    case H_Reverb+48  : goto rvbd;\r
-    case H_Reverb+50  : goto rvbd;\r
-    case H_Reverb+52  : goto rvbd;\r
-    case H_Reverb+54  : goto rvbd;\r
-    case H_Reverb+56  : goto rvbd;\r
-    case H_Reverb+58  : goto rvbd;\r
-    case H_Reverb+60  : spu.rvb->IN_COEF_L=(short)val;   break;\r
-    case H_Reverb+62  : spu.rvb->IN_COEF_R=(short)val;   break;\r
+    case H_Reverb + 0x00 : goto rvbd;\r
+    case H_Reverb + 0x02 : goto rvbd;\r
+    case H_Reverb + 0x04 : spu.rvb->vIIR   = (signed short)val; break;\r
+    case H_Reverb + 0x06 : spu.rvb->vCOMB1 = (signed short)val; break;\r
+    case H_Reverb + 0x08 : spu.rvb->vCOMB2 = (signed short)val; break;\r
+    case H_Reverb + 0x0a : spu.rvb->vCOMB3 = (signed short)val; break;\r
+    case H_Reverb + 0x0c : spu.rvb->vCOMB4 = (signed short)val; break;\r
+    case H_Reverb + 0x0e : spu.rvb->vWALL  = (signed short)val; break;\r
+    case H_Reverb + 0x10 : spu.rvb->vAPF1  = (signed short)val; break;\r
+    case H_Reverb + 0x12 : spu.rvb->vAPF2  = (signed short)val; break;\r
+    case H_Reverb + 0x14 : goto rvbd;\r
+    case H_Reverb + 0x16 : goto rvbd;\r
+    case H_Reverb + 0x18 : goto rvbd;\r
+    case H_Reverb + 0x1a : goto rvbd;\r
+    case H_Reverb + 0x1c : goto rvbd;\r
+    case H_Reverb + 0x1e : goto rvbd;\r
+    case H_Reverb + 0x20 : goto rvbd;\r
+    case H_Reverb + 0x22 : goto rvbd;\r
+    case H_Reverb + 0x24 : goto rvbd;\r
+    case H_Reverb + 0x26 : goto rvbd;\r
+    case H_Reverb + 0x28 : goto rvbd;\r
+    case H_Reverb + 0x2a : goto rvbd;\r
+    case H_Reverb + 0x2c : goto rvbd;\r
+    case H_Reverb + 0x2e : goto rvbd;\r
+    case H_Reverb + 0x30 : goto rvbd;\r
+    case H_Reverb + 0x32 : goto rvbd;\r
+    case H_Reverb + 0x34 : goto rvbd;\r
+    case H_Reverb + 0x36 : goto rvbd;\r
+    case H_Reverb + 0x38 : goto rvbd;\r
+    case H_Reverb + 0x3a : goto rvbd;\r
+    case H_Reverb + 0x3c : spu.rvb->vLIN = (signed short)val; break;\r
+    case H_Reverb + 0x3e : spu.rvb->vRIN = (signed short)val; break;\r
    }\r
  return;\r
 \r
index c0ecea1..8d31c35 100644 (file)
@@ -21,6 +21,7 @@
 \r
 #include "stdafx.h"\r
 #include "spu.h"\r
+#include <assert.h>\r
 \r
 #define _IN_REVERB\r
 \r
@@ -42,130 +43,136 @@ INLINE void StartREVERB(int ch)
 \r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-INLINE int rvb2ram_offs(int curr, int space, int iOff)\r
+INLINE int rvb_wrap(int ofs, int space)\r
 {\r
- iOff += curr;\r
- if (iOff >= 0x40000) iOff -= space;\r
- return iOff;\r
+#if 0\r
+ int mask = (0x3ffff - ofs) >> 31;\r
+ ofs = ofs - (space & mask);\r
+#else\r
+ if (ofs >= 0x40000)\r
+  ofs -= space;\r
+#endif\r
+ //assert(ofs >= 0x40000 - space);\r
+ //assert(ofs < 0x40000);\r
+ return ofs;\r
+}\r
+\r
+INLINE int rvb2ram_offs(int curr, int space, int ofs)\r
+{\r
+ ofs += curr;\r
+ return rvb_wrap(ofs, space);\r
 }\r
 \r
 // get_buffer content helper: takes care about wraps\r
 #define g_buffer(var) \\r
- ((int)(signed short)LE16TOH(spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)]))\r
+ ((int)(signed short)LE16TOH(spuMem[rvb2ram_offs(curr_addr, space, var)]))\r
 \r
 // saturate iVal and store it as var\r
-#define s_buffer(var, iVal) \\r
+#define s_buffer_w(var, iVal) \\r
  ssat32_to_16(iVal); \\r
- spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)] = HTOLE16(iVal)\r
-\r
-#define s_buffer1(var, iVal) \\r
- ssat32_to_16(iVal); \\r
- spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var + 1)] = HTOLE16(iVal)\r
+ spuMem[rvb2ram_offs(curr_addr, space, var)] = HTOLE16(iVal)\r
 \r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-// portions based on spu2-x from PCSX2\r
+// from nocash psx-spx\r
 static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr)\r
 {\r
+ unsigned short *spuMem = spu.spuMem;\r
  const REVERBInfo *rvb = spu.rvb;\r
- int IIR_ALPHA = rvb->IIR_ALPHA;\r
- int IIR_COEF = rvb->IIR_COEF;\r
  int space = 0x40000 - rvb->StartAddr;\r
- int l, r, ns;\r
+ int mlsame_m2o = rvb->mLSAME + space - 1;\r
+ int mrsame_m2o = rvb->mRSAME + space - 1;\r
+ int mldiff_m2o = rvb->mLDIFF + space - 1;\r
+ int mrdiff_m2o = rvb->mRDIFF + space - 1;\r
+ int vCOMB1 = rvb->vCOMB1, vCOMB2 = rvb->vCOMB2;\r
+ int vCOMB3 = rvb->vCOMB3, vCOMB4 = rvb->vCOMB4;\r
+ int vAPF1 = rvb->vAPF1, vAPF2 = rvb->vAPF2;\r
+ int vIIR = rvb->vIIR;\r
+ int vWALL = rvb->vWALL;\r
+ int ns;\r
+\r
+ if (mlsame_m2o >= space) mlsame_m2o -= space;\r
+ if (mrsame_m2o >= space) mrsame_m2o -= space;\r
+ if (mldiff_m2o >= space) mldiff_m2o -= space;\r
+ if (mrdiff_m2o >= space) mrdiff_m2o -= space;\r
 \r
  for (ns = 0; ns < ns_to * 2; )\r
   {\r
-   int ACC0, ACC1, FB_A0, FB_A1, FB_B0, FB_B1;\r
-   int mix_dest_a0, mix_dest_a1, mix_dest_b0, mix_dest_b1;\r
-\r
-   int input_L = RVB[ns]   * rvb->IN_COEF_L;\r
-   int input_R = RVB[ns+1] * rvb->IN_COEF_R;\r
-\r
-   int IIR_INPUT_A0 = ((g_buffer(IIR_SRC_A0) * IIR_COEF) + input_L) >> 15;\r
-   int IIR_INPUT_A1 = ((g_buffer(IIR_SRC_A1) * IIR_COEF) + input_R) >> 15;\r
-   int IIR_INPUT_B0 = ((g_buffer(IIR_SRC_B0) * IIR_COEF) + input_L) >> 15;\r
-   int IIR_INPUT_B1 = ((g_buffer(IIR_SRC_B1) * IIR_COEF) + input_R) >> 15;\r
-\r
-   int iir_dest_a0 = g_buffer(IIR_DEST_A0);\r
-   int iir_dest_a1 = g_buffer(IIR_DEST_A1);\r
-   int iir_dest_b0 = g_buffer(IIR_DEST_B0);\r
-   int iir_dest_b1 = g_buffer(IIR_DEST_B1);\r
-\r
-   int IIR_A0 = iir_dest_a0 + ((IIR_INPUT_A0 - iir_dest_a0) * IIR_ALPHA >> 15);\r
-   int IIR_A1 = iir_dest_a1 + ((IIR_INPUT_A1 - iir_dest_a1) * IIR_ALPHA >> 15);\r
-   int IIR_B0 = iir_dest_b0 + ((IIR_INPUT_B0 - iir_dest_b0) * IIR_ALPHA >> 15);\r
-   int IIR_B1 = iir_dest_b1 + ((IIR_INPUT_B1 - iir_dest_b1) * IIR_ALPHA >> 15);\r
+   int Lin = RVB[ns]   * rvb->vLIN;\r
+   int Rin = RVB[ns+1] * rvb->vRIN;\r
+   int mlsame_m2 = g_buffer(mlsame_m2o) << 15; // -1\r
+   int mrsame_m2 = g_buffer(mrsame_m2o) << 15;\r
+   int mldiff_m2 = g_buffer(mldiff_m2o) << 15;\r
+   int mrdiff_m2 = g_buffer(mrdiff_m2o) << 15;\r
+   int Lout, Rout;\r
+\r
+   mlsame_m2 += ((Lin + g_buffer(rvb->dLSAME) * vWALL - mlsame_m2) >> 15) * vIIR;\r
+   mrsame_m2 += ((Rin + g_buffer(rvb->dRSAME) * vWALL - mrsame_m2) >> 15) * vIIR;\r
+   mldiff_m2 += ((Lin + g_buffer(rvb->dLDIFF) * vWALL - mldiff_m2) >> 15) * vIIR;\r
+   mrdiff_m2 += ((Rin + g_buffer(rvb->dRDIFF) * vWALL - mrdiff_m2) >> 15) * vIIR;\r
+   mlsame_m2 >>= 15; s_buffer_w(rvb->mLSAME, mlsame_m2);\r
+   mrsame_m2 >>= 15; s_buffer_w(rvb->mRSAME, mrsame_m2);\r
+   mldiff_m2 >>= 15; s_buffer_w(rvb->mLDIFF, mldiff_m2);\r
+   mrdiff_m2 >>= 15; s_buffer_w(rvb->mRDIFF, mrdiff_m2);\r
+\r
+   Lout = vCOMB1 * g_buffer(rvb->mLCOMB1) + vCOMB2 * g_buffer(rvb->mLCOMB2)\r
+        + vCOMB3 * g_buffer(rvb->mLCOMB3) + vCOMB4 * g_buffer(rvb->mLCOMB4);\r
+   Rout = vCOMB1 * g_buffer(rvb->mRCOMB1) + vCOMB2 * g_buffer(rvb->mRCOMB2)\r
+        + vCOMB3 * g_buffer(rvb->mRCOMB3) + vCOMB4 * g_buffer(rvb->mRCOMB4);\r
 \r
    preload(SSumLR + ns + 64*2/4 - 4);\r
 \r
-   s_buffer1(IIR_DEST_A0, IIR_A0);\r
-   s_buffer1(IIR_DEST_A1, IIR_A1);\r
-   s_buffer1(IIR_DEST_B0, IIR_B0);\r
-   s_buffer1(IIR_DEST_B1, IIR_B1);\r
+   Lout -= vAPF1 * g_buffer(rvb->mLAPF1_dAPF1); Lout >>= 15;\r
+   Rout -= vAPF1 * g_buffer(rvb->mRAPF1_dAPF1); Rout >>= 15;\r
+   s_buffer_w(rvb->mLAPF1, Lout);\r
+   s_buffer_w(rvb->mRAPF1, Rout);\r
+   Lout = Lout * vAPF1 + (g_buffer(rvb->mLAPF1_dAPF1) << 15);\r
+   Rout = Rout * vAPF1 + (g_buffer(rvb->mRAPF1_dAPF1) << 15);\r
 \r
    preload(RVB + ns + 64*2/4 - 4);\r
 \r
-   ACC0 = (g_buffer(ACC_SRC_A0) * rvb->ACC_COEF_A +\r
-           g_buffer(ACC_SRC_B0) * rvb->ACC_COEF_B +\r
-           g_buffer(ACC_SRC_C0) * rvb->ACC_COEF_C +\r
-           g_buffer(ACC_SRC_D0) * rvb->ACC_COEF_D) >> 15;\r
-   ACC1 = (g_buffer(ACC_SRC_A1) * rvb->ACC_COEF_A +\r
-           g_buffer(ACC_SRC_B1) * rvb->ACC_COEF_B +\r
-           g_buffer(ACC_SRC_C1) * rvb->ACC_COEF_C +\r
-           g_buffer(ACC_SRC_D1) * rvb->ACC_COEF_D) >> 15;\r
-\r
-   FB_A0 = g_buffer(FB_SRC_A0);\r
-   FB_A1 = g_buffer(FB_SRC_A1);\r
-   FB_B0 = g_buffer(FB_SRC_B0);\r
-   FB_B1 = g_buffer(FB_SRC_B1);\r
-\r
-   mix_dest_a0 = ACC0 - ((FB_A0 * rvb->FB_ALPHA) >> 15);\r
-   mix_dest_a1 = ACC1 - ((FB_A1 * rvb->FB_ALPHA) >> 15);\r
-\r
-   mix_dest_b0 = FB_A0 + (((ACC0 - FB_A0) * rvb->FB_ALPHA - FB_B0 * rvb->FB_X) >> 15);\r
-   mix_dest_b1 = FB_A1 + (((ACC1 - FB_A1) * rvb->FB_ALPHA - FB_B1 * rvb->FB_X) >> 15);\r
+   Lout -= vAPF2 * g_buffer(rvb->mLAPF2_dAPF2); Lout >>= 15;\r
+   Rout -= vAPF2 * g_buffer(rvb->mRAPF2_dAPF2); Rout >>= 15;\r
+   s_buffer_w(rvb->mLAPF2, Lout);\r
+   s_buffer_w(rvb->mRAPF2, Rout);\r
+   Lout = Lout * vAPF2 + (g_buffer(rvb->mLAPF2_dAPF2) << 15);\r
+   Rout = Rout * vAPF2 + (g_buffer(rvb->mRAPF2_dAPF2) << 15);\r
 \r
-   s_buffer(MIX_DEST_A0, mix_dest_a0);\r
-   s_buffer(MIX_DEST_A1, mix_dest_a1);\r
-   s_buffer(MIX_DEST_B0, mix_dest_b0);\r
-   s_buffer(MIX_DEST_B1, mix_dest_b1);\r
+   Lout = ((Lout >> 15) * rvb->VolLeft)  >> 15;\r
+   Rout = ((Rout >> 15) * rvb->VolRight) >> 15;\r
 \r
-   l = (mix_dest_a0 + mix_dest_b0) / 2;\r
-   r = (mix_dest_a1 + mix_dest_b1) / 2;\r
-\r
-   l = (l * rvb->VolLeft)  >> 15; // 15?\r
-   r = (r * rvb->VolRight) >> 15;\r
-\r
-   SSumLR[ns++] += l;\r
-   SSumLR[ns++] += r;\r
-   SSumLR[ns++] += l;\r
-   SSumLR[ns++] += r;\r
+   SSumLR[ns++] += Lout;\r
+   SSumLR[ns++] += Rout;\r
+   SSumLR[ns++] += Lout;\r
+   SSumLR[ns++] += Rout;\r
 \r
    curr_addr++;\r
-   if (curr_addr >= 0x40000) curr_addr = rvb->StartAddr;\r
+   curr_addr = rvb_wrap(curr_addr, space);\r
   }\r
 }\r
 \r
 static void MixREVERB_off(int *SSumLR, int ns_to, int curr_addr)\r
 {\r
  const REVERBInfo *rvb = spu.rvb;\r
+ unsigned short *spuMem = spu.spuMem;\r
  int space = 0x40000 - rvb->StartAddr;\r
- int l, r, ns;\r
+ int Lout, Rout, ns;\r
 \r
  for (ns = 0; ns < ns_to * 2; )\r
   {\r
    preload(SSumLR + ns + 64*2/4 - 4);\r
 \r
-   l = (g_buffer(MIX_DEST_A0) + g_buffer(MIX_DEST_B0)) / 2;\r
-   r = (g_buffer(MIX_DEST_A1) + g_buffer(MIX_DEST_B1)) / 2;\r
+   // todo: is this missing COMB and APF1?\r
+   Lout = g_buffer(rvb->mLAPF2_dAPF2);\r
+   Rout = g_buffer(rvb->mLAPF2_dAPF2);\r
 \r
-   l = (l * rvb->VolLeft)  >> 15;\r
-   r = (r * rvb->VolRight) >> 15;\r
+   Lout = (Lout * rvb->VolLeft)  >> 15;\r
+   Rout = (Rout * rvb->VolRight) >> 15;\r
 \r
-   SSumLR[ns++] += l;\r
-   SSumLR[ns++] += r;\r
-   SSumLR[ns++] += l;\r
-   SSumLR[ns++] += r;\r
+   SSumLR[ns++] += Lout;\r
+   SSumLR[ns++] += Rout;\r
+   SSumLR[ns++] += Lout;\r
+   SSumLR[ns++] += Rout;\r
 \r
    curr_addr++;\r
    if (curr_addr >= 0x40000) curr_addr = rvb->StartAddr;\r
@@ -199,30 +206,30 @@ static void REVERBPrep(void)
      t -= space; \\r
    rvb->d = t\r
 \r
- prep_offs(IIR_SRC_A0, 32);\r
- prep_offs(IIR_SRC_A1, 34);\r
- prep_offs(IIR_SRC_B0, 36);\r
- prep_offs(IIR_SRC_B1, 38);\r
- prep_offs(IIR_DEST_A0, 20);\r
- prep_offs(IIR_DEST_A1, 22);\r
- prep_offs(IIR_DEST_B0, 36);\r
- prep_offs(IIR_DEST_B1, 38);\r
- prep_offs(ACC_SRC_A0, 24);\r
- prep_offs(ACC_SRC_A1, 26);\r
- prep_offs(ACC_SRC_B0, 28);\r
- prep_offs(ACC_SRC_B1, 30);\r
- prep_offs(ACC_SRC_C0, 40);\r
- prep_offs(ACC_SRC_C1, 42);\r
- prep_offs(ACC_SRC_D0, 44);\r
- prep_offs(ACC_SRC_D1, 46);\r
- prep_offs(MIX_DEST_A0, 52);\r
- prep_offs(MIX_DEST_A1, 54);\r
- prep_offs(MIX_DEST_B0, 56);\r
- prep_offs(MIX_DEST_B1, 58);\r
- prep_offs2(FB_SRC_A0, 52, 0);\r
- prep_offs2(FB_SRC_A1, 54, 0);\r
- prep_offs2(FB_SRC_B0, 56, 2);\r
- prep_offs2(FB_SRC_B1, 58, 2);\r
+ prep_offs(mLSAME,  0x14);\r
+ prep_offs(mRSAME,  0x16);\r
+ prep_offs(mLCOMB1, 0x18);\r
+ prep_offs(mRCOMB1, 0x1a);\r
+ prep_offs(mLCOMB2, 0x1c);\r
+ prep_offs(mRCOMB2, 0x1e);\r
+ prep_offs(dLSAME,  0x20);\r
+ prep_offs(dRSAME,  0x22);\r
+ prep_offs(mLDIFF,  0x24);\r
+ prep_offs(mRDIFF,  0x26);\r
+ prep_offs(mLCOMB3, 0x28);\r
+ prep_offs(mRCOMB3, 0x2a);\r
+ prep_offs(mLCOMB4, 0x2c);\r
+ prep_offs(mRCOMB4, 0x2e);\r
+ prep_offs(dLDIFF,  0x30);\r
+ prep_offs(dRDIFF,  0x32);\r
+ prep_offs(mLAPF1,  0x34);\r
+ prep_offs(mRAPF1,  0x36);\r
+ prep_offs(mLAPF2,  0x38);\r
+ prep_offs(mRAPF2,  0x3a);\r
+ prep_offs2(mLAPF1_dAPF1, 0x34, 0);\r
+ prep_offs2(mRAPF1_dAPF1, 0x36, 0);\r
+ prep_offs2(mLAPF2_dAPF2, 0x38, 2);\r
+ prep_offs2(mRAPF2_dAPF2, 0x3a, 2);\r
 \r
 #undef prep_offs\r
 #undef prep_offs2\r
@@ -245,180 +252,4 @@ INLINE void REVERBDo(int *SSumLR, int *RVB, int ns_to, int curr_addr)
 \r
 #endif\r
 \r
-/*\r
------------------------------------------------------------------------------\r
-PSX reverb hardware notes\r
-by Neill Corlett\r
------------------------------------------------------------------------------\r
-\r
-Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway\r
-yadda yadda.\r
-\r
------------------------------------------------------------------------------\r
-\r
-Basics\r
-------\r
-\r
-- The reverb buffer is 22khz 16-bit mono PCM.\r
-- It starts at the reverb address given by 1DA2, extends to\r
-  the end of sound RAM, and wraps back to the 1DA2 address.\r
-\r
-Setting the address at 1DA2 resets the current reverb work address.\r
-\r
-This work address ALWAYS increments every 1/22050 sec., regardless of\r
-whether reverb is enabled (bit 7 of 1DAA set).\r
-\r
-And the contents of the reverb buffer ALWAYS play, scaled by the\r
-"reverberation depth left/right" volumes (1D84/1D86).\r
-(which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)\r
-\r
------------------------------------------------------------------------------\r
-\r
-Register names\r
---------------\r
-\r
-These are probably not their real names.\r
-These are probably not even correct names.\r
-We will use them anyway, because we can.\r
-\r
-1DC0: FB_SRC_A       (offset)\r
-1DC2: FB_SRC_B       (offset)\r
-1DC4: IIR_ALPHA      (coef.)\r
-1DC6: ACC_COEF_A     (coef.)\r
-1DC8: ACC_COEF_B     (coef.)\r
-1DCA: ACC_COEF_C     (coef.)\r
-1DCC: ACC_COEF_D     (coef.)\r
-1DCE: IIR_COEF       (coef.)\r
-1DD0: FB_ALPHA       (coef.)\r
-1DD2: FB_X           (coef.)\r
-1DD4: IIR_DEST_A0    (offset)\r
-1DD6: IIR_DEST_A1    (offset)\r
-1DD8: ACC_SRC_A0     (offset)\r
-1DDA: ACC_SRC_A1     (offset)\r
-1DDC: ACC_SRC_B0     (offset)\r
-1DDE: ACC_SRC_B1     (offset)\r
-1DE0: IIR_SRC_A0     (offset)\r
-1DE2: IIR_SRC_A1     (offset)\r
-1DE4: IIR_DEST_B0    (offset)\r
-1DE6: IIR_DEST_B1    (offset)\r
-1DE8: ACC_SRC_C0     (offset)\r
-1DEA: ACC_SRC_C1     (offset)\r
-1DEC: ACC_SRC_D0     (offset)\r
-1DEE: ACC_SRC_D1     (offset)\r
-1DF0: IIR_SRC_B1     (offset)\r
-1DF2: IIR_SRC_B0     (offset)\r
-1DF4: MIX_DEST_A0    (offset)\r
-1DF6: MIX_DEST_A1    (offset)\r
-1DF8: MIX_DEST_B0    (offset)\r
-1DFA: MIX_DEST_B1    (offset)\r
-1DFC: IN_COEF_L      (coef.)\r
-1DFE: IN_COEF_R      (coef.)\r
-\r
-The coefficients are signed fractional values.\r
--32768 would be -1.0\r
- 32768 would be  1.0 (if it were possible... the highest is of course 32767)\r
-\r
-The offsets are (byte/8) offsets into the reverb buffer.\r
-i.e. you multiply them by 8, you get byte offsets.\r
-You can also think of them as (samples/4) offsets.\r
-They appear to be signed.  They can be negative.\r
-None of the documented presets make them negative, though.\r
-\r
-Yes, 1DF0 and 1DF2 appear to be backwards.  Not a typo.\r
-\r
------------------------------------------------------------------------------\r
-\r
-What it does\r
-------------\r
-\r
-We take all reverb sources:\r
-- regular channels that have the reverb bit on\r
-- cd and external sources, if their reverb bits are on\r
-and mix them into one stereo 44100hz signal.\r
-\r
-Lowpass/downsample that to 22050hz.  The PSX uses a proper bandlimiting\r
-algorithm here, but I haven't figured out the hysterically exact specifics.\r
-I use an 8-tap filter with these coefficients, which are nice but probably\r
-not the real ones:\r
-\r
-0.037828187894\r
-0.157538631280\r
-0.321159685278\r
-0.449322115345\r
-0.449322115345\r
-0.321159685278\r
-0.157538631280\r
-0.037828187894\r
-\r
-So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.\r
-\r
-* IN MY EMULATION, I divide these by 2 to make it clip less.\r
-  (and of course the L/R output coefficients are adjusted to compensate)\r
-  The real thing appears to not do this.\r
-\r
-At every 22050hz tick:\r
-- If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb\r
-  steady-state algorithm described below\r
-- AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer\r
-  (This part may not be exactly right and I guessed at the coefs. TODO: check later.)\r
-  L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])\r
-  R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])\r
-- Advance the current buffer position by 1 sample\r
-\r
-The wet out L and R are then upsampled to 44100hz and played at the\r
-"reverberation depth left/right" (1D84/1D86) volume, independent of the main\r
-volume.\r
-\r
------------------------------------------------------------------------------\r
-\r
-Reverb steady-state\r
--------------------\r
-\r
-The reverb steady-state algorithm is fairly clever, and of course by\r
-"clever" I mean "batshit insane".\r
-\r
-buffer[x] is relative to the current buffer position, not the beginning of\r
-the buffer.  Note that all buffer offsets must wrap around so they're\r
-contained within the reverb work area.\r
-\r
-Clipping is performed at the end... maybe also sooner, but definitely at\r
-the end.\r
-\r
-IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;\r
-IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;\r
-IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;\r
-IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;\r
-\r
-IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);\r
-IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);\r
-IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);\r
-IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);\r
-\r
-buffer[IIR_DEST_A0 + 1sample] = IIR_A0;\r
-buffer[IIR_DEST_A1 + 1sample] = IIR_A1;\r
-buffer[IIR_DEST_B0 + 1sample] = IIR_B0;\r
-buffer[IIR_DEST_B1 + 1sample] = IIR_B1;\r
-\r
-ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +\r
-       buffer[ACC_SRC_B0] * ACC_COEF_B +\r
-       buffer[ACC_SRC_C0] * ACC_COEF_C +\r
-       buffer[ACC_SRC_D0] * ACC_COEF_D;\r
-ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +\r
-       buffer[ACC_SRC_B1] * ACC_COEF_B +\r
-       buffer[ACC_SRC_C1] * ACC_COEF_C +\r
-       buffer[ACC_SRC_D1] * ACC_COEF_D;\r
-\r
-FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];\r
-FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];\r
-FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];\r
-FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];\r
-\r
-buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;\r
-buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;\r
-buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;\r
-buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;\r
-\r
------------------------------------------------------------------------------\r
-*/\r
-\r
 // vim:shiftwidth=1:expandtab\r