aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS11
-rw-r--r--pandora/readme.txt11
-rw-r--r--plugins/dfsound/externals.h19
-rw-r--r--plugins/dfsound/registers.c60
-rw-r--r--plugins/dfsound/reverb.c372
-rw-r--r--plugins/dfsound/reverb.h19
-rw-r--r--plugins/dfsound/spu.c45
7 files changed, 259 insertions, 278 deletions
diff --git a/AUTHORS b/AUTHORS
index 3e943e3..a9a361c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -36,11 +36,16 @@ GLES plugin (psx4m project):
Proger
Pickle
-builtin GPU/SPU plugins:
- Pete Bernert and the P.E.Op.S. team
+builtin GPU plugin:
+ (C) Pete Bernert and the P.E.Op.S. team
+
+builtin SPU plugin:
+ (C) Pete Bernert and the P.E.Op.S. team
+ (C) SPU2-X, gigaherz, Pcsx2 Development Team
+ shalma
MIPS->ARM recompiler:
- (C) 2009-2010 Ari64
+ (C) 2009-2011 Ari64
integration, optimization and frontend:
(C) 2010-2011 notaz
diff --git a/pandora/readme.txt b/pandora/readme.txt
index 2963867..db42e9f 100644
--- a/pandora/readme.txt
+++ b/pandora/readme.txt
@@ -202,11 +202,16 @@ GLES plugin (psx4m project):
Proger
Pickle
-builtin GPU/SPU plugins:
- Pete Bernert and the P.E.Op.S. team
+builtin GPU/SPU plugin:
+ (C) Pete Bernert and the P.E.Op.S. team
+
+builtin SPU plugin:
+ (C) Pete Bernert and the P.E.Op.S. team
+ (C) SPU2-X, gigaherz, Pcsx2 Development Team
+ shalma
MIPS->ARM recompiler:
- (C) 2009-2010 Ari64
+ (C) 2009-2011 Ari64
integration, optimization and frontend:
(C) 2010-2011 notaz
diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h
index 2ccc811..73134d0 100644
--- a/plugins/dfsound/externals.h
+++ b/plugins/dfsound/externals.h
@@ -45,7 +45,8 @@
#define MAXCHAN 24
// ~ 1 ms of data
-#define NSSIZE 45
+// note: must be even due to the way reverb works now
+#define NSSIZE 46
///////////////////////////////////////////////////////////
// struct defines
@@ -142,8 +143,6 @@ typedef struct
int VolLeft;
int VolRight;
- int iLastRVBLeft;
- int iLastRVBRight;
int iRVBLeft;
int iRVBRight;
@@ -179,6 +178,17 @@ typedef struct
int MIX_DEST_B1; // (offset)
int IN_COEF_L; // (coef.)
int IN_COEF_R; // (coef.)
+
+ int dirty; // registers changed
+
+ // normalized offsets
+ int nIIR_DEST_A0, nIIR_DEST_A1, nIIR_DEST_B0, nIIR_DEST_B1,
+ nACC_SRC_A0, nACC_SRC_A1, nACC_SRC_B0, nACC_SRC_B1,
+ nIIR_SRC_A0, nIIR_SRC_A1, nIIR_SRC_B0, nIIR_SRC_B1,
+ nACC_SRC_C0, nACC_SRC_C1, nACC_SRC_D0, nACC_SRC_D1,
+ nMIX_DEST_A0, nMIX_DEST_A1, nMIX_DEST_B0, nMIX_DEST_B1;
+ // MIX_DEST_xx - FB_SRC_x
+ int nFB_SRC_A0, nFB_SRC_A1, nFB_SRC_B0, nFB_SRC_B1;
} REVERBInfo;
///////////////////////////////////////////////////////////
@@ -268,8 +278,5 @@ extern int iRightXAVol;
extern int * sRVBPlay;
extern int * sRVBEnd;
extern int * sRVBStart;
-extern int iReverbOff;
-extern int iReverbRepeat;
-extern int iReverbNum;
#endif
diff --git a/plugins/dfsound/registers.c b/plugins/dfsound/registers.c
index 87f7558..83b9e43 100644
--- a/plugins/dfsound/registers.c
+++ b/plugins/dfsound/registers.c
@@ -22,7 +22,6 @@
#include "externals.h"
#include "registers.h"
#include "regs.h"
-#include "reverb.h"
/*
// adsr time values (in ms) by James Higgs ... see the end of
@@ -212,6 +211,7 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val)
rvb.CurrAddr=rvb.StartAddr;
}
}
+ rvb.dirty = 1;
break;
//-------------------------------------------------//
case H_SPUirqAddr:
@@ -303,19 +303,8 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val)
ReverbOn(16,24,val);
break;
//-------------------------------------------------//
- case H_Reverb+0:
-
- rvb.FB_SRC_A=val;
-
- // OK, here's the fake REVERB stuff...
- // depending on effect we do more or less delay and repeats... bah
- // still... better than nothing :)
-
- SetREVERB(val);
- break;
-
-
- case H_Reverb+2 : rvb.FB_SRC_B=(short)val; break;
+ case H_Reverb+0 : rvb.FB_SRC_A=val*4; break;
+ case H_Reverb+2 : rvb.FB_SRC_B=val*4; break;
case H_Reverb+4 : rvb.IIR_ALPHA=(short)val; break;
case H_Reverb+6 : rvb.ACC_COEF_A=(short)val; break;
case H_Reverb+8 : rvb.ACC_COEF_B=(short)val; break;
@@ -324,30 +313,33 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val)
case H_Reverb+14 : rvb.IIR_COEF=(short)val; break;
case H_Reverb+16 : rvb.FB_ALPHA=(short)val; break;
case H_Reverb+18 : rvb.FB_X=(short)val; break;
- case H_Reverb+20 : rvb.IIR_DEST_A0=(short)val; break;
- case H_Reverb+22 : rvb.IIR_DEST_A1=(short)val; break;
- case H_Reverb+24 : rvb.ACC_SRC_A0=(short)val; break;
- case H_Reverb+26 : rvb.ACC_SRC_A1=(short)val; break;
- case H_Reverb+28 : rvb.ACC_SRC_B0=(short)val; break;
- case H_Reverb+30 : rvb.ACC_SRC_B1=(short)val; break;
- case H_Reverb+32 : rvb.IIR_SRC_A0=(short)val; break;
- case H_Reverb+34 : rvb.IIR_SRC_A1=(short)val; break;
- case H_Reverb+36 : rvb.IIR_DEST_B0=(short)val; break;
- case H_Reverb+38 : rvb.IIR_DEST_B1=(short)val; break;
- case H_Reverb+40 : rvb.ACC_SRC_C0=(short)val; break;
- case H_Reverb+42 : rvb.ACC_SRC_C1=(short)val; break;
- case H_Reverb+44 : rvb.ACC_SRC_D0=(short)val; break;
- case H_Reverb+46 : rvb.ACC_SRC_D1=(short)val; break;
- case H_Reverb+48 : rvb.IIR_SRC_B1=(short)val; break;
- case H_Reverb+50 : rvb.IIR_SRC_B0=(short)val; break;
- case H_Reverb+52 : rvb.MIX_DEST_A0=(short)val; break;
- case H_Reverb+54 : rvb.MIX_DEST_A1=(short)val; break;
- case H_Reverb+56 : rvb.MIX_DEST_B0=(short)val; break;
- case H_Reverb+58 : rvb.MIX_DEST_B1=(short)val; break;
+ case H_Reverb+20 : rvb.IIR_DEST_A0=val*4; break;
+ case H_Reverb+22 : rvb.IIR_DEST_A1=val*4; break;
+ case H_Reverb+24 : rvb.ACC_SRC_A0=val*4; break;
+ case H_Reverb+26 : rvb.ACC_SRC_A1=val*4; break;
+ case H_Reverb+28 : rvb.ACC_SRC_B0=val*4; break;
+ case H_Reverb+30 : rvb.ACC_SRC_B1=val*4; break;
+ case H_Reverb+32 : rvb.IIR_SRC_A0=val*4; break;
+ case H_Reverb+34 : rvb.IIR_SRC_A1=val*4; break;
+ case H_Reverb+36 : rvb.IIR_DEST_B0=val*4; break;
+ case H_Reverb+38 : rvb.IIR_DEST_B1=val*4; break;
+ case H_Reverb+40 : rvb.ACC_SRC_C0=val*4; break;
+ case H_Reverb+42 : rvb.ACC_SRC_C1=val*4; break;
+ case H_Reverb+44 : rvb.ACC_SRC_D0=val*4; break;
+ case H_Reverb+46 : rvb.ACC_SRC_D1=val*4; break;
+ case H_Reverb+48 : rvb.IIR_SRC_B1=val*4; break;
+ case H_Reverb+50 : rvb.IIR_SRC_B0=val*4; break;
+ case H_Reverb+52 : rvb.MIX_DEST_A0=val*4; break;
+ case H_Reverb+54 : rvb.MIX_DEST_A1=val*4; break;
+ case H_Reverb+56 : rvb.MIX_DEST_B0=val*4; break;
+ case H_Reverb+58 : rvb.MIX_DEST_B1=val*4; break;
case H_Reverb+60 : rvb.IN_COEF_L=(short)val; break;
case H_Reverb+62 : rvb.IN_COEF_R=(short)val; break;
}
+ if ((r & ~0x3f) == H_Reverb)
+ rvb.dirty = 1; // recalculate on next update
+
iSpuAsyncWait=0;
}
diff --git a/plugins/dfsound/reverb.c b/plugins/dfsound/reverb.c
index 343c979..2d65a69 100644
--- a/plugins/dfsound/reverb.c
+++ b/plugins/dfsound/reverb.c
@@ -4,6 +4,10 @@
begin : Wed May 15 2002
copyright : (C) 2002 by Pete Bernert
email : BlackDove@addcom.de
+
+ Portions (C) GraÅžvydas "notaz" Ignotas, 2010-2011
+ Portions (C) SPU2-X, gigaherz, Pcsx2 Development Team
+
***************************************************************************/
/***************************************************************************
* *
@@ -31,32 +35,6 @@
int * sRVBPlay = 0;
int * sRVBEnd = 0;
int * sRVBStart = 0;
-int iReverbOff = -1; // some delay factor for reverb
-int iReverbRepeat = 0;
-int iReverbNum = 1;
-
-////////////////////////////////////////////////////////////////////////
-// SET REVERB
-////////////////////////////////////////////////////////////////////////
-
-void SetREVERB(unsigned short val)
-{
- switch(val)
- {
- case 0x0000: iReverbOff=-1; break; // off
- case 0x007D: iReverbOff=32; iReverbNum=2; iReverbRepeat=128; break; // ok room
-
- case 0x0033: iReverbOff=32; iReverbNum=2; iReverbRepeat=64; break; // studio small
- case 0x00B1: iReverbOff=48; iReverbNum=2; iReverbRepeat=96; break; // ok studio medium
- case 0x00E3: iReverbOff=64; iReverbNum=2; iReverbRepeat=128; break; // ok studio large ok
-
- case 0x01A5: iReverbOff=128; iReverbNum=4; iReverbRepeat=32; break; // ok hall
- case 0x033D: iReverbOff=256; iReverbNum=4; iReverbRepeat=64; break; // space echo
- case 0x0001: iReverbOff=184; iReverbNum=3; iReverbRepeat=128; break; // echo/delay
- case 0x0017: iReverbOff=128; iReverbNum=2; iReverbRepeat=128; break; // half echo
- default: iReverbOff=32; iReverbNum=1; iReverbRepeat=0; break;
- }
-}
////////////////////////////////////////////////////////////////////////
// START REVERB
@@ -66,15 +44,7 @@ INLINE void StartREVERB(int ch)
{
if(s_chan[ch].bReverb && (spuCtrl&0x80)) // reverb possible?
{
- if(iUseReverb==2) s_chan[ch].bRVBActive=1;
- else
- if(iUseReverb==1 && iReverbOff>0) // -> fake reverb used?
- {
- s_chan[ch].bRVBActive=1; // -> activate it
- s_chan[ch].iRVBOffset=iReverbOff*45;
- s_chan[ch].iRVBRepeat=iReverbRepeat*45;
- s_chan[ch].iRVBNum =iReverbNum;
- }
+ s_chan[ch].bRVBActive=!!iUseReverb;
}
else s_chan[ch].bRVBActive=0; // else -> no reverb
}
@@ -85,199 +55,198 @@ INLINE void StartREVERB(int ch)
INLINE void InitREVERB(void)
{
- if(iUseReverb==2)
- {memset(sRVBStart,0,NSSIZE*2*4);}
+ memset(sRVBStart,0,NSSIZE*2*4);
}
////////////////////////////////////////////////////////////////////////
// STORE REVERB
////////////////////////////////////////////////////////////////////////
-INLINE void StoreREVERB(int ch,int ns,int sval)
+INLINE void StoreREVERB(int ch,int ns,int l,int r)
{
- if(iUseReverb==0) return;
- else
- if(iUseReverb==2) // -------------------------------- // Neil's reverb
- {
- const int iRxl=(sval*s_chan[ch].iLeftVolume)/0x4000;
- const int iRxr=(sval*s_chan[ch].iRightVolume)/0x4000;
+ ns<<=1;
- ns<<=1;
-
- *(sRVBStart+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer
- *(sRVBStart+ns+1)+=iRxr;
- }
- else // --------------------------------------------- // Pete's easy fake reverb
- {
- int * pN;int iRn,iRr=0;
-
- // we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on
-
- int iRxl=(sval*s_chan[ch].iLeftVolume)/0x8000;
- int iRxr=(sval*s_chan[ch].iRightVolume)/0x8000;
-
- for(iRn=1;iRn<=s_chan[ch].iRVBNum;iRn++,iRr+=s_chan[ch].iRVBRepeat,iRxl/=2,iRxr/=2)
- {
- pN=sRVBPlay+((s_chan[ch].iRVBOffset+iRr+ns)<<1);
- if(pN>=sRVBEnd) pN=sRVBStart+(pN-sRVBEnd);
-
- (*pN)+=iRxl;
- pN++;
- (*pN)+=iRxr;
- }
- }
+ sRVBStart[ns] +=l; // -> we mix all active reverb channels into an extra buffer
+ sRVBStart[ns+1]+=r;
}
////////////////////////////////////////////////////////////////////////
-INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps
+INLINE int rvb2ram_offs(int curr, int space, int iOff)
{
- short * p=(short *)spuMem;
- iOff=(iOff*4)+rvb.CurrAddr;
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
- return (int)*(p+iOff);
+ iOff += curr;
+ if (iOff >= 0x40000) iOff -= space;
+ return iOff;
}
-////////////////////////////////////////////////////////////////////////
+// get_buffer content helper: takes care about wraps
+#define g_buffer(var) \
+ ((int)(signed short)spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var)])
-INLINE void s_buffer(int iOff,int iVal) // set_buffer content helper: takes care about wraps and clipping
-{
- short * p=(short *)spuMem;
- iOff=(iOff*4)+rvb.CurrAddr;
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
- if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
- *(p+iOff)=(short)iVal;
-}
-
-////////////////////////////////////////////////////////////////////////
+// saturate iVal and store it as var
+#define s_buffer(var, iVal) \
+ ssat32_to_16(iVal); \
+ spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var)] = iVal
-INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping
-{
- short * p=(short *)spuMem;
- iOff=(iOff*4)+rvb.CurrAddr+1;
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
- if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;
- *(p+iOff)=(short)iVal;
-}
+#define s_buffer1(var, iVal) \
+ ssat32_to_16(iVal); \
+ spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var + 1)] = iVal
////////////////////////////////////////////////////////////////////////
-INLINE int MixREVERBLeft(int ns)
+// portions based on spu2-x from PCSX2
+static void MixREVERB(void)
{
- if(iUseReverb==0) return 0;
- else
- if(iUseReverb==2)
- {
- static int iCnt=0; // this func will be called with 44.1 khz
-
- if(!rvb.StartAddr) // reverb is off
- {
- rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0;
- return 0;
- }
-
- iCnt++;
-
- if(iCnt&1) // we work on every second left value: downsample to 22 khz
- {
- if(spuCtrl&0x80) // -> reverb on? oki
- {
- int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
-
- const int INPUT_SAMPLE_L=*(sRVBStart+(ns<<1));
- const int INPUT_SAMPLE_R=*(sRVBStart+(ns<<1)+1);
-
- const int IIR_INPUT_A0 = (g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L;
- const int IIR_INPUT_A1 = (g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L;
- const int IIR_INPUT_B0 = (g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L;
- const int IIR_INPUT_B1 = (g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L;
-
- const int IIR_A0 = (IIR_INPUT_A0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))/32768L;
- const int IIR_A1 = (IIR_INPUT_A1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))/32768L;
- const int IIR_B0 = (IIR_INPUT_B0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))/32768L;
- const int IIR_B1 = (IIR_INPUT_B1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))/32768L;
-
- s_buffer1(rvb.IIR_DEST_A0, IIR_A0);
- s_buffer1(rvb.IIR_DEST_A1, IIR_A1);
- s_buffer1(rvb.IIR_DEST_B0, IIR_B0);
- s_buffer1(rvb.IIR_DEST_B1, IIR_B1);
-
- ACC0 = (g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)/32768L +
- (g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)/32768L +
- (g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)/32768L +
- (g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)/32768L;
- ACC1 = (g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)/32768L +
- (g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)/32768L +
- (g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)/32768L +
- (g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)/32768L;
-
- FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A);
- FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A);
- FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B);
- FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B);
-
- s_buffer(rvb.MIX_DEST_A0, ACC0 - (FB_A0 * rvb.FB_ALPHA)/32768L);
- s_buffer(rvb.MIX_DEST_A1, ACC1 - (FB_A1 * rvb.FB_ALPHA)/32768L);
-
- s_buffer(rvb.MIX_DEST_B0, (rvb.FB_ALPHA * ACC0)/32768L - (FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B0 * rvb.FB_X)/32768L);
- s_buffer(rvb.MIX_DEST_B1, (rvb.FB_ALPHA * ACC1)/32768L - (FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))/32768L - (FB_B1 * rvb.FB_X)/32768L);
-
- rvb.iLastRVBLeft = rvb.iRVBLeft;
- rvb.iLastRVBRight = rvb.iRVBRight;
-
- rvb.iRVBLeft = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3;
- rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3;
-
- rvb.iRVBLeft = (rvb.iRVBLeft * rvb.VolLeft) / 0x4000;
- rvb.iRVBRight = (rvb.iRVBRight * rvb.VolRight) / 0x4000;
-
- rvb.CurrAddr++;
- if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
-
- return rvb.iLastRVBLeft+(rvb.iRVBLeft-rvb.iLastRVBLeft)/2;
- }
- else // -> reverb off
- {
- rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0;
- }
-
- rvb.CurrAddr++;
- if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
- }
-
- return rvb.iLastRVBLeft;
- }
- else // easy fake reverb:
+ int l_old = rvb.iRVBLeft;
+ int r_old = rvb.iRVBRight;
+ int curr_addr = rvb.CurrAddr;
+ int space = 0x40000 - rvb.StartAddr;
+ int l, r, ns;
+
+ for (ns = 0; ns < NSSIZE*2; )
{
- const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value
- *sRVBPlay++=0; // -> init it after
- if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds
- return iRV; // -> return reverb mix buf val
+ int IIR_ALPHA = rvb.IIR_ALPHA;
+ int ACC0, ACC1, FB_A0, FB_A1, FB_B0, FB_B1;
+ int mix_dest_a0, mix_dest_a1, mix_dest_b0, mix_dest_b1;
+
+ int input_L = sRVBStart[ns] * rvb.IN_COEF_L;
+ int input_R = sRVBStart[ns+1] * rvb.IN_COEF_R;
+
+ int IIR_INPUT_A0 = ((g_buffer(IIR_SRC_A0) * rvb.IIR_COEF) + input_L) >> 15;
+ int IIR_INPUT_A1 = ((g_buffer(IIR_SRC_A1) * rvb.IIR_COEF) + input_R) >> 15;
+ int IIR_INPUT_B0 = ((g_buffer(IIR_SRC_B0) * rvb.IIR_COEF) + input_L) >> 15;
+ int IIR_INPUT_B1 = ((g_buffer(IIR_SRC_B1) * rvb.IIR_COEF) + input_R) >> 15;
+
+ int iir_dest_a0 = g_buffer(IIR_DEST_A0);
+ int iir_dest_a1 = g_buffer(IIR_DEST_A1);
+ int iir_dest_b0 = g_buffer(IIR_DEST_B0);
+ int iir_dest_b1 = g_buffer(IIR_DEST_B1);
+
+ int IIR_A0 = iir_dest_a0 + ((IIR_INPUT_A0 - iir_dest_a0) * IIR_ALPHA >> 15);
+ int IIR_A1 = iir_dest_a1 + ((IIR_INPUT_A1 - iir_dest_a1) * IIR_ALPHA >> 15);
+ int IIR_B0 = iir_dest_b0 + ((IIR_INPUT_B0 - iir_dest_b0) * IIR_ALPHA >> 15);
+ int IIR_B1 = iir_dest_b1 + ((IIR_INPUT_B1 - iir_dest_b1) * IIR_ALPHA >> 15);
+
+ s_buffer1(IIR_DEST_A0, IIR_A0);
+ s_buffer1(IIR_DEST_A1, IIR_A1);
+ s_buffer1(IIR_DEST_B0, IIR_B0);
+ s_buffer1(IIR_DEST_B1, IIR_B1);
+
+ ACC0 = (g_buffer(ACC_SRC_A0) * rvb.ACC_COEF_A +
+ g_buffer(ACC_SRC_B0) * rvb.ACC_COEF_B +
+ g_buffer(ACC_SRC_C0) * rvb.ACC_COEF_C +
+ g_buffer(ACC_SRC_D0) * rvb.ACC_COEF_D) >> 15;
+ ACC1 = (g_buffer(ACC_SRC_A1) * rvb.ACC_COEF_A +
+ g_buffer(ACC_SRC_B1) * rvb.ACC_COEF_B +
+ g_buffer(ACC_SRC_C1) * rvb.ACC_COEF_C +
+ g_buffer(ACC_SRC_D1) * rvb.ACC_COEF_D) >> 15;
+
+ FB_A0 = g_buffer(FB_SRC_A0);
+ FB_A1 = g_buffer(FB_SRC_A1);
+ FB_B0 = g_buffer(FB_SRC_B0);
+ FB_B1 = g_buffer(FB_SRC_B1);
+
+ mix_dest_a0 = ACC0 - ((FB_A0 * rvb.FB_ALPHA) >> 15);
+ mix_dest_a1 = ACC1 - ((FB_A1 * rvb.FB_ALPHA) >> 15);
+
+ mix_dest_b0 = FB_A0 + (((ACC0 - FB_A0) * rvb.FB_ALPHA - FB_B0 * rvb.FB_X) >> 15);
+ mix_dest_b1 = FB_A1 + (((ACC1 - FB_A1) * rvb.FB_ALPHA - FB_B1 * rvb.FB_X) >> 15);
+
+ s_buffer(MIX_DEST_A0, mix_dest_a0);
+ s_buffer(MIX_DEST_A1, mix_dest_a1);
+ s_buffer(MIX_DEST_B0, mix_dest_b0);
+ s_buffer(MIX_DEST_B1, mix_dest_b1);
+
+ l = (mix_dest_a0 + mix_dest_b0) / 3;
+ r = (mix_dest_a1 + mix_dest_b1) / 3;
+
+ l = (l * rvb.VolLeft) >> 14;
+ r = (r * rvb.VolRight) >> 14;
+
+ SSumLR[ns++] += (l + l_old) / 2;
+ SSumLR[ns++] += (r + r_old) / 2;
+ SSumLR[ns++] += l;
+ SSumLR[ns++] += r;
+
+ l_old = l;
+ r_old = r;
+
+ curr_addr++;
+ if (curr_addr >= 0x40000) curr_addr = rvb.StartAddr;
}
+
+ rvb.iRVBLeft = l;
+ rvb.iRVBRight = r;
+ rvb.CurrAddr = curr_addr;
}
-////////////////////////////////////////////////////////////////////////
+static void prepare_offsets(void)
+{
+ int space = 0x40000 - rvb.StartAddr;
+ int t;
+ #define prep_offs(v) \
+ t = rvb.v; \
+ while (t >= space) \
+ t -= space; \
+ rvb.n##v = t
+ #define prep_offs2(d, v1, v2) \
+ t = rvb.v1 - rvb.v2; \
+ while (t >= space) \
+ t -= space; \
+ rvb.n##d = t
+
+ prep_offs(IIR_SRC_A0);
+ prep_offs(IIR_SRC_A1);
+ prep_offs(IIR_SRC_B0);
+ prep_offs(IIR_SRC_B1);
+ prep_offs(IIR_DEST_A0);
+ prep_offs(IIR_DEST_A1);
+ prep_offs(IIR_DEST_B0);
+ prep_offs(IIR_DEST_B1);
+ prep_offs(ACC_SRC_A0);
+ prep_offs(ACC_SRC_A1);
+ prep_offs(ACC_SRC_B0);
+ prep_offs(ACC_SRC_B1);
+ prep_offs(ACC_SRC_C0);
+ prep_offs(ACC_SRC_C1);
+ prep_offs(ACC_SRC_D0);
+ prep_offs(ACC_SRC_D1);
+ prep_offs(MIX_DEST_A0);
+ prep_offs(MIX_DEST_A1);
+ prep_offs(MIX_DEST_B0);
+ prep_offs(MIX_DEST_B1);
+ prep_offs2(FB_SRC_A0, MIX_DEST_A0, FB_SRC_A);
+ prep_offs2(FB_SRC_A1, MIX_DEST_A1, FB_SRC_A);
+ prep_offs2(FB_SRC_B0, MIX_DEST_B0, FB_SRC_B);
+ prep_offs2(FB_SRC_B1, MIX_DEST_B1, FB_SRC_B);
+
+#undef prep_offs
+#undef prep_offs2
+ rvb.dirty = 0;
+}
-INLINE int MixREVERBRight(void)
+INLINE void REVERBDo(void)
{
- if(iUseReverb==0) return 0;
- else
- if(iUseReverb==2) // Neill's reverb:
- {
- int i=rvb.iLastRVBRight+(rvb.iRVBRight-rvb.iLastRVBRight)/2;
- rvb.iLastRVBRight=rvb.iRVBRight;
- return i; // -> just return the last right reverb val (little bit scaled by the previous right val)
- }
- else // easy fake reverb:
- {
- const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value
- *sRVBPlay++=0; // -> init it after
- if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds
- return iRV; // -> return reverb mix buf val
- }
+ if (!rvb.StartAddr) // reverb is off
+ {
+ rvb.iRVBLeft = rvb.iRVBRight = 0;
+ return;
+ }
+
+ if (spuCtrl & 0x80) // -> reverb on? oki
+ {
+ if (rvb.dirty)
+ prepare_offsets();
+
+ MixREVERB();
+ }
+ else // -> reverb off
+ {
+ // supposedly runs anyway?
+ rvb.CurrAddr += NSSIZE/2;
+ while (rvb.CurrAddr >= 0x40000)
+ rvb.CurrAddr -= 0x40000 - rvb.StartAddr;
+ }
}
////////////////////////////////////////////////////////////////////////
@@ -460,3 +429,4 @@ buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB
-----------------------------------------------------------------------------
*/
+// vim:shiftwidth=1:expandtab
diff --git a/plugins/dfsound/reverb.h b/plugins/dfsound/reverb.h
deleted file mode 100644
index f7e9aa2..0000000
--- a/plugins/dfsound/reverb.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/***************************************************************************
- reverb.h - description
- -------------------
- begin : Wed May 15 2002
- copyright : (C) 2002 by Pete Bernert
- email : BlackDove@addcom.de
- ***************************************************************************/
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. See also the license.txt file for *
- * additional informations. *
- * *
- ***************************************************************************/
-
-void SetREVERB(unsigned short val);
-
diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c
index e6c5449..d6cd952 100644
--- a/plugins/dfsound/spu.c
+++ b/plugins/dfsound/spu.c
@@ -38,6 +38,16 @@
#define N_(x) (x)
#endif
+#ifdef __arm__
+ #define ssat32_to_16(v) \
+ asm("ssat %0,#16,%1" : "=r" (v) : "r" (v))
+#else
+ #define ssat32_to_16(v) do { \
+ if (v < -32768) v = -32768; \
+ else if (v > 32767) v = 32767; \
+ } while (0)
+#endif
+
/*
#if defined (USEMACOSX)
static char * libraryName = N_("Mac OS X Sound");
@@ -730,21 +740,28 @@ static void *MAINThread(void *arg)
if(s_chan[ch].bFMod==2) // fmod freq channel
memcpy(iFMod, ChanBuf, sizeof(iFMod));
- else for(ns=ns_from;ns<ns_to;ns++)
+ else
{
- int sval = ChanBuf[ns];
+ int lv=s_chan[ch].iLeftVolume;
+ int rv=s_chan[ch].iRightVolume;
+ for(ns=ns_from;ns<ns_to;ns++)
{
+ int sval = ChanBuf[ns];
+ int l, r;
+
//////////////////////////////////////////////
// ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
- SSumLR[ns*2] +=(sval*s_chan[ch].iLeftVolume)/0x4000L;
- SSumLR[ns*2+1]+=(sval*s_chan[ch].iRightVolume)/0x4000L;
+ l=(sval*lv)>>14;
+ r=(sval*rv)>>14;
+ SSumLR[ns*2] +=l;
+ SSumLR[ns*2+1]+=r;
//////////////////////////////////////////////
// now let us store sound data for reverb
- if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns,sval);
+ if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns,l,r);
}
}
}
@@ -811,19 +828,24 @@ static void *MAINThread(void *arg)
///////////////////////////////////////////////////////
// mix all channels (including reverb) into one buffer
+ if(iUseReverb)
+ REVERBDo();
+
+ if((spuCtrl&0x4000)==0) // muted? (rare, don't optimize for this)
+ {
+ memset(pS, 0, NSSIZE * 2 * sizeof(pS[0]));
+ pS += NSSIZE*2;
+ }
+ else
for (ns = 0; ns < NSSIZE*2; )
{
- SSumLR[ns] += MixREVERBLeft(ns/2);
-
d = SSumLR[ns] / voldiv; SSumLR[ns] = 0;
- if (d < -32767) d = -32767; if (d > 32767) d = 32767;
+ ssat32_to_16(d);
*pS++ = d;
ns++;
- SSumLR[ns] += MixREVERBRight();
-
d = SSumLR[ns] / voldiv; SSumLR[ns] = 0;
- if(d < -32767) d = -32767; if(d > 32767) d = 32767;
+ ssat32_to_16(d);
*pS++ = d;
ns++;
}
@@ -1037,7 +1059,6 @@ long CALLBACK SPUinit(void)
InitADSR();
iVolume = 3;
- iReverbOff = -1;
spuIrq = 0;
spuAddr = 0xffffffff;
bEndThread = 0;