Commit | Line | Data |
---|---|---|
ef79bbde P |
1 | /***************************************************************************\r |
2 | reverb.c - description\r | |
3 | -------------------\r | |
4 | begin : Wed May 15 2002\r | |
5 | copyright : (C) 2002 by Pete Bernert\r | |
6 | email : BlackDove@addcom.de\r | |
1775933a | 7 | \r |
8 | Portions (C) GraÅžvydas "notaz" Ignotas, 2010-2011\r | |
9 | Portions (C) SPU2-X, gigaherz, Pcsx2 Development Team\r | |
10 | \r | |
ef79bbde P |
11 | ***************************************************************************/\r |
12 | /***************************************************************************\r | |
13 | * *\r | |
14 | * This program is free software; you can redistribute it and/or modify *\r | |
15 | * it under the terms of the GNU General Public License as published by *\r | |
16 | * the Free Software Foundation; either version 2 of the License, or *\r | |
17 | * (at your option) any later version. See also the license.txt file for *\r | |
18 | * additional informations. *\r | |
19 | * *\r | |
20 | ***************************************************************************/\r | |
21 | \r | |
22 | #include "stdafx.h"\r | |
a4621d43 | 23 | #include "spu.h"\r |
f79ea779 | 24 | #include <assert.h>\r |
ef79bbde P |
25 | \r |
26 | #define _IN_REVERB\r | |
27 | \r | |
28 | // will be included from spu.c\r | |
29 | #ifdef _IN_SPU\r | |
30 | \r | |
ef79bbde P |
31 | ////////////////////////////////////////////////////////////////////////\r |
32 | // START REVERB\r | |
33 | ////////////////////////////////////////////////////////////////////////\r | |
34 | \r | |
35 | INLINE void StartREVERB(int ch)\r | |
36 | {\r | |
5514a050 | 37 | if(spu.s_chan[ch].bReverb && (spu.spuCtrl&0x80)) // reverb possible?\r |
ef79bbde | 38 | {\r |
5514a050 | 39 | spu.s_chan[ch].bRVBActive=!!spu_config.iUseReverb;\r |
ef79bbde | 40 | }\r |
5514a050 | 41 | else spu.s_chan[ch].bRVBActive=0; // else -> no reverb\r |
ef79bbde P |
42 | }\r |
43 | \r | |
ef79bbde P |
44 | ////////////////////////////////////////////////////////////////////////\r |
45 | \r | |
f79ea779 | 46 | INLINE int rvb_wrap(int ofs, int space)\r |
ef79bbde | 47 | {\r |
f79ea779 | 48 | #if 0\r |
49 | int mask = (0x3ffff - ofs) >> 31;\r | |
50 | ofs = ofs - (space & mask);\r | |
51 | #else\r | |
52 | if (ofs >= 0x40000)\r | |
53 | ofs -= space;\r | |
54 | #endif\r | |
55 | //assert(ofs >= 0x40000 - space);\r | |
56 | //assert(ofs < 0x40000);\r | |
57 | return ofs;\r | |
58 | }\r | |
59 | \r | |
60 | INLINE int rvb2ram_offs(int curr, int space, int ofs)\r | |
61 | {\r | |
62 | ofs += curr;\r | |
63 | return rvb_wrap(ofs, space);\r | |
ef79bbde P |
64 | }\r |
65 | \r | |
1775933a | 66 | // get_buffer content helper: takes care about wraps\r |
67 | #define g_buffer(var) \\r | |
f79ea779 | 68 | ((int)(signed short)LE16TOH(spuMem[rvb2ram_offs(curr_addr, space, var)]))\r |
ef79bbde | 69 | \r |
1775933a | 70 | // saturate iVal and store it as var\r |
f79ea779 | 71 | #define s_buffer_w(var, iVal) \\r |
1775933a | 72 | ssat32_to_16(iVal); \\r |
f79ea779 | 73 | spuMem[rvb2ram_offs(curr_addr, space, var)] = HTOLE16(iVal)\r |
ef79bbde P |
74 | \r |
75 | ////////////////////////////////////////////////////////////////////////\r | |
76 | \r | |
ef0559d4 | 77 | static void reverb_interpolate(sample_buf *sb, int curr_addr,\r |
0f5a4b3a | 78 | int out0[2], int out1[2])\r |
79 | {\r | |
80 | int spos = (curr_addr - 3) & 3;\r | |
81 | int dpos = curr_addr & 3;\r | |
82 | int i;\r | |
83 | \r | |
84 | for (i = 0; i < 2; i++)\r | |
ef0559d4 | 85 | sb->SB_rvb[i][dpos] = sb->SB_rvb[i][4 | dpos] = out0[i];\r |
0f5a4b3a | 86 | \r |
87 | // mednafen uses some 20 coefs here, we just reuse gauss [0] and [128]\r | |
88 | for (i = 0; i < 2; i++)\r | |
89 | {\r | |
90 | const int *s;\r | |
ef0559d4 | 91 | s = &sb->SB_rvb[i][spos];\r |
0f5a4b3a | 92 | out0[i] = (s[0] * 0x12c7 + s[1] * 0x59b3 + s[2] * 0x1307) >> 15;\r |
93 | out1[i] = (s[0] * 0x019c + s[1] * 0x3def + s[2] * 0x3e4c + s[3] * 0x01a8) >> 15;\r | |
94 | }\r | |
95 | }\r | |
96 | \r | |
97 | static void MixREVERB(int *SSumLR, int *RVB, int ns_to, int curr_addr,\r | |
98 | int do_filter)\r | |
ef79bbde | 99 | {\r |
f79ea779 | 100 | unsigned short *spuMem = spu.spuMem;\r |
ef0559d4 | 101 | const REVERBInfo *rvb = spu.rvb;\r |
102 | sample_buf *sb = &spu.sb[MAXCHAN];\r | |
05c7cec7 | 103 | int space = 0x40000 - rvb->StartAddr;\r |
f79ea779 | 104 | int mlsame_m2o = rvb->mLSAME + space - 1;\r |
105 | int mrsame_m2o = rvb->mRSAME + space - 1;\r | |
106 | int mldiff_m2o = rvb->mLDIFF + space - 1;\r | |
107 | int mrdiff_m2o = rvb->mRDIFF + space - 1;\r | |
961cb15e | 108 | int vCOMB1 = rvb->vCOMB1 >> 1, vCOMB2 = rvb->vCOMB2 >> 1;\r |
109 | int vCOMB3 = rvb->vCOMB3 >> 1, vCOMB4 = rvb->vCOMB4 >> 1;\r | |
110 | int vAPF1 = rvb->vAPF1 >> 1, vAPF2 = rvb->vAPF2 >> 1;\r | |
111 | int vLIN = rvb->vLIN >> 1, vRIN = rvb->vRIN >> 1;\r | |
112 | int vWALL = rvb->vWALL >> 1;\r | |
f79ea779 | 113 | int vIIR = rvb->vIIR;\r |
f79ea779 | 114 | int ns;\r |
115 | \r | |
ef0559d4 | 116 | #if P_HAVE_PTHREAD || defined(WANT_THREAD_CODE)\r |
117 | sb = &spu.sb_thread[MAXCHAN];\r | |
118 | #endif\r | |
f79ea779 | 119 | if (mlsame_m2o >= space) mlsame_m2o -= space;\r |
120 | if (mrsame_m2o >= space) mrsame_m2o -= space;\r | |
121 | if (mldiff_m2o >= space) mldiff_m2o -= space;\r | |
122 | if (mrdiff_m2o >= space) mrdiff_m2o -= space;\r | |
1775933a | 123 | \r |
650adfd2 | 124 | for (ns = 0; ns < ns_to * 2; )\r |
ef79bbde | 125 | {\r |
961cb15e | 126 | int Lin = RVB[ns];\r |
127 | int Rin = RVB[ns+1];\r | |
128 | int mlsame_m2 = g_buffer(mlsame_m2o) << (15-1);\r | |
129 | int mrsame_m2 = g_buffer(mrsame_m2o) << (15-1);\r | |
130 | int mldiff_m2 = g_buffer(mldiff_m2o) << (15-1);\r | |
131 | int mrdiff_m2 = g_buffer(mrdiff_m2o) << (15-1);\r | |
0f5a4b3a | 132 | int Lout, Rout, out0[2], out1[2];\r |
f79ea779 | 133 | \r |
961cb15e | 134 | ssat32_to_16(Lin); Lin *= vLIN;\r |
135 | ssat32_to_16(Rin); Rin *= vRIN;\r | |
136 | \r | |
0f5a4b3a | 137 | // from nocash psx-spx\r |
f79ea779 | 138 | mlsame_m2 += ((Lin + g_buffer(rvb->dLSAME) * vWALL - mlsame_m2) >> 15) * vIIR;\r |
139 | mrsame_m2 += ((Rin + g_buffer(rvb->dRSAME) * vWALL - mrsame_m2) >> 15) * vIIR;\r | |
140 | mldiff_m2 += ((Lin + g_buffer(rvb->dLDIFF) * vWALL - mldiff_m2) >> 15) * vIIR;\r | |
141 | mrdiff_m2 += ((Rin + g_buffer(rvb->dRDIFF) * vWALL - mrdiff_m2) >> 15) * vIIR;\r | |
961cb15e | 142 | mlsame_m2 >>= (15-1); s_buffer_w(rvb->mLSAME, mlsame_m2);\r |
143 | mrsame_m2 >>= (15-1); s_buffer_w(rvb->mRSAME, mrsame_m2);\r | |
144 | mldiff_m2 >>= (15-1); s_buffer_w(rvb->mLDIFF, mldiff_m2);\r | |
145 | mrdiff_m2 >>= (15-1); s_buffer_w(rvb->mRDIFF, mrdiff_m2);\r | |
f79ea779 | 146 | \r |
147 | Lout = vCOMB1 * g_buffer(rvb->mLCOMB1) + vCOMB2 * g_buffer(rvb->mLCOMB2)\r | |
148 | + vCOMB3 * g_buffer(rvb->mLCOMB3) + vCOMB4 * g_buffer(rvb->mLCOMB4);\r | |
149 | Rout = vCOMB1 * g_buffer(rvb->mRCOMB1) + vCOMB2 * g_buffer(rvb->mRCOMB2)\r | |
150 | + vCOMB3 * g_buffer(rvb->mRCOMB3) + vCOMB4 * g_buffer(rvb->mRCOMB4);\r | |
1775933a | 151 | \r |
05c7cec7 | 152 | preload(SSumLR + ns + 64*2/4 - 4);\r |
153 | \r | |
961cb15e | 154 | Lout -= vAPF1 * g_buffer(rvb->mLAPF1_dAPF1); Lout >>= (15-1);\r |
155 | Rout -= vAPF1 * g_buffer(rvb->mRAPF1_dAPF1); Rout >>= (15-1);\r | |
f79ea779 | 156 | s_buffer_w(rvb->mLAPF1, Lout);\r |
157 | s_buffer_w(rvb->mRAPF1, Rout);\r | |
961cb15e | 158 | Lout = Lout * vAPF1 + (g_buffer(rvb->mLAPF1_dAPF1) << (15-1));\r |
159 | Rout = Rout * vAPF1 + (g_buffer(rvb->mRAPF1_dAPF1) << (15-1));\r | |
1775933a | 160 | \r |
05c7cec7 | 161 | preload(RVB + ns + 64*2/4 - 4);\r |
162 | \r | |
961cb15e | 163 | Lout -= vAPF2 * g_buffer(rvb->mLAPF2_dAPF2); Lout >>= (15-1);\r |
164 | Rout -= vAPF2 * g_buffer(rvb->mRAPF2_dAPF2); Rout >>= (15-1);\r | |
f79ea779 | 165 | s_buffer_w(rvb->mLAPF2, Lout);\r |
166 | s_buffer_w(rvb->mRAPF2, Rout);\r | |
961cb15e | 167 | Lout = Lout * vAPF2 + (g_buffer(rvb->mLAPF2_dAPF2) << (15-1));\r |
168 | Rout = Rout * vAPF2 + (g_buffer(rvb->mRAPF2_dAPF2) << (15-1));\r | |
1775933a | 169 | \r |
961cb15e | 170 | out0[0] = out1[0] = (Lout >> (15-1)) * rvb->VolLeft >> 15;\r |
171 | out0[1] = out1[1] = (Rout >> (15-1)) * rvb->VolRight >> 15;\r | |
0f5a4b3a | 172 | if (do_filter)\r |
ef0559d4 | 173 | reverb_interpolate(sb, curr_addr, out0, out1);\r |
1775933a | 174 | \r |
0f5a4b3a | 175 | SSumLR[ns++] += out0[0];\r |
176 | SSumLR[ns++] += out0[1];\r | |
177 | SSumLR[ns++] += out1[0];\r | |
178 | SSumLR[ns++] += out1[1];\r | |
b72f17a1 | 179 | \r |
180 | curr_addr++;\r | |
f79ea779 | 181 | curr_addr = rvb_wrap(curr_addr, space);\r |
b72f17a1 | 182 | }\r |
b72f17a1 | 183 | }\r |
184 | \r | |
05c7cec7 | 185 | static void MixREVERB_off(int *SSumLR, int ns_to, int curr_addr)\r |
b72f17a1 | 186 | {\r |
05c7cec7 | 187 | const REVERBInfo *rvb = spu.rvb;\r |
f79ea779 | 188 | unsigned short *spuMem = spu.spuMem;\r |
05c7cec7 | 189 | int space = 0x40000 - rvb->StartAddr;\r |
f79ea779 | 190 | int Lout, Rout, ns;\r |
b72f17a1 | 191 | \r |
650adfd2 | 192 | for (ns = 0; ns < ns_to * 2; )\r |
b72f17a1 | 193 | {\r |
05c7cec7 | 194 | preload(SSumLR + ns + 64*2/4 - 4);\r |
195 | \r | |
f79ea779 | 196 | // todo: is this missing COMB and APF1?\r |
197 | Lout = g_buffer(rvb->mLAPF2_dAPF2);\r | |
198 | Rout = g_buffer(rvb->mLAPF2_dAPF2);\r | |
b72f17a1 | 199 | \r |
f79ea779 | 200 | Lout = (Lout * rvb->VolLeft) >> 15;\r |
201 | Rout = (Rout * rvb->VolRight) >> 15;\r | |
1775933a | 202 | \r |
f79ea779 | 203 | SSumLR[ns++] += Lout;\r |
204 | SSumLR[ns++] += Rout;\r | |
205 | SSumLR[ns++] += Lout;\r | |
206 | SSumLR[ns++] += Rout;\r | |
1775933a | 207 | \r |
208 | curr_addr++;\r | |
05c7cec7 | 209 | if (curr_addr >= 0x40000) curr_addr = rvb->StartAddr;\r |
ef79bbde P |
210 | }\r |
211 | }\r | |
212 | \r | |
05c7cec7 | 213 | static void REVERBPrep(void)\r |
1775933a | 214 | {\r |
05c7cec7 | 215 | REVERBInfo *rvb = spu.rvb;\r |
7b2c4897 | 216 | int space, t;\r |
217 | \r | |
20ed712f | 218 | t = regAreaGet(H_SPUReverbAddr);\r |
7b2c4897 | 219 | if (t == 0xFFFF || t <= 0x200)\r |
220 | spu.rvb->StartAddr = spu.rvb->CurrAddr = 0;\r | |
221 | else if (spu.rvb->StartAddr != (t << 2))\r | |
222 | spu.rvb->StartAddr = spu.rvb->CurrAddr = t << 2;\r | |
223 | \r | |
224 | space = 0x40000 - rvb->StartAddr;\r | |
225 | \r | |
226 | #define prep_offs(v, r) \\r | |
227 | t = spu.regArea[(0x1c0 + r) >> 1] * 4; \\r | |
1775933a | 228 | while (t >= space) \\r |
229 | t -= space; \\r | |
7b2c4897 | 230 | rvb->v = t\r |
231 | #define prep_offs2(d, r1, r2) \\r | |
232 | t = spu.regArea[(0x1c0 + r1) >> 1] * 4; \\r | |
233 | t -= spu.regArea[(0x1c0 + r2) >> 1] * 4; \\r | |
234 | while (t < 0) \\r | |
235 | t += space; \\r | |
1775933a | 236 | while (t >= space) \\r |
237 | t -= space; \\r | |
7b2c4897 | 238 | rvb->d = t\r |
239 | \r | |
f79ea779 | 240 | prep_offs(mLSAME, 0x14);\r |
241 | prep_offs(mRSAME, 0x16);\r | |
242 | prep_offs(mLCOMB1, 0x18);\r | |
243 | prep_offs(mRCOMB1, 0x1a);\r | |
244 | prep_offs(mLCOMB2, 0x1c);\r | |
245 | prep_offs(mRCOMB2, 0x1e);\r | |
246 | prep_offs(dLSAME, 0x20);\r | |
247 | prep_offs(dRSAME, 0x22);\r | |
248 | prep_offs(mLDIFF, 0x24);\r | |
249 | prep_offs(mRDIFF, 0x26);\r | |
250 | prep_offs(mLCOMB3, 0x28);\r | |
251 | prep_offs(mRCOMB3, 0x2a);\r | |
252 | prep_offs(mLCOMB4, 0x2c);\r | |
253 | prep_offs(mRCOMB4, 0x2e);\r | |
254 | prep_offs(dLDIFF, 0x30);\r | |
255 | prep_offs(dRDIFF, 0x32);\r | |
256 | prep_offs(mLAPF1, 0x34);\r | |
257 | prep_offs(mRAPF1, 0x36);\r | |
258 | prep_offs(mLAPF2, 0x38);\r | |
259 | prep_offs(mRAPF2, 0x3a);\r | |
260 | prep_offs2(mLAPF1_dAPF1, 0x34, 0);\r | |
261 | prep_offs2(mRAPF1_dAPF1, 0x36, 0);\r | |
262 | prep_offs2(mLAPF2_dAPF2, 0x38, 2);\r | |
263 | prep_offs2(mRAPF2_dAPF2, 0x3a, 2);\r | |
1775933a | 264 | \r |
265 | #undef prep_offs\r | |
266 | #undef prep_offs2\r | |
05c7cec7 | 267 | rvb->dirty = 0;\r |
1775933a | 268 | }\r |
ef79bbde | 269 | \r |
05c7cec7 | 270 | INLINE void REVERBDo(int *SSumLR, int *RVB, int ns_to, int curr_addr)\r |
ef79bbde | 271 | {\r |
3154bfab | 272 | if (spu.spuCtrl & 0x80) // -> reverb on? oki\r |
1775933a | 273 | {\r |
ef0559d4 | 274 | MixREVERB(SSumLR, RVB, ns_to, curr_addr, 0); //spu.interpolation > 1);\r |
b72f17a1 | 275 | }\r |
05c7cec7 | 276 | else if (spu.rvb->VolLeft || spu.rvb->VolRight)\r |
1775933a | 277 | {\r |
05c7cec7 | 278 | MixREVERB_off(SSumLR, ns_to, curr_addr);\r |
1775933a | 279 | }\r |
ef79bbde P |
280 | }\r |
281 | \r | |
282 | ////////////////////////////////////////////////////////////////////////\r | |
283 | \r | |
284 | #endif\r | |
285 | \r | |
1775933a | 286 | // vim:shiftwidth=1:expandtab\r |