1 /***************************************************************************
2                           reverb.c  -  description
3                              -------------------
4     begin                : Wed May 15 2002
5     copyright            : (C) 2002 by Pete Bernert
6     email                : BlackDove@addcom.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version. See also the license.txt file for *
15  *   additional informations.                                              *
16  *                                                                         *
17  ***************************************************************************/
18 
19 //*************************************************************************//
20 // History of changes:
21 //
22 // 2003/03/17 - xodnizel
23 // - Implemented Neill's 44.1Khz-22050Hz downsampling data
24 //   I also need to check if the ~4 sample delay doesn't screw any sounds
25 //   up by making things too out of phase.  It could be fixed easily(elsewhere).
26 //
27 // 2003/01/19 - Pete
28 // - added Neill's reverb (see at the end of file)
29 //
30 // 2002/12/26 - Pete
31 // - adjusted reverb handling
32 //
33 // 2002/08/14 - Pete
34 // - added extra reverb
35 //
36 // 2002/05/15 - Pete
37 // - generic cleanup for the Peops release
38 //
39 //*************************************************************************//
40 
41 #define _IN_REVERB
42 
43 // will be included from spu.c
44 #ifdef _IN_SPU
45 
46 ////////////////////////////////////////////////////////////////////////
47 // globals
48 ////////////////////////////////////////////////////////////////////////
49 
50 // REVERB info and timing vars...
51 
52 ////////////////////////////////////////////////////////////////////////
53 
g_buffer(int iOff)54 static inline s64 g_buffer(int iOff)                          // get_buffer content helper: takes care about wraps
55 {
56  s16 * p=(s16 *)spuMem;
57  iOff=(iOff*4)+rvb.CurrAddr;
58  while(iOff>0x3FFFF)       iOff=rvb.StartAddr+(iOff-0x40000);
59  while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
60  return (int)(s16)BFLIP16(*(p+iOff));
61 }
62 
63 ////////////////////////////////////////////////////////////////////////
64 
s_buffer(int iOff,int iVal)65 static inline void s_buffer(int iOff,int iVal)                // set_buffer content helper: takes care about wraps and clipping
66 {
67  s16 * p=(s16 *)spuMem;
68  iOff=(iOff*4)+rvb.CurrAddr;
69  while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
70  while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
71  if(iVal<-32768L) iVal=-32768L;
72  if(iVal>32767L) iVal=32767L;
73  *(p+iOff)=(s16)BFLIP16((s16)iVal);
74 }
75 
76 ////////////////////////////////////////////////////////////////////////
77 
s_buffer1(int iOff,int iVal)78 static inline void s_buffer1(int iOff,int iVal)                // set_buffer (+1 sample) content helper: takes care about wraps and clipping
79 {
80  s16 * p=(s16 *)spuMem;
81  iOff=(iOff*4)+rvb.CurrAddr+1;
82  while(iOff>0x3FFFF) iOff=rvb.StartAddr+(iOff-0x40000);
83  while(iOff<rvb.StartAddr) iOff=0x3ffff-(rvb.StartAddr-iOff);
84  if(iVal<-32768L) iVal=-32768L;
85  if(iVal>32767L) iVal=32767L;
86  *(p+iOff)=(s16)BFLIP16((s16)iVal);
87 }
88 
MixREVERBLeftRight(s32 * oleft,s32 * oright,s32 inleft,s32 inright)89 static inline void MixREVERBLeftRight(s32 *oleft, s32 *oright, s32 inleft, s32 inright)
90 {
91    static s32 downbuf[2][8];
92    static s32 upbuf[2][8];
93    static int dbpos=0,ubpos=0;
94    static s32 downcoeffs[8]={ /* Symmetry is sexy. */
95 				1283,5344,10895,15243,
96 				15243,10895,5344,1283
97 			       };
98    int x;
99 
100    if(!rvb.StartAddr)                                  // reverb is off
101     {
102      rvb.iRVBLeft=rvb.iRVBRight=0;
103      return;
104     }
105 
106    //if(inleft<-32767 || inleft>32767) printf("%d\n",inleft);
107    //if(inright<-32767 || inright>32767) printf("%d\n",inright);
108    downbuf[0][dbpos]=inleft;
109    downbuf[1][dbpos]=inright;
110    dbpos=(dbpos+1)&7;
111 
112    if(dbpos&1)                                          // we work on every second left value: downsample to 22 khz
113     {
114      if(spuCtrl&0x80)                                  // -> reverb on? oki
115       {
116        int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;
117        s32 INPUT_SAMPLE_L=0;
118        s32 INPUT_SAMPLE_R=0;
119 
120        for(x=0;x<8;x++)
121        {
122         INPUT_SAMPLE_L+=(downbuf[0][(dbpos+x)&7]*downcoeffs[x])>>8; /* Lose insignificant
123 							    digits to prevent
124 							    overflow(check this) */
125         INPUT_SAMPLE_R+=(downbuf[1][(dbpos+x)&7]*downcoeffs[x])>>8;
126        }
127 
128        INPUT_SAMPLE_L>>=(16-8);
129        INPUT_SAMPLE_R>>=(16-8);
130        {
131         const s64 IIR_INPUT_A0 = ((g_buffer(rvb.IIR_SRC_A0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
132         const s64 IIR_INPUT_A1 = ((g_buffer(rvb.IIR_SRC_A1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
133         const s64 IIR_INPUT_B0 = ((g_buffer(rvb.IIR_SRC_B0) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_L * rvb.IN_COEF_L)>>15);
134         const s64 IIR_INPUT_B1 = ((g_buffer(rvb.IIR_SRC_B1) * rvb.IIR_COEF)>>15) + ((INPUT_SAMPLE_R * rvb.IN_COEF_R)>>15);
135         const s64 IIR_A0 = ((IIR_INPUT_A0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A0) * (32768L - rvb.IIR_ALPHA))>>15);
136         const s64 IIR_A1 = ((IIR_INPUT_A1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_A1) * (32768L - rvb.IIR_ALPHA))>>15);
137         const s64 IIR_B0 = ((IIR_INPUT_B0 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B0) * (32768L - rvb.IIR_ALPHA))>>15);
138         const s64 IIR_B1 = ((IIR_INPUT_B1 * rvb.IIR_ALPHA)>>15) + ((g_buffer(rvb.IIR_DEST_B1) * (32768L - rvb.IIR_ALPHA))>>15);
139 
140        s_buffer1(rvb.IIR_DEST_A0, IIR_A0);
141        s_buffer1(rvb.IIR_DEST_A1, IIR_A1);
142        s_buffer1(rvb.IIR_DEST_B0, IIR_B0);
143        s_buffer1(rvb.IIR_DEST_B1, IIR_B1);
144 
145        ACC0 = ((g_buffer(rvb.ACC_SRC_A0) * rvb.ACC_COEF_A)>>15) +
146               ((g_buffer(rvb.ACC_SRC_B0) * rvb.ACC_COEF_B)>>15) +
147               ((g_buffer(rvb.ACC_SRC_C0) * rvb.ACC_COEF_C)>>15) +
148               ((g_buffer(rvb.ACC_SRC_D0) * rvb.ACC_COEF_D)>>15);
149        ACC1 = ((g_buffer(rvb.ACC_SRC_A1) * rvb.ACC_COEF_A)>>15) +
150               ((g_buffer(rvb.ACC_SRC_B1) * rvb.ACC_COEF_B)>>15) +
151               ((g_buffer(rvb.ACC_SRC_C1) * rvb.ACC_COEF_C)>>15) +
152               ((g_buffer(rvb.ACC_SRC_D1) * rvb.ACC_COEF_D)>>15);
153 
154        FB_A0 = g_buffer(rvb.MIX_DEST_A0 - rvb.FB_SRC_A);
155        FB_A1 = g_buffer(rvb.MIX_DEST_A1 - rvb.FB_SRC_A);
156        FB_B0 = g_buffer(rvb.MIX_DEST_B0 - rvb.FB_SRC_B);
157        FB_B1 = g_buffer(rvb.MIX_DEST_B1 - rvb.FB_SRC_B);
158 
159        s_buffer(rvb.MIX_DEST_A0, ACC0 - ((FB_A0 * rvb.FB_ALPHA)>>15));
160        s_buffer(rvb.MIX_DEST_A1, ACC1 - ((FB_A1 * rvb.FB_ALPHA)>>15));
161 
162        s_buffer(rvb.MIX_DEST_B0, ((rvb.FB_ALPHA * ACC0)>>15) - ((FB_A0 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B0 * rvb.FB_X)>>15));
163        s_buffer(rvb.MIX_DEST_B1, ((rvb.FB_ALPHA * ACC1)>>15) - ((FB_A1 * (int)(rvb.FB_ALPHA^0xFFFF8000))>>15) - ((FB_B1 * rvb.FB_X)>>15));
164 
165        rvb.iRVBLeft  = (g_buffer(rvb.MIX_DEST_A0)+g_buffer(rvb.MIX_DEST_B0))/3;
166        rvb.iRVBRight = (g_buffer(rvb.MIX_DEST_A1)+g_buffer(rvb.MIX_DEST_B1))/3;
167 
168        rvb.iRVBLeft  = ((s64)rvb.iRVBLeft * rvb.VolLeft)  >> 14;
169        rvb.iRVBRight = ((s64)rvb.iRVBRight * rvb.VolRight) >> 14;
170 
171        upbuf[0][ubpos]=rvb.iRVBLeft;
172        upbuf[1][ubpos]=rvb.iRVBRight;
173        ubpos=(ubpos+1)&7;
174        } // Bracket hack(et).
175       }
176      else                                              // -> reverb off
177       {
178        rvb.iRVBLeft=rvb.iRVBRight=0;
179        return;
180       }
181      rvb.CurrAddr++;
182      if(rvb.CurrAddr>0x3ffff) rvb.CurrAddr=rvb.StartAddr;
183     }
184     else
185     {
186      upbuf[0][ubpos]=0;
187      upbuf[1][ubpos]=0;
188      ubpos=(ubpos+1)&7;
189     }
190    {
191     s32 retl=0,retr=0;
192     for(x=0;x<8;x++)
193     {
194      retl+=(upbuf[0][(ubpos+x)&7]*downcoeffs[x])>>8;
195      retr+=(upbuf[1][(ubpos+x)&7]*downcoeffs[x])>>8;
196     }
197     retl>>=(16-8-1); /* -1 To adjust for the null padding. */
198     retr>>=(16-8-1);
199 
200     *oleft+=retl;
201     *oright+=retr;
202    }
203 }
204 
205 ////////////////////////////////////////////////////////////////////////
206 
207 #endif
208 
209 /*
210 -----------------------------------------------------------------------------
211 PSX reverb hardware notes
212 by Neill Corlett
213 -----------------------------------------------------------------------------
214 
215 Yadda yadda disclaimer yadda probably not perfect yadda well it's okay anyway
216 yadda yadda.
217 
218 -----------------------------------------------------------------------------
219 
220 Basics
221 ------
222 
223 - The reverb buffer is 22khz 16-bit mono PCM.
224 - It starts at the reverb address given by 1DA2, extends to
225   the end of sound RAM, and wraps back to the 1DA2 address.
226 
227 Setting the address at 1DA2 resets the current reverb work address.
228 
229 This work address ALWAYS increments every 1/22050 sec., regardless of
230 whether reverb is enabled (bit 7 of 1DAA set).
231 
232 And the contents of the reverb buffer ALWAYS play, scaled by the
233 "reverberation depth left/right" volumes (1D84/1D86).
234 (which, by the way, appear to be scaled so 3FFF=approx. 1.0, 4000=-1.0)
235 
236 -----------------------------------------------------------------------------
237 
238 Register names
239 --------------
240 
241 These are probably not their real names.
242 These are probably not even correct names.
243 We will use them anyway, because we can.
244 
245 1DC0: FB_SRC_A       (offset)
246 1DC2: FB_SRC_B       (offset)
247 1DC4: IIR_ALPHA      (coef.)
248 1DC6: ACC_COEF_A     (coef.)
249 1DC8: ACC_COEF_B     (coef.)
250 1DCA: ACC_COEF_C     (coef.)
251 1DCC: ACC_COEF_D     (coef.)
252 1DCE: IIR_COEF       (coef.)
253 1DD0: FB_ALPHA       (coef.)
254 1DD2: FB_X           (coef.)
255 1DD4: IIR_DEST_A0    (offset)
256 1DD6: IIR_DEST_A1    (offset)
257 1DD8: ACC_SRC_A0     (offset)
258 1DDA: ACC_SRC_A1     (offset)
259 1DDC: ACC_SRC_B0     (offset)
260 1DDE: ACC_SRC_B1     (offset)
261 1DE0: IIR_SRC_A0     (offset)
262 1DE2: IIR_SRC_A1     (offset)
263 1DE4: IIR_DEST_B0    (offset)
264 1DE6: IIR_DEST_B1    (offset)
265 1DE8: ACC_SRC_C0     (offset)
266 1DEA: ACC_SRC_C1     (offset)
267 1DEC: ACC_SRC_D0     (offset)
268 1DEE: ACC_SRC_D1     (offset)
269 1DF0: IIR_SRC_B1     (offset)
270 1DF2: IIR_SRC_B0     (offset)
271 1DF4: MIX_DEST_A0    (offset)
272 1DF6: MIX_DEST_A1    (offset)
273 1DF8: MIX_DEST_B0    (offset)
274 1DFA: MIX_DEST_B1    (offset)
275 1DFC: IN_COEF_L      (coef.)
276 1DFE: IN_COEF_R      (coef.)
277 
278 The coefficients are signed fractional values.
279 -32768 would be -1.0
280  32768 would be  1.0 (if it were possible... the highest is of course 32767)
281 
282 The offsets are (byte/8) offsets into the reverb buffer.
283 i.e. you multiply them by 8, you get byte offsets.
284 You can also think of them as (samples/4) offsets.
285 They appear to be signed.  They can be negative.
286 None of the documented presets make them negative, though.
287 
288 Yes, 1DF0 and 1DF2 appear to be backwards.  Not a typo.
289 
290 -----------------------------------------------------------------------------
291 
292 What it does
293 ------------
294 
295 We take all reverb sources:
296 - regular channels that have the reverb bit on
297 - cd and external sources, if their reverb bits are on
298 and mix them into one stereo 44100hz signal.
299 
300 Lowpass/downsample that to 22050hz.  The PSX uses a proper bandlimiting
301 algorithm here, but I haven't figured out the hysterically exact specifics.
302 I use an 8-tap filter with these coefficients, which are nice but probably
303 not the real ones:
304 
305 0.037828187894
306 0.157538631280
307 0.321159685278
308 0.449322115345
309 0.449322115345
310 0.321159685278
311 0.157538631280
312 0.037828187894
313 
314 So we have two input samples (INPUT_SAMPLE_L, INPUT_SAMPLE_R) every 22050hz.
315 
316 * IN MY EMULATION, I divide these by 2 to make it clip less.
317   (and of course the L/R output coefficients are adjusted to compensate)
318   The real thing appears to not do this.
319 
320 At every 22050hz tick:
321 - If the reverb bit is enabled (bit 7 of 1DAA), execute the reverb
322   steady-state algorithm described below
323 - AFTERWARDS, retrieve the "wet out" L and R samples from the reverb buffer
324   (This part may not be exactly right and I guessed at the coefs. TODO: check later.)
325   L is: 0.333 * (buffer[MIX_DEST_A0] + buffer[MIX_DEST_B0])
326   R is: 0.333 * (buffer[MIX_DEST_A1] + buffer[MIX_DEST_B1])
327 - Advance the current buffer position by 1 sample
328 
329 The wet out L and R are then upsampled to 44100hz and played at the
330 "reverberation depth left/right" (1D84/1D86) volume, independent of the main
331 volume.
332 
333 -----------------------------------------------------------------------------
334 
335 Reverb steady-state
336 -------------------
337 
338 The reverb steady-state algorithm is fairly clever, and of course by
339 "clever" I mean "batshit insane".
340 
341 buffer[x] is relative to the current buffer position, not the beginning of
342 the buffer.  Note that all buffer offsets must wrap around so they're
343 contained within the reverb work area.
344 
345 Clipping is performed at the end... maybe also sooner, but definitely at
346 the end.
347 
348 IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
349 IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
350 IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
351 IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
352 
353 IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
354 IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
355 IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
356 IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
357 
358 buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
359 buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
360 buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
361 buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
362 
363 ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
364        buffer[ACC_SRC_B0] * ACC_COEF_B +
365        buffer[ACC_SRC_C0] * ACC_COEF_C +
366        buffer[ACC_SRC_D0] * ACC_COEF_D;
367 ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
368        buffer[ACC_SRC_B1] * ACC_COEF_B +
369        buffer[ACC_SRC_C1] * ACC_COEF_C +
370        buffer[ACC_SRC_D1] * ACC_COEF_D;
371 
372 FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
373 FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
374 FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
375 FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
376 
377 buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
378 buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
379 buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
380 buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
381 
382 -----------------------------------------------------------------------------
383 */
384 
385