From 2dbad870056d6b7760ae549215bb694b2f9e102e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 26 Jul 2015 15:23:11 +0200 Subject: [PATCH] Cleanups --- mednafen/psx/spu.cpp | 181 +++++++++++++++++++++++++++++++++++- mednafen/psx/spu_reverb.inc | 180 ----------------------------------- 2 files changed, 180 insertions(+), 181 deletions(-) delete mode 100644 mednafen/psx/spu_reverb.inc diff --git a/mednafen/psx/spu.cpp b/mednafen/psx/spu.cpp index c9b2a7ae..1027a779 100644 --- a/mednafen/psx/spu.cpp +++ b/mednafen/psx/spu.cpp @@ -569,7 +569,186 @@ INLINE uint16 PS_SPU::ReadSPURAM(uint32 addr) return(SPURAM[addr]); } -#include "spu_reverb.inc" +static INLINE int16 ReverbSat(int32 samp) +{ + if(samp > 32767) + samp = 32767; + + if(samp < -32768) + samp = -32768; + + return(samp); +} + + +INLINE uint32 PS_SPU::Get_Reverb_Offset(uint32 in_offset) +{ + uint32 offset = ReverbCur + (in_offset & 0x3FFFF); + + offset += ReverbWA & ((int32)(offset << 13) >> 31); + offset &= 0x3FFFF; + + // For debugging in case there are any problems with games misprogramming the reverb registers in a race-conditiony manner that + // causes important data in SPU RAM to be trashed: + //if(offset < ReverbWA) + // printf("BARF: offset=%05x reverbwa=%05x reverbcur=%05x in_offset=%05x\n", offset, ReverbWA, ReverbCur, in_offset & 0x3FFFF); + + return(offset); +} + +int16 NO_INLINE PS_SPU::RD_RVB(uint16 raw_offs, int32 extra_offs) +{ + return ReadSPURAM(Get_Reverb_Offset((raw_offs << 2) + extra_offs)); +} + +void NO_INLINE PS_SPU::WR_RVB(uint16 raw_offs, int16 sample) +{ + WriteSPURAM(Get_Reverb_Offset(raw_offs << 2), sample); +} + +// +// Zeroes optimized out; middle removed too(it's 16384) +static const int16 ResampTable[20] = +{ + -1, 2, -10, 35, -103, 266, -616, 1332, -2960, 10246, 10246, -2960, 1332, -616, 266, -103, 35, -10, 2, -1, +}; + +static INLINE int32 Reverb4422(const int16 *src) +{ + int32 out = 0; // 32-bits is adequate(it won't overflow) + + for(unsigned i = 0; i < 20; i++) + out += ResampTable[i] * src[i * 2]; + + // Middle non-zero + out += 0x4000 * src[19]; + + out >>= 15; + + clamp(&out, -32768, 32767); + + return(out); +} + +static INLINE int32 Reverb2244(const int16 *src) +{ + unsigned i; + int32_t out = 0; /* 32bits is adequate (it won't overflow) */ + + for(i = 0; i < 20; i++) + out += ResampTable[i] * src[i]; + + out >>= 14; + + clamp(&out, -32768, 32767); + + return out; +} + +static int32 IIASM(const int16 IIR_ALPHA, const int16 insamp) +{ + if(MDFN_UNLIKELY(IIR_ALPHA == -32768)) + { + if(insamp == -32768) + return 0; + return insamp * -65536; + } + + return insamp * (32768 - IIR_ALPHA); +} + +// +// Take care to thoroughly test the reverb resampling code when modifying anything that uses RvbResPos. +// +void PS_SPU::RunReverb(const int32* in, int32* out) +{ + int32 upsampled[2] = { 0, 0 }; + + for(unsigned lr = 0; lr < 2; lr++) + { + RDSB[lr][RvbResPos | 0x00] = in[lr]; + RDSB[lr][RvbResPos | 0x40] = in[lr]; // So we don't have to &/bounds check in our MAC loop + } + + if(RvbResPos & 1) + { + int32 downsampled[2]; + + for(unsigned lr = 0; lr < 2; lr++) + downsampled[lr] = Reverb4422(&RDSB[lr][(RvbResPos - 39) & 0x3F]); + + /* Run algorithm */ + if(SPUControl & 0x80) + { + int16 ACC0, ACC1; + int16 FB_A0, FB_A1, FB_B0, FB_B1; + + int16 IIR_INPUT_A0 = ReverbSat(((RD_RVB(IIR_SRC_A0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15)); + int16 IIR_INPUT_A1 = ReverbSat(((RD_RVB(IIR_SRC_A1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15)); + int16 IIR_INPUT_B0 = ReverbSat(((RD_RVB(IIR_SRC_B0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15)); + int16 IIR_INPUT_B1 = ReverbSat(((RD_RVB(IIR_SRC_B1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15)); + + int16 IIR_A0 = ReverbSat((((IIR_INPUT_A0 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A0, -1)) >> 14)) >> 1); + int16 IIR_A1 = ReverbSat((((IIR_INPUT_A1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A1, -1)) >> 14)) >> 1); + int16 IIR_B0 = ReverbSat((((IIR_INPUT_B0 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B0, -1)) >> 14)) >> 1); + int16 IIR_B1 = ReverbSat((((IIR_INPUT_B1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B1, -1)) >> 14)) >> 1); + + WR_RVB(IIR_DEST_A0, IIR_A0); + WR_RVB(IIR_DEST_A1, IIR_A1); + WR_RVB(IIR_DEST_B0, IIR_B0); + WR_RVB(IIR_DEST_B1, IIR_B1); + + ACC0 = ReverbSat((((RD_RVB(ACC_SRC_A0) * ACC_COEF_A) >> 14) + + ((RD_RVB(ACC_SRC_B0) * ACC_COEF_B) >> 14) + + ((RD_RVB(ACC_SRC_C0) * ACC_COEF_C) >> 14) + + ((RD_RVB(ACC_SRC_D0) * ACC_COEF_D) >> 14)) >> 1); + + ACC1 = ReverbSat((((RD_RVB(ACC_SRC_A1) * ACC_COEF_A) >> 14) + + ((RD_RVB(ACC_SRC_B1) * ACC_COEF_B) >> 14) + + ((RD_RVB(ACC_SRC_C1) * ACC_COEF_C) >> 14) + + ((RD_RVB(ACC_SRC_D1) * ACC_COEF_D) >> 14)) >> 1); + + FB_A0 = RD_RVB(MIX_DEST_A0 - FB_SRC_A); + FB_A1 = RD_RVB(MIX_DEST_A1 - FB_SRC_A); + FB_B0 = RD_RVB(MIX_DEST_B0 - FB_SRC_B); + FB_B1 = RD_RVB(MIX_DEST_B1 - FB_SRC_B); + + WR_RVB(MIX_DEST_A0, ReverbSat(ACC0 - ((FB_A0 * FB_ALPHA) >> 15))); + WR_RVB(MIX_DEST_A1, ReverbSat(ACC1 - ((FB_A1 * FB_ALPHA) >> 15))); + + WR_RVB(MIX_DEST_B0, ReverbSat(((FB_ALPHA * ACC0) >> 15) - ((FB_A0 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B0 * FB_X) >> 15))); + WR_RVB(MIX_DEST_B1, ReverbSat(((FB_ALPHA * ACC1) >> 15) - ((FB_A1 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B1 * FB_X) >> 15))); + } + + /* Get output samplesq */ + RUSB[0][(RvbResPos >> 1) | 0x20] = RUSB[0][RvbResPos >> 1] = (RD_RVB(MIX_DEST_A0) + RD_RVB(MIX_DEST_B0)) >> 1; + RUSB[1][(RvbResPos >> 1) | 0x20] = RUSB[1][RvbResPos >> 1] = (RD_RVB(MIX_DEST_A1) + RD_RVB(MIX_DEST_B1)) >> 1; + + ReverbCur = (ReverbCur + 1) & 0x3FFFF; + if(!ReverbCur) + ReverbCur = ReverbWA; + + for(unsigned lr = 0; lr < 2; lr++) + { + const int16 *src = &RUSB[lr][((RvbResPos - 39) & 0x3F) >> 1]; + upsampled[lr] = src[9]; /* Reverb 2244 (Middle non-zero */ + } + } + else + { + for(unsigned lr = 0; lr < 2; lr++) + { + const int16 *src = &RUSB[lr][((RvbResPos - 39) & 0x3F) >> 1]; + upsampled[lr] = Reverb2244(src); + } + } + + RvbResPos = (RvbResPos + 1) & 0x3F; + + for(unsigned lr = 0; lr < 2; lr++) + out[lr] = upsampled[lr]; +} + INLINE void PS_SPU::RunNoise(void) { diff --git a/mednafen/psx/spu_reverb.inc b/mednafen/psx/spu_reverb.inc deleted file mode 100644 index e6044692..00000000 --- a/mednafen/psx/spu_reverb.inc +++ /dev/null @@ -1,180 +0,0 @@ -static INLINE int16 ReverbSat(int32 samp) -{ - if(samp > 32767) - samp = 32767; - - if(samp < -32768) - samp = -32768; - - return(samp); -} - - -INLINE uint32 PS_SPU::Get_Reverb_Offset(uint32 in_offset) -{ - uint32 offset = ReverbCur + (in_offset & 0x3FFFF); - - offset += ReverbWA & ((int32)(offset << 13) >> 31); - offset &= 0x3FFFF; - - // For debugging in case there are any problems with games misprogramming the reverb registers in a race-conditiony manner that - // causes important data in SPU RAM to be trashed: - //if(offset < ReverbWA) - // printf("BARF: offset=%05x reverbwa=%05x reverbcur=%05x in_offset=%05x\n", offset, ReverbWA, ReverbCur, in_offset & 0x3FFFF); - - return(offset); -} - -int16 NO_INLINE PS_SPU::RD_RVB(uint16 raw_offs, int32 extra_offs) -{ - return ReadSPURAM(Get_Reverb_Offset((raw_offs << 2) + extra_offs)); -} - -void NO_INLINE PS_SPU::WR_RVB(uint16 raw_offs, int16 sample) -{ - WriteSPURAM(Get_Reverb_Offset(raw_offs << 2), sample); -} - -// -// Zeroes optimized out; middle removed too(it's 16384) -static const int16 ResampTable[20] = -{ - -1, 2, -10, 35, -103, 266, -616, 1332, -2960, 10246, 10246, -2960, 1332, -616, 266, -103, 35, -10, 2, -1, -}; - -static INLINE int32 Reverb4422(const int16 *src) -{ - int32 out = 0; // 32-bits is adequate(it won't overflow) - - for(unsigned i = 0; i < 20; i++) - out += ResampTable[i] * src[i * 2]; - - // Middle non-zero - out += 0x4000 * src[19]; - - out >>= 15; - - clamp(&out, -32768, 32767); - - return(out); -} - -static INLINE int32 Reverb2244(const int16 *src) -{ - unsigned i; - int32_t out = 0; /* 32bits is adequate (it won't overflow) */ - - for(i = 0; i < 20; i++) - out += ResampTable[i] * src[i]; - - out >>= 14; - - clamp(&out, -32768, 32767); - - return out; -} - -static int32 IIASM(const int16 IIR_ALPHA, const int16 insamp) -{ - if(MDFN_UNLIKELY(IIR_ALPHA == -32768)) - { - if(insamp == -32768) - return 0; - return insamp * -65536; - } - - return insamp * (32768 - IIR_ALPHA); -} - -// -// Take care to thoroughly test the reverb resampling code when modifying anything that uses RvbResPos. -// -void PS_SPU::RunReverb(const int32* in, int32* out) -{ - int32 upsampled[2] = { 0, 0 }; - - for(unsigned lr = 0; lr < 2; lr++) - { - RDSB[lr][RvbResPos | 0x00] = in[lr]; - RDSB[lr][RvbResPos | 0x40] = in[lr]; // So we don't have to &/bounds check in our MAC loop - } - - if(RvbResPos & 1) - { - int32 downsampled[2]; - - for(unsigned lr = 0; lr < 2; lr++) - downsampled[lr] = Reverb4422(&RDSB[lr][(RvbResPos - 39) & 0x3F]); - - /* Run algorithm */ - if(SPUControl & 0x80) - { - int16 ACC0, ACC1; - int16 FB_A0, FB_A1, FB_B0, FB_B1; - - int16 IIR_INPUT_A0 = ReverbSat(((RD_RVB(IIR_SRC_A0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15)); - int16 IIR_INPUT_A1 = ReverbSat(((RD_RVB(IIR_SRC_A1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15)); - int16 IIR_INPUT_B0 = ReverbSat(((RD_RVB(IIR_SRC_B0) * IIR_COEF) >> 15) + ((downsampled[0] * IN_COEF_L) >> 15)); - int16 IIR_INPUT_B1 = ReverbSat(((RD_RVB(IIR_SRC_B1) * IIR_COEF) >> 15) + ((downsampled[1] * IN_COEF_R) >> 15)); - - int16 IIR_A0 = ReverbSat((((IIR_INPUT_A0 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A0, -1)) >> 14)) >> 1); - int16 IIR_A1 = ReverbSat((((IIR_INPUT_A1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_A1, -1)) >> 14)) >> 1); - int16 IIR_B0 = ReverbSat((((IIR_INPUT_B0 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B0, -1)) >> 14)) >> 1); - int16 IIR_B1 = ReverbSat((((IIR_INPUT_B1 * IIR_ALPHA) >> 14) + (IIASM(IIR_ALPHA, RD_RVB(IIR_DEST_B1, -1)) >> 14)) >> 1); - - WR_RVB(IIR_DEST_A0, IIR_A0); - WR_RVB(IIR_DEST_A1, IIR_A1); - WR_RVB(IIR_DEST_B0, IIR_B0); - WR_RVB(IIR_DEST_B1, IIR_B1); - - ACC0 = ReverbSat((((RD_RVB(ACC_SRC_A0) * ACC_COEF_A) >> 14) + - ((RD_RVB(ACC_SRC_B0) * ACC_COEF_B) >> 14) + - ((RD_RVB(ACC_SRC_C0) * ACC_COEF_C) >> 14) + - ((RD_RVB(ACC_SRC_D0) * ACC_COEF_D) >> 14)) >> 1); - - ACC1 = ReverbSat((((RD_RVB(ACC_SRC_A1) * ACC_COEF_A) >> 14) + - ((RD_RVB(ACC_SRC_B1) * ACC_COEF_B) >> 14) + - ((RD_RVB(ACC_SRC_C1) * ACC_COEF_C) >> 14) + - ((RD_RVB(ACC_SRC_D1) * ACC_COEF_D) >> 14)) >> 1); - - FB_A0 = RD_RVB(MIX_DEST_A0 - FB_SRC_A); - FB_A1 = RD_RVB(MIX_DEST_A1 - FB_SRC_A); - FB_B0 = RD_RVB(MIX_DEST_B0 - FB_SRC_B); - FB_B1 = RD_RVB(MIX_DEST_B1 - FB_SRC_B); - - WR_RVB(MIX_DEST_A0, ReverbSat(ACC0 - ((FB_A0 * FB_ALPHA) >> 15))); - WR_RVB(MIX_DEST_A1, ReverbSat(ACC1 - ((FB_A1 * FB_ALPHA) >> 15))); - - WR_RVB(MIX_DEST_B0, ReverbSat(((FB_ALPHA * ACC0) >> 15) - ((FB_A0 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B0 * FB_X) >> 15))); - WR_RVB(MIX_DEST_B1, ReverbSat(((FB_ALPHA * ACC1) >> 15) - ((FB_A1 * (int16)(0x8000 ^ FB_ALPHA)) >> 15) - ((FB_B1 * FB_X) >> 15))); - } - - /* Get output samplesq */ - RUSB[0][(RvbResPos >> 1) | 0x20] = RUSB[0][RvbResPos >> 1] = (RD_RVB(MIX_DEST_A0) + RD_RVB(MIX_DEST_B0)) >> 1; - RUSB[1][(RvbResPos >> 1) | 0x20] = RUSB[1][RvbResPos >> 1] = (RD_RVB(MIX_DEST_A1) + RD_RVB(MIX_DEST_B1)) >> 1; - - ReverbCur = (ReverbCur + 1) & 0x3FFFF; - if(!ReverbCur) - ReverbCur = ReverbWA; - - for(unsigned lr = 0; lr < 2; lr++) - { - const int16 *src = &RUSB[lr][((RvbResPos - 39) & 0x3F) >> 1]; - upsampled[lr] = src[9]; /* Reverb 2244 (Middle non-zero */ - } - } - else - { - for(unsigned lr = 0; lr < 2; lr++) - { - const int16 *src = &RUSB[lr][((RvbResPos - 39) & 0x3F) >> 1]; - upsampled[lr] = Reverb2244(src); - } - } - - RvbResPos = (RvbResPos + 1) & 0x3F; - - for(unsigned lr = 0; lr < 2; lr++) - out[lr] = upsampled[lr]; -} -