ref: 52ed0fea7229014eeb0fb0e21e47ef6d36891908
parent: 333b95a4bd31ca40541e4b6f76f94628042b6bc4
author: allkern <lisandroaalarcon@gmail.com>
date: Thu Oct 12 09:05:42 EDT 2023
Implement SPU reverb
--- a/psx/dev/spu.c
+++ b/psx/dev/spu.c
@@ -423,60 +423,91 @@
free(spu);
}
-#define R16(addr) (*((uint16_t*)(&spu->ram[addr])))
-#define W16(addr) *((uint16_t*)(&spu->ram[addr]))
+// To-do: Optimize reverb
+int16_t spu_read_reverb(psx_spu_t* spu, uint32_t addr) {+ uint32_t mbase = spu->mbase << 3;
+
+ uint32_t relative = (addr + spu->revbaddr - mbase) % (0x80000 - mbase);
+ uint32_t wrapped = (mbase + relative) & 0x7fffe;
+
+ return *(int16_t*)(spu->ram + wrapped);
+}
+
+void spu_write_reverb(psx_spu_t* spu, uint32_t addr, int16_t value) {+ uint32_t mbase = spu->mbase << 3;
+
+ uint32_t relative = (addr + spu->revbaddr - mbase) % (0x80000 - mbase);
+ uint32_t wrapped = (mbase + relative) & 0x7fffe;
+
+ *(int16_t*)(spu->ram + wrapped) = value;
+}
+
+#define R16(addr) (spu_read_reverb(spu, addr))
+#define W16(addr, value) spu_write_reverb(spu, addr, value)
+
void spu_get_reverb_sample(psx_spu_t* spu, int inl, int inr, int* outl, int* outr) {uint32_t mbase = spu->mbase << 3;
uint32_t dapf1 = spu->dapf1 << 3;
uint32_t dapf2 = spu->dapf2 << 3;
- uint32_t mlsame = MAX(mbase, (spu->revbaddr + (spu->mlsame << 3)) & 0x7fffe);
- uint32_t mrsame = MAX(mbase, (spu->revbaddr + (spu->mrsame << 3)) & 0x7fffe);
- uint32_t dlsame = MAX(mbase, (spu->revbaddr + (spu->dlsame << 3)) & 0x7fffe);
- uint32_t drsame = MAX(mbase, (spu->revbaddr + (spu->drsame << 3)) & 0x7fffe);
- uint32_t mldiff = MAX(mbase, (spu->revbaddr + (spu->mldiff << 3)) & 0x7fffe);
- uint32_t mrdiff = MAX(mbase, (spu->revbaddr + (spu->mrdiff << 3)) & 0x7fffe);
- uint32_t dldiff = MAX(mbase, (spu->revbaddr + (spu->dldiff << 3)) & 0x7fffe);
- uint32_t drdiff = MAX(mbase, (spu->revbaddr + (spu->drdiff << 3)) & 0x7fffe);
- uint32_t mlcomb1 = MAX(mbase, (spu->revbaddr + (spu->mlcomb1 << 3)) & 0x7fffe);
- uint32_t mlcomb2 = MAX(mbase, (spu->revbaddr + (spu->mlcomb2 << 3)) & 0x7fffe);
- uint32_t mlcomb3 = MAX(mbase, (spu->revbaddr + (spu->mlcomb3 << 3)) & 0x7fffe);
- uint32_t mlcomb4 = MAX(mbase, (spu->revbaddr + (spu->mlcomb4 << 3)) & 0x7fffe);
- uint32_t mrcomb1 = MAX(mbase, (spu->revbaddr + (spu->mrcomb1 << 3)) & 0x7fffe);
- uint32_t mrcomb2 = MAX(mbase, (spu->revbaddr + (spu->mrcomb2 << 3)) & 0x7fffe);
- uint32_t mrcomb3 = MAX(mbase, (spu->revbaddr + (spu->mrcomb3 << 3)) & 0x7fffe);
- uint32_t mrcomb4 = MAX(mbase, (spu->revbaddr + (spu->mrcomb4 << 3)) & 0x7fffe);
- uint32_t mlapf1 = MAX(mbase, (spu->revbaddr + ((spu->mlapf1 << 3) - dapf1)) & 0x7fffe);
- uint32_t mlapf2 = MAX(mbase, (spu->revbaddr + ((spu->mlapf2 << 3) - dapf2)) & 0x7fffe);
- uint32_t mrapf1 = MAX(mbase, (spu->revbaddr + ((spu->mrapf1 << 3) - dapf1)) & 0x7fffe);
- uint32_t mrapf2 = MAX(mbase, (spu->revbaddr + ((spu->mrapf2 << 3) - dapf2)) & 0x7fffe);
- int16_t viir = spu->viir;
- int16_t vwall = spu->vwall;
- int16_t vcomb1 = spu->vcomb1;
- int16_t vcomb2 = spu->vcomb2;
- int16_t vcomb3 = spu->vcomb3;
- int16_t vcomb4 = spu->vcomb4;
- int16_t vapf1 = spu->vapf1;
- int16_t vapf2 = spu->vapf2;
- int16_t vlout = spu->vlout;
- int16_t vrout = spu->vrout;
+ uint32_t mlsame = spu->mlsame << 3;
+ uint32_t mrsame = spu->mrsame << 3;
+ uint32_t dlsame = spu->dlsame << 3;
+ uint32_t drsame = spu->drsame << 3;
+ uint32_t mldiff = spu->mldiff << 3;
+ uint32_t mrdiff = spu->mrdiff << 3;
+ uint32_t dldiff = spu->dldiff << 3;
+ uint32_t drdiff = spu->drdiff << 3;
+ uint32_t mlcomb1 = spu->mlcomb1 << 3;
+ uint32_t mlcomb2 = spu->mlcomb2 << 3;
+ uint32_t mlcomb3 = spu->mlcomb3 << 3;
+ uint32_t mlcomb4 = spu->mlcomb4 << 3;
+ uint32_t mrcomb1 = spu->mrcomb1 << 3;
+ uint32_t mrcomb2 = spu->mrcomb2 << 3;
+ uint32_t mrcomb3 = spu->mrcomb3 << 3;
+ uint32_t mrcomb4 = spu->mrcomb4 << 3;
+ uint32_t mlapf1 = spu->mlapf1 << 3;
+ uint32_t mlapf2 = spu->mlapf2 << 3;
+ uint32_t mrapf1 = spu->mrapf1 << 3;
+ uint32_t mrapf2 = spu->mrapf2 << 3;
- int lin = inl * spu->vlin;
- int rin = inr * spu->vrin;
+ float vlin = (float)spu->vlin / 32767.0f;
+ float vrin = (float)spu->vrin / 32767.0f;
+ float viir = (float)spu->viir / 32767.0f;
+ float vwall = (float)spu->vwall / 32767.0f;
+ float vcomb1 = (float)spu->vcomb1 / 32767.0f;
+ float vcomb2 = (float)spu->vcomb2 / 32767.0f;
+ float vcomb3 = (float)spu->vcomb3 / 32767.0f;
+ float vcomb4 = (float)spu->vcomb4 / 32767.0f;
+ float vapf1 = (float)spu->vapf1 / 32767.0f;
+ float vapf2 = (float)spu->vapf2 / 32767.0f;
+ float vlout = (float)spu->vlout / 32767.0f;
+ float vrout = (float)spu->vrout / 32767.0f;
- W16(mlsame) = (lin + R16(dlsame)*vwall - R16(mlsame-2))*viir + R16(mlsame-2);
- W16(mrsame) = (rin + R16(drsame)*vwall - R16(mrsame-2))*viir + R16(mrsame-2);
- W16(mldiff) = (lin + R16(drdiff)*vwall - R16(mldiff-2))*viir + R16(mldiff-2);
- W16(mrdiff) = (rin + R16(dldiff)*vwall - R16(mrdiff-2))*viir + R16(mrdiff-2);
+ int lin = ((float)inl * 0.5f) * vlin;
+ int rin = ((float)inr * 0.5f) * vrin;
+ int mlsamev = (lin + R16(dlsame)*vwall - R16(mlsame-2))*viir + R16(mlsame-2);
+ int mrsamev = (rin + R16(drsame)*vwall - R16(mrsame-2))*viir + R16(mrsame-2);
+ int mldiffv = (lin + R16(drdiff)*vwall - R16(mldiff-2))*viir + R16(mldiff-2);
+ int mrdiffv = (rin + R16(dldiff)*vwall - R16(mrdiff-2))*viir + R16(mrdiff-2);
+
+ W16(mlsame, CLAMP(mlsamev, -0x8000, 0x7fff));
+ W16(mrsame, CLAMP(mrsamev, -0x8000, 0x7fff));
+ W16(mldiff, CLAMP(mldiffv, -0x8000, 0x7fff));
+ W16(mrdiff, CLAMP(mrdiffv, -0x8000, 0x7fff));
+
int lout=vcomb1*R16(mlcomb1)+vcomb2*R16(mlcomb2)+vcomb3*R16(mlcomb3)+vcomb4*R16(mlcomb4);
int rout=vcomb1*R16(mrcomb1)+vcomb2*R16(mrcomb2)+vcomb3*R16(mrcomb3)+vcomb4*R16(mrcomb4);
- lout-=vapf1*R16(mlapf1); R16(mlapf1)=lout; lout*=vapf1+R16(mlapf1);
- rout-=vapf1*R16(mrapf1); R16(mrapf1)=rout; rout*=vapf1+R16(mrapf1);
- lout-=vapf2*R16(mlapf2); R16(mlapf2)=lout; lout*=vapf2+R16(mlapf2);
- rout-=vapf2*R16(mrapf2); R16(mrapf2)=rout; rout*=vapf2+R16(mrapf2);
+ lout = CLAMP(lout, -0x8000, 0x7fff);
+ rout = CLAMP(rout, -0x8000, 0x7fff);
+ lout-=CLAMP(vapf1*R16(mlapf1 - dapf1), -0x8000, 0x7fff); W16(mlapf1, lout); lout*=vapf1+((float)R16(mlapf1 - dapf1) / 32767.0f);
+ rout-=CLAMP(vapf1*R16(mrapf1 - dapf1), -0x8000, 0x7fff); W16(mrapf1, rout); rout*=vapf1+((float)R16(mrapf1 - dapf1) / 32767.0f);
+ lout-=CLAMP(vapf2*R16(mlapf2 - dapf2), -0x8000, 0x7fff); W16(mlapf2, lout); lout*=vapf2+((float)R16(mlapf2 - dapf2) / 32767.0f);
+ rout-=CLAMP(vapf2*R16(mrapf2 - dapf2), -0x8000, 0x7fff); W16(mrapf2, rout); rout*=vapf2+((float)R16(mrapf2 - dapf2) / 32767.0f);
+
*outl = lout * vlout;
*outr = rout * vrout;
@@ -488,6 +519,7 @@
uint32_t psx_spu_get_sample(psx_spu_t* spu) {spu->even_cycle ^= 1;
+
int active_voice_count = 0;
int left = 0;
int right = 0;
@@ -577,13 +609,20 @@
if (!active_voice_count)
return 0x00000000;
+
+ int rsl = spu->lrsl;
+ int rsr = spu->lrsr;
// To-do: Fix reverb
- // if ((spu->spucnt & 0x0080) && spu->even_cycle)
- // spu_get_reverb_sample(spu, revl, revr, &spu->lrsl, &spu->lrsr);
+ if ((spu->spucnt & 0x0080) && spu->even_cycle) {+ spu_get_reverb_sample(spu, revl, revr, &rsl, &rsr);
- uint16_t clampl = CLAMP(left, INT16_MIN, INT16_MAX);
- uint16_t clampr = CLAMP(right, INT16_MIN, INT16_MAX);
+ spu->lrsl = rsl;
+ spu->lrsr = rsr;
+ }
+
+ uint16_t clampl = CLAMP(left + spu->lrsl, INT16_MIN, INT16_MAX);
+ uint16_t clampr = CLAMP(right + spu->lrsr, INT16_MIN, INT16_MAX);
return clampl | (((uint32_t)clampr) << 16);
}
--
⑨