#include "externals.h"\r
#include "registers.h"\r
#include "regs.h"\r
-#include "reverb.h"\r
\r
/*\r
// adsr time values (in ms) by James Higgs ... see the end of\r
rvb.CurrAddr=rvb.StartAddr;\r
}\r
}\r
+ rvb.dirty = 1;\r
break;\r
//-------------------------------------------------//\r
case H_SPUirqAddr:\r
ReverbOn(16,24,val);\r
break;\r
//-------------------------------------------------//\r
- case H_Reverb+0:\r
-\r
- rvb.FB_SRC_A=val;\r
-\r
- // OK, here's the fake REVERB stuff...\r
- // depending on effect we do more or less delay and repeats... bah\r
- // still... better than nothing :)\r
-\r
- SetREVERB(val);\r
- break;\r
-\r
-\r
- case H_Reverb+2 : rvb.FB_SRC_B=(short)val; break;\r
+ case H_Reverb+0 : rvb.FB_SRC_A=val*4; break;\r
+ case H_Reverb+2 : rvb.FB_SRC_B=val*4; break;\r
case H_Reverb+4 : rvb.IIR_ALPHA=(short)val; break;\r
case H_Reverb+6 : rvb.ACC_COEF_A=(short)val; break;\r
case H_Reverb+8 : rvb.ACC_COEF_B=(short)val; break;\r
case H_Reverb+14 : rvb.IIR_COEF=(short)val; break;\r
case H_Reverb+16 : rvb.FB_ALPHA=(short)val; break;\r
case H_Reverb+18 : rvb.FB_X=(short)val; break;\r
- case H_Reverb+20 : rvb.IIR_DEST_A0=(short)val; break;\r
- case H_Reverb+22 : rvb.IIR_DEST_A1=(short)val; break;\r
- case H_Reverb+24 : rvb.ACC_SRC_A0=(short)val; break;\r
- case H_Reverb+26 : rvb.ACC_SRC_A1=(short)val; break;\r
- case H_Reverb+28 : rvb.ACC_SRC_B0=(short)val; break;\r
- case H_Reverb+30 : rvb.ACC_SRC_B1=(short)val; break;\r
- case H_Reverb+32 : rvb.IIR_SRC_A0=(short)val; break;\r
- case H_Reverb+34 : rvb.IIR_SRC_A1=(short)val; break;\r
- case H_Reverb+36 : rvb.IIR_DEST_B0=(short)val; break;\r
- case H_Reverb+38 : rvb.IIR_DEST_B1=(short)val; break;\r
- case H_Reverb+40 : rvb.ACC_SRC_C0=(short)val; break;\r
- case H_Reverb+42 : rvb.ACC_SRC_C1=(short)val; break;\r
- case H_Reverb+44 : rvb.ACC_SRC_D0=(short)val; break;\r
- case H_Reverb+46 : rvb.ACC_SRC_D1=(short)val; break;\r
- case H_Reverb+48 : rvb.IIR_SRC_B1=(short)val; break;\r
- case H_Reverb+50 : rvb.IIR_SRC_B0=(short)val; break;\r
- case H_Reverb+52 : rvb.MIX_DEST_A0=(short)val; break;\r
- case H_Reverb+54 : rvb.MIX_DEST_A1=(short)val; break;\r
- case H_Reverb+56 : rvb.MIX_DEST_B0=(short)val; break;\r
- case H_Reverb+58 : rvb.MIX_DEST_B1=(short)val; break;\r
+ case H_Reverb+20 : rvb.IIR_DEST_A0=val*4; break;\r
+ case H_Reverb+22 : rvb.IIR_DEST_A1=val*4; break;\r
+ case H_Reverb+24 : rvb.ACC_SRC_A0=val*4; break;\r
+ case H_Reverb+26 : rvb.ACC_SRC_A1=val*4; break;\r
+ case H_Reverb+28 : rvb.ACC_SRC_B0=val*4; break;\r
+ case H_Reverb+30 : rvb.ACC_SRC_B1=val*4; break;\r
+ case H_Reverb+32 : rvb.IIR_SRC_A0=val*4; break;\r
+ case H_Reverb+34 : rvb.IIR_SRC_A1=val*4; break;\r
+ case H_Reverb+36 : rvb.IIR_DEST_B0=val*4; break;\r
+ case H_Reverb+38 : rvb.IIR_DEST_B1=val*4; break;\r
+ case H_Reverb+40 : rvb.ACC_SRC_C0=val*4; break;\r
+ case H_Reverb+42 : rvb.ACC_SRC_C1=val*4; break;\r
+ case H_Reverb+44 : rvb.ACC_SRC_D0=val*4; break;\r
+ case H_Reverb+46 : rvb.ACC_SRC_D1=val*4; break;\r
+ case H_Reverb+48 : rvb.IIR_SRC_B1=val*4; break;\r
+ case H_Reverb+50 : rvb.IIR_SRC_B0=val*4; break;\r
+ case H_Reverb+52 : rvb.MIX_DEST_A0=val*4; break;\r
+ case H_Reverb+54 : rvb.MIX_DEST_A1=val*4; break;\r
+ case H_Reverb+56 : rvb.MIX_DEST_B0=val*4; break;\r
+ case H_Reverb+58 : rvb.MIX_DEST_B1=val*4; break;\r
case H_Reverb+60 : rvb.IN_COEF_L=(short)val; break;\r
case H_Reverb+62 : rvb.IN_COEF_R=(short)val; break;\r
}\r
\r
+ if ((r & ~0x3f) == H_Reverb)\r
+ rvb.dirty = 1; // recalculate on next update\r
+\r
iSpuAsyncWait=0;\r
}\r
\r
begin : Wed May 15 2002\r
copyright : (C) 2002 by Pete Bernert\r
email : BlackDove@addcom.de\r
+\r
+ Portions (C) GraÅžvydas "notaz" Ignotas, 2010-2011\r
+ Portions (C) SPU2-X, gigaherz, Pcsx2 Development Team\r
+\r
***************************************************************************/\r
/***************************************************************************\r
* *\r
int * sRVBPlay = 0;\r
int * sRVBEnd = 0;\r
int * sRVBStart = 0;\r
-int iReverbOff = -1; // some delay factor for reverb\r
-int iReverbRepeat = 0;\r
-int iReverbNum = 1; \r
-\r
-////////////////////////////////////////////////////////////////////////\r
-// SET REVERB\r
-////////////////////////////////////////////////////////////////////////\r
-\r
-void SetREVERB(unsigned short val)\r
-{\r
- switch(val)\r
- {\r
- case 0x0000: iReverbOff=-1; break; // off\r
- case 0x007D: iReverbOff=32; iReverbNum=2; iReverbRepeat=128; break; // ok room\r
-\r
- case 0x0033: iReverbOff=32; iReverbNum=2; iReverbRepeat=64; break; // studio small\r
- case 0x00B1: iReverbOff=48; iReverbNum=2; iReverbRepeat=96; break; // ok studio medium\r
- case 0x00E3: iReverbOff=64; iReverbNum=2; iReverbRepeat=128; break; // ok studio large ok\r
-\r
- case 0x01A5: iReverbOff=128; iReverbNum=4; iReverbRepeat=32; break; // ok hall\r
- case 0x033D: iReverbOff=256; iReverbNum=4; iReverbRepeat=64; break; // space echo\r
- case 0x0001: iReverbOff=184; iReverbNum=3; iReverbRepeat=128; break; // echo/delay\r
- case 0x0017: iReverbOff=128; iReverbNum=2; iReverbRepeat=128; break; // half echo\r
- default: iReverbOff=32; iReverbNum=1; iReverbRepeat=0; break;\r
- }\r
-}\r
\r
////////////////////////////////////////////////////////////////////////\r
// START REVERB\r
{\r
if(s_chan[ch].bReverb && (spuCtrl&0x80)) // reverb possible?\r
{\r
- if(iUseReverb==2) s_chan[ch].bRVBActive=1;\r
- else\r
- if(iUseReverb==1 && iReverbOff>0) // -> fake reverb used?\r
- {\r
- s_chan[ch].bRVBActive=1; // -> activate it\r
- s_chan[ch].iRVBOffset=iReverbOff*45;\r
- s_chan[ch].iRVBRepeat=iReverbRepeat*45;\r
- s_chan[ch].iRVBNum =iReverbNum;\r
- }\r
+ s_chan[ch].bRVBActive=!!iUseReverb;\r
}\r
else s_chan[ch].bRVBActive=0; // else -> no reverb\r
}\r
\r
INLINE void InitREVERB(void)\r
{\r
- if(iUseReverb==2)\r
- {memset(sRVBStart,0,NSSIZE*2*4);}\r
+ memset(sRVBStart,0,NSSIZE*2*4);\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
// STORE REVERB\r
////////////////////////////////////////////////////////////////////////\r
\r
-INLINE void StoreREVERB(int ch,int ns,int sval)\r
+INLINE void StoreREVERB(int ch,int ns,int l,int r)\r
{\r
- if(iUseReverb==0) return;\r
- else\r
- if(iUseReverb==2) // -------------------------------- // Neil's reverb\r
- {\r
- const int iRxl=(sval*s_chan[ch].iLeftVolume)/0x4000;\r
- const int iRxr=(sval*s_chan[ch].iRightVolume)/0x4000;\r
+ ns<<=1;\r
\r
- ns<<=1;\r
-\r
- *(sRVBStart+ns) +=iRxl; // -> we mix all active reverb channels into an extra buffer\r
- *(sRVBStart+ns+1)+=iRxr;\r
- }\r
- else // --------------------------------------------- // Pete's easy fake reverb\r
- {\r
- int * pN;int iRn,iRr=0;\r
-\r
- // we use the half channel volume (/0x8000) for the first reverb effects, quarter for next and so on\r
-\r
- int iRxl=(sval*s_chan[ch].iLeftVolume)/0x8000;\r
- int iRxr=(sval*s_chan[ch].iRightVolume)/0x8000;\r
- \r
- for(iRn=1;iRn<=s_chan[ch].iRVBNum;iRn++,iRr+=s_chan[ch].iRVBRepeat,iRxl/=2,iRxr/=2)\r
- {\r
- pN=sRVBPlay+((s_chan[ch].iRVBOffset+iRr+ns)<<1);\r
- if(pN>=sRVBEnd) pN=sRVBStart+(pN-sRVBEnd);\r
-\r
- (*pN)+=iRxl;\r
- pN++;\r
- (*pN)+=iRxr;\r
- }\r
- }\r
+ sRVBStart[ns] +=l; // -> we mix all active reverb channels into an extra buffer\r
+ sRVBStart[ns+1]+=r;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-INLINE int g_buffer(int iOff) // get_buffer content helper: takes care about wraps\r
+INLINE int rvb2ram_offs(int curr, int space, int iOff)\r
{\r
- short * p=(short *)spuMem;\r
- iOff=(iOff*4)+rvb.CurrAddr;\r
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);\r
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);\r
- return (int)*(p+iOff);\r
+ iOff += curr;\r
+ if (iOff >= 0x40000) iOff -= space;\r
+ return iOff;\r
}\r
\r
-////////////////////////////////////////////////////////////////////////\r
+// get_buffer content helper: takes care about wraps\r
+#define g_buffer(var) \\r
+ ((int)(signed short)spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var)])\r
\r
-INLINE void s_buffer(int iOff,int iVal) // set_buffer content helper: takes care about wraps and clipping\r
-{\r
- short * p=(short *)spuMem;\r
- iOff=(iOff*4)+rvb.CurrAddr;\r
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);\r
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);\r
- if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;\r
- *(p+iOff)=(short)iVal;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////\r
+// saturate iVal and store it as var\r
+#define s_buffer(var, iVal) \\r
+ ssat32_to_16(iVal); \\r
+ spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var)] = iVal\r
\r
-INLINE void s_buffer1(int iOff,int iVal) // set_buffer (+1 sample) content helper: takes care about wraps and clipping\r
-{\r
- short * p=(short *)spuMem;\r
- iOff=(iOff*4)+rvb.CurrAddr+1;\r
- while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);\r
- while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);\r
- if(iVal<-32768L) iVal=-32768L;if(iVal>32767L) iVal=32767L;\r
- *(p+iOff)=(short)iVal;\r
-}\r
+#define s_buffer1(var, iVal) \\r
+ ssat32_to_16(iVal); \\r
+ spuMem[rvb2ram_offs(curr_addr, space, rvb.n##var + 1)] = iVal\r
\r
////////////////////////////////////////////////////////////////////////\r
\r
-INLINE int MixREVERBLeft(int ns)\r
+// portions based on spu2-x from PCSX2\r
+static void MixREVERB(void)\r
{\r
- if(iUseReverb==0) return 0;\r
- else\r
- if(iUseReverb==2)\r
- {\r
- static int iCnt=0; // this func will be called with 44.1 khz\r
-\r
- if(!rvb.StartAddr) // reverb is off\r
- {\r
- rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0;\r
- return 0;\r
- }\r
-\r
- iCnt++; \r
-\r
- if(iCnt&1) // we work on every second left value: downsample to 22 khz\r
- {\r
- if(spuCtrl&0x80) // -> reverb on? oki\r
- {\r
- int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;\r
-\r
- const int INPUT_SAMPLE_L=*(sRVBStart+(ns<<1)); \r
- const int INPUT_SAMPLE_R=*(sRVBStart+(ns<<1)+1); \r
-\r
- const int IIR_INPUT_A0 = (g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L;\r
- const int IIR_INPUT_A1 = (g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L;\r
- const int IIR_INPUT_B0 = (g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_L * rvb.IN_COEF_L)/32768L;\r
- const int IIR_INPUT_B1 = (g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)/32768L + (INPUT_SAMPLE_R * rvb.IN_COEF_R)/32768L;\r
-\r
- const int IIR_A0 = (IIR_INPUT_A0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))/32768L;\r
- const int IIR_A1 = (IIR_INPUT_A1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))/32768L;\r
- const int IIR_B0 = (IIR_INPUT_B0 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))/32768L;\r
- const int IIR_B1 = (IIR_INPUT_B1 * rvb.IIR_ALPHA)/32768L + (g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))/32768L;\r
-\r
- s_buffer1(rvb.IIR_DEST_A0, IIR_A0);\r
- s_buffer1(rvb.IIR_DEST_A1, IIR_A1);\r
- s_buffer1(rvb.IIR_DEST_B0, IIR_B0);\r
- s_buffer1(rvb.IIR_DEST_B1, IIR_B1);\r
- \r
- ACC0 = (g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)/32768L +\r
- (g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)/32768L +\r
- (g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)/32768L +\r
- (g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)/32768L;\r
- ACC1 = (g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)/32768L +\r
- (g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)/32768L +\r
- (g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)/32768L +\r
- (g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)/32768L;\r
-\r
- FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A);\r
- FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A);\r
- FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B);\r
- FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B);\r
-\r
- s_buffer(rvb.MIX_DEST_A0, ACC0 - (FB_A0 * rvb.FB_ALPHA)/32768L);\r
- s_buffer(rvb.MIX_DEST_A1, ACC1 - (FB_A1 * rvb.FB_ALPHA)/32768L);\r
- \r
- 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);\r
- 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);\r
- \r
- rvb.iLastRVBLeft = rvb.iRVBLeft;\r
- rvb.iLastRVBRight = rvb.iRVBRight;\r
-\r
- rvb.iRVBLeft = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3;\r
- rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3;\r
-\r
- rvb.iRVBLeft = (rvb.iRVBLeft * rvb.VolLeft) / 0x4000;\r
- rvb.iRVBRight = (rvb.iRVBRight * rvb.VolRight) / 0x4000;\r
-\r
- rvb.CurrAddr++;\r
- if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;\r
-\r
- return rvb.iLastRVBLeft+(rvb.iRVBLeft-rvb.iLastRVBLeft)/2;\r
- }\r
- else // -> reverb off\r
- {\r
- rvb.iLastRVBLeft=rvb.iLastRVBRight=rvb.iRVBLeft=rvb.iRVBRight=0;\r
- }\r
-\r
- rvb.CurrAddr++;\r
- if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;\r
- }\r
-\r
- return rvb.iLastRVBLeft;\r
- }\r
- else // easy fake reverb:\r
+ int l_old = rvb.iRVBLeft;\r
+ int r_old = rvb.iRVBRight;\r
+ int curr_addr = rvb.CurrAddr;\r
+ int space = 0x40000 - rvb.StartAddr;\r
+ int l, r, ns;\r
+\r
+ for (ns = 0; ns < NSSIZE*2; )\r
{\r
- const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value\r
- *sRVBPlay++=0; // -> init it after\r
- if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds\r
- return iRV; // -> return reverb mix buf val\r
+ int IIR_ALPHA = rvb.IIR_ALPHA;\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 = sRVBStart[ns] * rvb.IN_COEF_L;\r
+ int input_R = sRVBStart[ns+1] * rvb.IN_COEF_R;\r
+\r
+ int IIR_INPUT_A0 = ((g_buffer(IIR_SRC_A0) * rvb.IIR_COEF) + input_L) >> 15;\r
+ int IIR_INPUT_A1 = ((g_buffer(IIR_SRC_A1) * rvb.IIR_COEF) + input_R) >> 15;\r
+ int IIR_INPUT_B0 = ((g_buffer(IIR_SRC_B0) * rvb.IIR_COEF) + input_L) >> 15;\r
+ int IIR_INPUT_B1 = ((g_buffer(IIR_SRC_B1) * rvb.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
+\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
+\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
+\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
+\r
+ l = (mix_dest_a0 + mix_dest_b0) / 3;\r
+ r = (mix_dest_a1 + mix_dest_b1) / 3;\r
+\r
+ l = (l * rvb.VolLeft) >> 14;\r
+ r = (r * rvb.VolRight) >> 14;\r
+\r
+ SSumLR[ns++] += (l + l_old) / 2;\r
+ SSumLR[ns++] += (r + r_old) / 2;\r
+ SSumLR[ns++] += l;\r
+ SSumLR[ns++] += r;\r
+\r
+ l_old = l;\r
+ r_old = r;\r
+\r
+ curr_addr++;\r
+ if (curr_addr >= 0x40000) curr_addr = rvb.StartAddr;\r
}\r
+\r
+ rvb.iRVBLeft = l;\r
+ rvb.iRVBRight = r;\r
+ rvb.CurrAddr = curr_addr;\r
}\r
\r
-////////////////////////////////////////////////////////////////////////\r
+static void prepare_offsets(void)\r
+{\r
+ int space = 0x40000 - rvb.StartAddr;\r
+ int t;\r
+ #define prep_offs(v) \\r
+ t = rvb.v; \\r
+ while (t >= space) \\r
+ t -= space; \\r
+ rvb.n##v = t\r
+ #define prep_offs2(d, v1, v2) \\r
+ t = rvb.v1 - rvb.v2; \\r
+ while (t >= space) \\r
+ t -= space; \\r
+ rvb.n##d = t\r
+\r
+ prep_offs(IIR_SRC_A0);\r
+ prep_offs(IIR_SRC_A1);\r
+ prep_offs(IIR_SRC_B0);\r
+ prep_offs(IIR_SRC_B1);\r
+ prep_offs(IIR_DEST_A0);\r
+ prep_offs(IIR_DEST_A1);\r
+ prep_offs(IIR_DEST_B0);\r
+ prep_offs(IIR_DEST_B1);\r
+ prep_offs(ACC_SRC_A0);\r
+ prep_offs(ACC_SRC_A1);\r
+ prep_offs(ACC_SRC_B0);\r
+ prep_offs(ACC_SRC_B1);\r
+ prep_offs(ACC_SRC_C0);\r
+ prep_offs(ACC_SRC_C1);\r
+ prep_offs(ACC_SRC_D0);\r
+ prep_offs(ACC_SRC_D1);\r
+ prep_offs(MIX_DEST_A0);\r
+ prep_offs(MIX_DEST_A1);\r
+ prep_offs(MIX_DEST_B0);\r
+ prep_offs(MIX_DEST_B1);\r
+ prep_offs2(FB_SRC_A0, MIX_DEST_A0, FB_SRC_A);\r
+ prep_offs2(FB_SRC_A1, MIX_DEST_A1, FB_SRC_A);\r
+ prep_offs2(FB_SRC_B0, MIX_DEST_B0, FB_SRC_B);\r
+ prep_offs2(FB_SRC_B1, MIX_DEST_B1, FB_SRC_B);\r
+\r
+#undef prep_offs\r
+#undef prep_offs2\r
+ rvb.dirty = 0;\r
+}\r
\r
-INLINE int MixREVERBRight(void)\r
+INLINE void REVERBDo(void)\r
{\r
- if(iUseReverb==0) return 0;\r
- else\r
- if(iUseReverb==2) // Neill's reverb:\r
- {\r
- int i=rvb.iLastRVBRight+(rvb.iRVBRight-rvb.iLastRVBRight)/2;\r
- rvb.iLastRVBRight=rvb.iRVBRight;\r
- return i; // -> just return the last right reverb val (little bit scaled by the previous right val)\r
- }\r
- else // easy fake reverb:\r
- {\r
- const int iRV=*sRVBPlay; // -> simply take the reverb mix buf value\r
- *sRVBPlay++=0; // -> init it after\r
- if(sRVBPlay>=sRVBEnd) sRVBPlay=sRVBStart; // -> and take care about wrap arounds\r
- return iRV; // -> return reverb mix buf val\r
- }\r
+ if (!rvb.StartAddr) // reverb is off\r
+ {\r
+ rvb.iRVBLeft = rvb.iRVBRight = 0;\r
+ return;\r
+ }\r
+\r
+ if (spuCtrl & 0x80) // -> reverb on? oki\r
+ {\r
+ if (rvb.dirty)\r
+ prepare_offsets();\r
+\r
+ MixREVERB();\r
+ }\r
+ else // -> reverb off\r
+ {\r
+ // supposedly runs anyway?\r
+ rvb.CurrAddr += NSSIZE/2;\r
+ while (rvb.CurrAddr >= 0x40000)\r
+ rvb.CurrAddr -= 0x40000 - rvb.StartAddr;\r
+ }\r
}\r
\r
////////////////////////////////////////////////////////////////////////\r
-----------------------------------------------------------------------------\r
*/\r
\r
+// vim:shiftwidth=1:expandtab\r