spu: try some reverb resample filtering master github/master
authornotaz <notasas@gmail.com>
Thu, 30 Jan 2025 21:24:18 +0000 (23:24 +0200)
committernotaz <notasas@gmail.com>
Thu, 30 Jan 2025 21:24:18 +0000 (23:24 +0200)
when gauss/cubic interpolation is on
libretro/pcsx_rearmed#515

plugins/dfsound/externals.h
plugins/dfsound/freeze.c
plugins/dfsound/gauss_i.h
plugins/dfsound/reverb.c
plugins/dfsound/spu.c

index 6fdef9d..38f66bc 100644 (file)
@@ -167,6 +167,8 @@ typedef struct
 \r
  int dirty;   // registers changed\r
 \r
+ // for filtering\r
+ int SB[2][4*2];\r
 } REVERBInfo;\r
 \r
 ///////////////////////////////////////////////////////////\r
index 36b8995..ef06203 100644 (file)
@@ -15,6 +15,7 @@
  *                                                                         *\r
  ***************************************************************************/\r
 \r
+#include <stddef.h>\r
 #include <assert.h>\r
 #include "stdafx.h"\r
 \r
@@ -137,6 +138,7 @@ typedef struct
  uint32_t   XARepeat;\r
  uint32_t   XALastVal;\r
  uint32_t   last_keyon_cycles;\r
+ uint32_t   rvb_sb[2][4];\r
 \r
 } SPUOSSFreeze_t;\r
 \r
