frontend: update libpicofe, fix missed callbacks
[pcsx_rearmed.git] / plugins / dfsound / reverb.c
CommitLineData
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
35INLINE 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 46INLINE 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
60INLINE 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 77static 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
97static 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 185static 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 213static 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 270INLINE 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