@@ -240,7 +242,7 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
  unsigned int cycles)\r
 {\r
  SPUOSSFreeze_t * pFO = NULL;\r
- int i;\r
+ int i, j;\r
 \r
  if(!pF) return 0;                                     // first check\r
 \r
@@ -310,6 +312,8 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
    pFO->XARepeat = spu.XARepeat;\r
    pFO->XALastVal = spu.XALastVal;\r
    pFO->last_keyon_cycles = spu.last_keyon_cycles;\r
+   for (i = 0; i < 2; i++)\r
+    memcpy(&pFO->rvb_sb[i], spu.rvb->SB[i], sizeof(pFO->rvb_sb[i]));\r
 \r
    for(i=0;i<MAXCHAN;i++)\r
     {\r
@@ -357,7 +361,7 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
  spu.XARepeat = 0;\r
  spu.XALastVal = 0;\r
  spu.last_keyon_cycles = cycles - 16*786u;\r
- if (pFO && pF->ulFreezeSize >= sizeof(*pF) + sizeof(*pFO)) {\r
+ if (pFO && pF->ulFreezeSize >= sizeof(*pF) + offsetof(SPUOSSFreeze_t, rvb_sb)) {\r
   spu.cycles_dma_end = pFO->cycles_dma_end;\r
   spu.decode_dirty_ch = pFO->decode_dirty_ch;\r
   spu.dwNoiseVal = pFO->dwNoiseVal;\r
@@ -366,6 +370,11 @@ long CALLBACK SPUfreeze(unsigned int ulFreezeMode, SPUFreeze_t * pF,
   spu.XALastVal = pFO->XALastVal;\r
   spu.last_keyon_cycles = pFO->last_keyon_cycles;\r
  }\r
+ if (pFO && pF->ulFreezeSize >= sizeof(*pF) + sizeof(*pFO)) {\r
+  for (i = 0; i < 2; i++)\r
+   for (j = 0; j < 2; j++)\r
+    memcpy(&spu.rvb->SB[i][j*4], pFO->rvb_sb[i], 4 * sizeof(spu.rvb->SB[i][0]));\r
+ }\r
 \r
  // repair some globals\r
  for(i=0;i<=62;i+=2)\r
index e754347..00a618a 100644 (file)
@@ -49,23 +49,24 @@ for(0) + for(256) + rev(256) + rev(0)
 \r
 \r
 // Mednafen's table (PSX) 99-100%\r
-const int gauss[]={\r
-       0x12c7, 0x59b3, 0x1307, 0xffffffff, \r
-       0x1288, 0x59b2, 0x1347, 0xffffffff, \r
-       0x1249, 0x59b0, 0x1388, 0xffffffff, \r
-       0x120b, 0x59ad, 0x13c9, 0xffffffff, \r
-       0x11cd, 0x59a9, 0x140b, 0xffffffff, \r
-       0x118f, 0x59a4, 0x144d, 0xffffffff, \r
-       0x1153, 0x599e, 0x1490, 0xffffffff, \r
-       0x1116, 0x5997, 0x14d4, 0xffffffff, \r
-       0x10db, 0x598f, 0x1517, 0xffffffff, \r
-       0x109f, 0x5986, 0x155c, 0xffffffff, \r
-       0x1065, 0x597c, 0x15a0, 0xffffffff, \r
-       0x102a, 0x5971, 0x15e6, 0xffffffff, \r
-       0x0ff1, 0x5965, 0x162c, 0xffffffff, \r
-       0x0fb7, 0x5958, 0x1672, 0xffffffff, \r
-       0x0f7f, 0x5949, 0x16b9, 0xffffffff, \r
-       0x0f46, 0x593a, 0x1700, 0xffffffff, \r
+static const signed short gauss[] =\r
+{\r
+       0x12c7, 0x59b3, 0x1307, 0xffff,\r
+       0x1288, 0x59b2, 0x1347, 0xffff,\r
+       0x1249, 0x59b0, 0x1388, 0xffff,\r
+       0x120b, 0x59ad, 0x13c9, 0xffff,\r
+       0x11cd, 0x59a9, 0x140b, 0xffff,\r
+       0x118f, 0x59a4, 0x144d, 0xffff,\r
+       0x1153, 0x599e, 0x1490, 0xffff,\r
+       0x1116, 0x5997, 0x14d4, 0xffff,\r
+       0x10db, 0x598f, 0x1517, 0xffff,\r
+       0x109f, 0x5986, 0x155c, 0xffff,\r
+       0x1065, 0x597c, 0x15a0, 0xffff,\r
+       0x102a, 0x5971, 0x15e6, 0xffff,\r
+       0x0ff1, 0x5965, 0x162c, 0xffff,\r
+       0x0fb7, 0x5958, 0x1672, 0xffff,\r
+       0x0f7f, 0x5949, 0x16b9, 0xffff,\r
+       0x0f46, 0x593a, 0x1700, 0xffff,\r
        0x0f0f, 0x592a, 0x1747, 0x0000, \r
        0x0ed7, 0x5919, 0x1790, 0x0000, \r
        0x0ea1, 0x5907, 0x17d8, 0x0000, \r
@@ -290,22 +291,22 @@ const int gauss[]={
        0x0000, 0x17d8, 0x5907, 0x0ea1, \r
        0x0000, 0x1790, 0x5919, 0x0ed7, \r
        0x0000, 0x1747, 0x592a, 0x0f0f, \r
-       0xffffffff, 0x1700, 0x593a, 0x0f46, \r
-       0xffffffff, 0x16b9, 0x5949, 0x0f7f, \r
-       0xffffffff, 0x1672, 0x5958, 0x0fb7, \r
-       0xffffffff, 0x162c, 0x5965, 0x0ff1, \r
-       0xffffffff, 0x15e6, 0x5971, 0x102a, \r
-       0xffffffff, 0x15a0, 0x597c, 0x1065, \r
-       0xffffffff, 0x155c, 0x5986, 0x109f, \r
-       0xffffffff, 0x1517, 0x598f, 0x10db, \r
-       0xffffffff, 0x14d4, 0x5997, 0x1116, \r
-       0xffffffff, 0x1490, 0x599e, 0x1153, \r
-       0xffffffff, 0x144d, 0x59a4, 0x118f, \r
-       0xffffffff, 0x140b, 0x59a9, 0x11cd, \r
-       0xffffffff, 0x13c9, 0x59ad, 0x120b, \r
-       0xffffffff, 0x1388, 0x59b0, 0x1249, \r
-       0xffffffff, 0x1347, 0x59b2, 0x1288, \r
-       0xffffffff, 0x1307, 0x59b3, 0x12c7, \r
+       0xffff, 0x1700, 0x593a, 0x0f46,\r
+       0xffff, 0x16b9, 0x5949, 0x0f7f,\r
+       0xffff, 0x1672, 0x5958, 0x0fb7,\r
+       0xffff, 0x162c, 0x5965, 0x0ff1,\r
+       0xffff, 0x15e6, 0x5971, 0x102a,\r
+       0xffff, 0x15a0, 0x597c, 0x1065,\r
+       0xffff, 0x155c, 0x5986, 0x109f,\r
+       0xffff, 0x1517, 0x598f, 0x10db,\r
+       0xffff, 0x14d4, 0x5997, 0x1116,\r
+       0xffff, 0x1490, 0x599e, 0x1153,\r
+       0xffff, 0x144d, 0x59a4, 0x118f,\r
+       0xffff, 0x140b, 0x59a9, 0x11cd,\r
+       0xffff, 0x13c9, 0x59ad, 0x120b,\r
+       0xffff, 0x1388, 0x59b0, 0x1249,\r
+       0xffff, 0x1347, 0x59b2, 0x1288,\r
+       0xffff, 0x1307, 0x59b3, 0x12c7,\r
 };\r
 \r
 #endif\r
index 8d31c35..0fcb6a1 100644 (file)
@@ -74,11 +74,31 @@ INLINE int rvb2ram_offs(int curr, int space, int ofs)
 \r
 ////////////////////////////////////////////////////////////////////////\r
 \r
-// from nocash psx-spx\r
-static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr)\r
+static void reverb_interpolate(REVERBInfo *rvb, int curr_addr,\r
+  int out0[2], int out1[2])\r
+{\r
+ int spos = (curr_addr - 3) & 3;\r
+ int dpos = curr_addr & 3;\r
+ int i;\r
+\r
+ for (i = 0; i < 2; i++)\r
+  rvb->SB[i][dpos] = rvb->SB[i][4 | dpos] = out0[i];\r
+\r
+ // mednafen uses some 20 coefs here, we just reuse gauss [0] and [128]\r
+ for (i = 0; i < 2; i++)\r
+ {\r
+  const int *s;\r
+  s = &rvb->SB[i][spos];\r
+  out0[i] = (s[0] * 0x12c7 + s[1] * 0x59b3 + s[2] * 0x1307) >> 15;\r
+  out1[i] = (s[0] * 0x019c + s[1] * 0x3def + s[2] * 0x3e4c + s[3] * 0x01a8) >> 15;\r
+ }\r
+}\r
+\r
+static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr,\r
+  int do_filter)\r
 {\r
  unsigned short *spuMem = spu.spuMem;\r
const REVERBInfo *rvb = spu.rvb;\r
+ REVERBInfo *rvb = spu.rvb;\r
  int space = 0x40000 - rvb->StartAddr;\r
  int mlsame_m2o = rvb->mLSAME + space - 1;\r
  int mrsame_m2o = rvb->mRSAME + space - 1;\r
@@ -104,8 +124,9 @@ static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr)
    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
+   int Lout, Rout, out0[2], out1[2];\r
 \r
+   // from nocash psx-spx\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
@@ -138,13 +159,15 @@ static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr)
    Lout = Lout * vAPF2 + (g_buffer(rvb->mLAPF2_dAPF2) << 15);\r
    Rout = Rout * vAPF2 + (g_buffer(rvb->mRAPF2_dAPF2) << 15);\r
 \r
-   Lout = ((Lout >> 15) * rvb->VolLeft)  >> 15;\r
-   Rout = ((Rout >> 15) * rvb->VolRight) >> 15;\r
+   out0[0] = out1[0] = (Lout >> 15) * rvb->VolLeft  >> 15;\r
+   out0[1] = out1[1] = (Rout >> 15) * rvb->VolRight >> 15;\r
+   if (do_filter)\r
+    reverb_interpolate(rvb, curr_addr, out0, out1);\r
 \r
-   SSumLR[ns++] += Lout;\r
-   SSumLR[ns++] += Rout;\r
-   SSumLR[ns++] += Lout;\r
-   SSumLR[ns++] += Rout;\r
+   SSumLR[ns++] += out0[0];\r
+   SSumLR[ns++] += out0[1];\r
+   SSumLR[ns++] += out1[0];\r
+   SSumLR[ns++] += out1[1];\r
 \r
    curr_addr++;\r
    curr_addr = rvb_wrap(curr_addr, space);\r
@@ -240,7 +263,7 @@ INLINE void REVERBDo(int *SSumLR, int *RVB, int ns_to, int curr_addr)
 {\r
  if (spu.spuCtrl & 0x80)                               // -> reverb on? oki\r
  {\r
-  MixREVERB(SSumLR, RVB, ns_to, curr_addr);\r
+  MixREVERB(SSumLR, RVB, ns_to, curr_addr, spu.interpolation > 1);\r
  }\r
  else if (spu.rvb->VolLeft || spu.rvb->VolRight)\r
  {\r
index bc9cbf1..0938a34 100644 (file)
@@ -333,11 +333,11 @@ INLINE int GetInterpolationGauss(const sample_buf *sb, int spos)
  int gpos = sb->interp.gauss.pos;
  int vl = (spos >> 6) & ~3;
  int vr;
- vr  = (gauss[vl+0] * gval(0)) >> 15;
- vr += (gauss[vl+1] * gval(1)) >> 15;
- vr += (gauss[vl+2] * gval(2)) >> 15;
- vr += (gauss[vl+3] * gval(3)) >> 15;
- return vr;
+ vr  = gauss[vl+0] * gval(0);
+ vr += gauss[vl+1] * gval(1);
+ vr += gauss[vl+2] * gval(2);
+ vr += gauss[vl+3] * gval(3);
+ return vr >> 15;
 }
 
 static void decode_block_data(int *dest, const unsigned char *src, int predict_nr, int shift_factor)