comparison src/modplug/fastmix.cxx @ 136:6b5a52635b3b trunk

[svn] - like with so many other things, modplug is now maintained by us.
author nenolod
date Sun, 29 Oct 2006 01:04:52 -0700
parents
children b1128efde471
comparison
equal deleted inserted replaced
135:33d24bd94ccc 136:6b5a52635b3b
1 /*
2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version.
6 *
7 * Authors: Olivier Lapicque <olivierl@jps.net>
8 * Markus Fick <webmaster@mark-f.de> spline + fir-resampler
9 */
10
11 #include "stdafx.h"
12 #include "sndfile.h"
13 #include <math.h>
14
15 #ifdef MSC_VER
16 #pragma bss_seg(".modplug")
17 #endif
18
19 // Front Mix Buffer (Also room for interleaved rear mix)
20 int MixSoundBuffer[MIXBUFFERSIZE*4];
21
22 // Reverb Mix Buffer
23 #ifndef MODPLUG_NO_REVERB
24 int MixReverbBuffer[MIXBUFFERSIZE*2];
25 extern UINT gnReverbSend;
26 #endif
27
28 #ifndef MODPLUG_FASTSOUNDLIB
29 int MixRearBuffer[MIXBUFFERSIZE*2];
30 float MixFloatBuffer[MIXBUFFERSIZE*2];
31 #endif
32
33 #ifdef MSC_VER
34 #pragma bss_seg()
35 #endif
36
37
38 extern LONG gnDryROfsVol;
39 extern LONG gnDryLOfsVol;
40 extern LONG gnRvbROfsVol;
41 extern LONG gnRvbLOfsVol;
42
43 // 4x256 taps polyphase FIR resampling filter
44 extern short int gFastSinc[];
45 extern short int gKaiserSinc[]; // 8-taps polyphase
46 /*
47 -----------------------------------------------------------------------------
48 cubic spline interpolation doc,
49 (derived from "digital image warping", g. wolberg)
50
51 interpolation polynomial: f(x) = A3*(x-floor(x))**3 + A2*(x-floor(x))**2 + A1*(x-floor(x)) + A0
52
53 with Y = equispaced data points (dist=1), YD = first derivates of data points and IP = floor(x)
54 the A[0..3] can be found by solving
55 A0 = Y[IP]
56 A1 = YD[IP]
57 A2 = 3*(Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1]
58 A3 = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] - YD[IP+1]
59
60 with the first derivates as
61 YD[IP] = 0.5 * (Y[IP+1] - Y[IP-1]);
62 YD[IP+1] = 0.5 * (Y[IP+2] - Y[IP])
63
64 the coefs becomes
65 A0 = Y[IP]
66 A1 = YD[IP]
67 = 0.5 * (Y[IP+1] - Y[IP-1]);
68 A2 = 3.0 * (Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1]
69 = 3.0 * (Y[IP+1] - Y[IP]) - 0.5 * 2.0 * (Y[IP+1] - Y[IP-1]) - 0.5 * (Y[IP+2] - Y[IP])
70 = 3.0 * Y[IP+1] - 3.0 * Y[IP] - Y[IP+1] + Y[IP-1] - 0.5 * Y[IP+2] + 0.5 * Y[IP]
71 = -0.5 * Y[IP+2] + 2.0 * Y[IP+1] - 2.5 * Y[IP] + Y[IP-1]
72 = Y[IP-1] + 2 * Y[IP+1] - 0.5 * (5.0 * Y[IP] + Y[IP+2])
73 A3 = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] + YD[IP+1]
74 = -2.0 * Y[IP+1] + 2.0 * Y[IP] + 0.5 * (Y[IP+1] - Y[IP-1]) + 0.5 * (Y[IP+2] - Y[IP])
75 = -2.0 * Y[IP+1] + 2.0 * Y[IP] + 0.5 * Y[IP+1] - 0.5 * Y[IP-1] + 0.5 * Y[IP+2] - 0.5 * Y[IP]
76 = 0.5 * Y[IP+2] - 1.5 * Y[IP+1] + 1.5 * Y[IP] - 0.5 * Y[IP-1]
77 = 0.5 * (3.0 * (Y[IP] - Y[IP+1]) - Y[IP-1] + YP[IP+2])
78
79 then interpolated data value is (horner rule)
80 out = (((A3*x)+A2)*x+A1)*x+A0
81
82 this gives parts of data points Y[IP-1] to Y[IP+2] of
83 part x**3 x**2 x**1 x**0
84 Y[IP-1] -0.5 1 -0.5 0
85 Y[IP] 1.5 -2.5 0 1
86 Y[IP+1] -1.5 2 0.5 0
87 Y[IP+2] 0.5 -0.5 0 0
88 -----------------------------------------------------------------------------
89 */
90 // number of bits used to scale spline coefs
91 #define SPLINE_QUANTBITS 14
92 #define SPLINE_QUANTSCALE (1L<<SPLINE_QUANTBITS)
93 #define SPLINE_8SHIFT (SPLINE_QUANTBITS-8)
94 #define SPLINE_16SHIFT (SPLINE_QUANTBITS)
95 // forces coefsset to unity gain
96 #define SPLINE_CLAMPFORUNITY
97 // log2(number) of precalculated splines (range is [4..14])
98 #define SPLINE_FRACBITS 10
99 #define SPLINE_LUTLEN (1L<<SPLINE_FRACBITS)
100
101 class CzCUBICSPLINE
102 { public:
103 CzCUBICSPLINE( );
104 ~CzCUBICSPLINE( );
105 static signed short lut[4*(1L<<SPLINE_FRACBITS)];
106 };
107
108 signed short CzCUBICSPLINE::lut[4*(1L<<SPLINE_FRACBITS)];
109
110 CzCUBICSPLINE::CzCUBICSPLINE( )
111 { int _LIi;
112 int _LLen = (1L<<SPLINE_FRACBITS);
113 float _LFlen = 1.0f / (float)_LLen;
114 float _LScale = (float)SPLINE_QUANTSCALE;
115 for(_LIi=0;_LIi<_LLen;_LIi++)
116 { float _LCm1, _LC0, _LC1, _LC2;
117 float _LX = ((float)_LIi)*_LFlen;
118 int _LSum,_LIdx = _LIi<<2;
119 _LCm1 = (float)floor( 0.5 + _LScale * (-0.5*_LX*_LX*_LX + 1.0 * _LX*_LX - 0.5 * _LX ) );
120 _LC0 = (float)floor( 0.5 + _LScale * ( 1.5*_LX*_LX*_LX - 2.5 * _LX*_LX + 1.0 ) );
121 _LC1 = (float)floor( 0.5 + _LScale * (-1.5*_LX*_LX*_LX + 2.0 * _LX*_LX + 0.5 * _LX ) );
122 _LC2 = (float)floor( 0.5 + _LScale * ( 0.5*_LX*_LX*_LX - 0.5 * _LX*_LX ) );
123 lut[_LIdx+0] = (signed short)( (_LCm1 < -_LScale) ? -_LScale : ((_LCm1 > _LScale) ? _LScale : _LCm1) );
124 lut[_LIdx+1] = (signed short)( (_LC0 < -_LScale) ? -_LScale : ((_LC0 > _LScale) ? _LScale : _LC0 ) );
125 lut[_LIdx+2] = (signed short)( (_LC1 < -_LScale) ? -_LScale : ((_LC1 > _LScale) ? _LScale : _LC1 ) );
126 lut[_LIdx+3] = (signed short)( (_LC2 < -_LScale) ? -_LScale : ((_LC2 > _LScale) ? _LScale : _LC2 ) );
127 #ifdef SPLINE_CLAMPFORUNITY
128 _LSum = lut[_LIdx+0]+lut[_LIdx+1]+lut[_LIdx+2]+lut[_LIdx+3];
129 if( _LSum != SPLINE_QUANTSCALE )
130 { int _LMax = _LIdx;
131 if( lut[_LIdx+1]>lut[_LMax] ) _LMax = _LIdx+1;
132 if( lut[_LIdx+2]>lut[_LMax] ) _LMax = _LIdx+2;
133 if( lut[_LIdx+3]>lut[_LMax] ) _LMax = _LIdx+3;
134 lut[_LMax] += (SPLINE_QUANTSCALE-_LSum);
135 }
136 #endif
137 }
138 }
139
140 CzCUBICSPLINE::~CzCUBICSPLINE( )
141 { // nothing todo
142 }
143
144 CzCUBICSPLINE sspline;
145
146 /*
147 ------------------------------------------------------------------------------------------------
148 fir interpolation doc,
149 (derived from "an engineer's guide to fir digital filters", n.j. loy)
150
151 calculate coefficients for ideal lowpass filter (with cutoff = fc in 0..1 (mapped to 0..nyquist))
152 c[-N..N] = (i==0) ? fc : sin(fc*pi*i)/(pi*i)
153
154 then apply selected window to coefficients
155 c[-N..N] *= w(0..N)
156 with n in 2*N and w(n) being a window function (see loy)
157
158 then calculate gain and scale filter coefs to have unity gain.
159 ------------------------------------------------------------------------------------------------
160 */
161 // quantizer scale of window coefs
162 #define WFIR_QUANTBITS 15
163 #define WFIR_QUANTSCALE (1L<<WFIR_QUANTBITS)
164 #define WFIR_8SHIFT (WFIR_QUANTBITS-8)
165 #define WFIR_16BITSHIFT (WFIR_QUANTBITS)
166 // log2(number)-1 of precalculated taps range is [4..12]
167 #define WFIR_FRACBITS 10
168 #define WFIR_LUTLEN ((1L<<(WFIR_FRACBITS+1))+1)
169 // number of samples in window
170 #define WFIR_LOG2WIDTH 3
171 #define WFIR_WIDTH (1L<<WFIR_LOG2WIDTH)
172 #define WFIR_SMPSPERWING ((WFIR_WIDTH-1)>>1)
173 // cutoff (1.0 == pi/2)
174 #define WFIR_CUTOFF 0.90f
175 // wfir type
176 #define WFIR_HANN 0
177 #define WFIR_HAMMING 1
178 #define WFIR_BLACKMANEXACT 2
179 #define WFIR_BLACKMAN3T61 3
180 #define WFIR_BLACKMAN3T67 4
181 #define WFIR_BLACKMAN4T92 5
182 #define WFIR_BLACKMAN4T74 6
183 #define WFIR_KAISER4T 7
184 #define WFIR_TYPE WFIR_BLACKMANEXACT
185 // wfir help
186 #ifndef M_zPI
187 #define M_zPI 3.1415926535897932384626433832795
188 #endif
189 #define M_zEPS 1e-8
190 #define M_zBESSELEPS 1e-21
191
192 class CzWINDOWEDFIR
193 {
194 public:
195 CzWINDOWEDFIR( );
196 ~CzWINDOWEDFIR( );
197 float coef( int _PCnr, float _POfs, float _PCut, int _PWidth, int _PType ) //float _PPos, float _PFc, int _PLen )
198 {
199 double _LWidthM1 = _PWidth-1;
200 double _LWidthM1Half = 0.5*_LWidthM1;
201 double _LPosU = ((double)_PCnr - _POfs);
202 double _LPos = _LPosU-_LWidthM1Half;
203 double _LPIdl = 2.0*M_zPI/_LWidthM1;
204 double _LWc,_LSi;
205 if( fabs(_LPos)<M_zEPS ) {
206 _LWc = 1.0;
207 _LSi = _PCut;
208 } else {
209 switch( _PType )
210 {
211 case WFIR_HANN:
212 _LWc = 0.50 - 0.50 * cos(_LPIdl*_LPosU);
213 break;
214 case WFIR_HAMMING:
215 _LWc = 0.54 - 0.46 * cos(_LPIdl*_LPosU);
216 break;
217 case WFIR_BLACKMANEXACT:
218 _LWc = 0.42 - 0.50 * cos(_LPIdl*_LPosU) + 0.08 * cos(2.0*_LPIdl*_LPosU);
219 break;
220 case WFIR_BLACKMAN3T61:
221 _LWc = 0.44959 - 0.49364 * cos(_LPIdl*_LPosU) + 0.05677 * cos(2.0*_LPIdl*_LPosU);
222 break;
223 case WFIR_BLACKMAN3T67:
224 _LWc = 0.42323 - 0.49755 * cos(_LPIdl*_LPosU) + 0.07922 * cos(2.0*_LPIdl*_LPosU);
225 break;
226 case WFIR_BLACKMAN4T92:
227 _LWc = 0.35875 - 0.48829 * cos(_LPIdl*_LPosU) + 0.14128 * cos(2.0*_LPIdl*_LPosU) - 0.01168 * cos(3.0*_LPIdl*_LPosU);
228 break;
229 case WFIR_BLACKMAN4T74:
230 _LWc = 0.40217 - 0.49703 * cos(_LPIdl*_LPosU) + 0.09392 * cos(2.0*_LPIdl*_LPosU) - 0.00183 * cos(3.0*_LPIdl*_LPosU);
231 break;
232 case WFIR_KAISER4T:
233 _LWc = 0.40243 - 0.49804 * cos(_LPIdl*_LPosU) + 0.09831 * cos(2.0*_LPIdl*_LPosU) - 0.00122 * cos(3.0*_LPIdl*_LPosU);
234 break;
235 default:
236 _LWc = 1.0;
237 break;
238 }
239 _LPos *= M_zPI;
240 _LSi = sin(_PCut*_LPos)/_LPos;
241 }
242 return (float)(_LWc*_LSi);
243 }
244 static signed short lut[WFIR_LUTLEN*WFIR_WIDTH];
245 };
246
247 signed short CzWINDOWEDFIR::lut[WFIR_LUTLEN*WFIR_WIDTH];
248
249 CzWINDOWEDFIR::CzWINDOWEDFIR()
250 {
251 int _LPcl;
252 float _LPcllen = (float)(1L<<WFIR_FRACBITS); // number of precalculated lines for 0..1 (-1..0)
253 float _LNorm = 1.0f / (float)(2.0f * _LPcllen);
254 float _LCut = WFIR_CUTOFF;
255 float _LScale = (float)WFIR_QUANTSCALE;
256 for( _LPcl=0;_LPcl<WFIR_LUTLEN;_LPcl++ )
257 {
258 float _LGain,_LCoefs[WFIR_WIDTH];
259 float _LOfs = ((float)_LPcl-_LPcllen)*_LNorm;
260 int _LCc,_LIdx = _LPcl<<WFIR_LOG2WIDTH;
261 for( _LCc=0,_LGain=0.0f;_LCc<WFIR_WIDTH;_LCc++ )
262 { _LGain += (_LCoefs[_LCc] = coef( _LCc, _LOfs, _LCut, WFIR_WIDTH, WFIR_TYPE ));
263 }
264 _LGain = 1.0f/_LGain;
265 for( _LCc=0;_LCc<WFIR_WIDTH;_LCc++ )
266 { float _LCoef = (float)floor( 0.5 + _LScale*_LCoefs[_LCc]*_LGain );
267 lut[_LIdx+_LCc] = (signed short)( (_LCoef<-_LScale)?-_LScale:((_LCoef>_LScale)?_LScale:_LCoef) );
268 }
269 }
270 }
271
272 CzWINDOWEDFIR::~CzWINDOWEDFIR()
273 { // nothing todo
274 }
275
276 CzWINDOWEDFIR sfir;
277
278 // ----------------------------------------------------------------------------
279 // MIXING MACROS
280 // ----------------------------------------------------------------------------
281 /////////////////////////////////////////////////////
282 // Mixing Macros
283
284 #define SNDMIX_BEGINSAMPLELOOP8\
285 register MODCHANNEL * const pChn = pChannel;\
286 nPos = pChn->nPosLo;\
287 const signed char *p = (signed char *)(pChn->pCurrentSample+pChn->nPos);\
288 if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\
289 int *pvol = pbuffer;\
290 do {
291
292 #define SNDMIX_BEGINSAMPLELOOP16\
293 register MODCHANNEL * const pChn = pChannel;\
294 nPos = pChn->nPosLo;\
295 const signed short *p = (signed short *)(pChn->pCurrentSample+(pChn->nPos*2));\
296 if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\
297 int *pvol = pbuffer;\
298 do {
299
300 #define SNDMIX_ENDSAMPLELOOP\
301 nPos += pChn->nInc;\
302 } while (pvol < pbufmax);\
303 pChn->nPos += nPos >> 16;\
304 pChn->nPosLo = nPos & 0xFFFF;
305
306 #define SNDMIX_ENDSAMPLELOOP8 SNDMIX_ENDSAMPLELOOP
307 #define SNDMIX_ENDSAMPLELOOP16 SNDMIX_ENDSAMPLELOOP
308
309 //////////////////////////////////////////////////////////////////////////////
310 // Mono
311
312 // No interpolation
313 #define SNDMIX_GETMONOVOL8NOIDO\
314 int vol = p[nPos >> 16] << 8;
315
316 #define SNDMIX_GETMONOVOL16NOIDO\
317 int vol = p[nPos >> 16];
318
319 // Linear Interpolation
320 #define SNDMIX_GETMONOVOL8LINEAR\
321 int poshi = nPos >> 16;\
322 int poslo = (nPos >> 8) & 0xFF;\
323 int srcvol = p[poshi];\
324 int destvol = p[poshi+1];\
325 int vol = (srcvol<<8) + ((int)(poslo * (destvol - srcvol)));
326
327 #define SNDMIX_GETMONOVOL16LINEAR\
328 int poshi = nPos >> 16;\
329 int poslo = (nPos >> 8) & 0xFF;\
330 int srcvol = p[poshi];\
331 int destvol = p[poshi+1];\
332 int vol = srcvol + ((int)(poslo * (destvol - srcvol)) >> 8);
333
334 // spline interpolation (2 guard bits should be enough???)
335 #define SPLINE_FRACSHIFT ((16-SPLINE_FRACBITS)-2)
336 #define SPLINE_FRACMASK (((1L<<(16-SPLINE_FRACSHIFT))-1)&~3)
337
338 #define SNDMIX_GETMONOVOL8SPLINE \
339 int poshi = nPos >> 16; \
340 int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
341 int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \
342 CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \
343 CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \
344 CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_8SHIFT;
345
346 #define SNDMIX_GETMONOVOL16SPLINE \
347 int poshi = nPos >> 16; \
348 int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
349 int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \
350 CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \
351 CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \
352 CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_16SHIFT;
353
354
355 // fir interpolation
356 #define WFIR_FRACSHIFT (16-(WFIR_FRACBITS+1+WFIR_LOG2WIDTH))
357 #define WFIR_FRACMASK ((((1L<<(17-WFIR_FRACSHIFT))-1)&~((1L<<WFIR_LOG2WIDTH)-1)))
358 #define WFIR_FRACHALVE (1L<<(16-(WFIR_FRACBITS+2)))
359
360 #define SNDMIX_GETMONOVOL8FIRFILTER \
361 int poshi = nPos >> 16;\
362 int poslo = (nPos & 0xFFFF);\
363 int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
364 int vol = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \
365 vol += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \
366 vol += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \
367 vol += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \
368 vol += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \
369 vol += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \
370 vol += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \
371 vol += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \
372 vol >>= WFIR_8SHIFT;
373
374 #define SNDMIX_GETMONOVOL16FIRFILTER \
375 int poshi = nPos >> 16;\
376 int poslo = (nPos & 0xFFFF);\
377 int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
378 int vol1 = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \
379 vol1 += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \
380 vol1 += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \
381 vol1 += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \
382 int vol2 = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \
383 vol2 += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \
384 vol2 += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \
385 vol2 += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \
386 int vol = ((vol1>>1)+(vol2>>1)) >> (WFIR_16BITSHIFT-1);
387
388 /////////////////////////////////////////////////////////////////////////////
389 // Stereo
390
391 // No interpolation
392 #define SNDMIX_GETSTEREOVOL8NOIDO\
393 int vol_l = p[(nPos>>16)*2] << 8;\
394 int vol_r = p[(nPos>>16)*2+1] << 8;
395
396 #define SNDMIX_GETSTEREOVOL16NOIDO\
397 int vol_l = p[(nPos>>16)*2];\
398 int vol_r = p[(nPos>>16)*2+1];
399
400 // Linear Interpolation
401 #define SNDMIX_GETSTEREOVOL8LINEAR\
402 int poshi = nPos >> 16;\
403 int poslo = (nPos >> 8) & 0xFF;\
404 int srcvol_l = p[poshi*2];\
405 int vol_l = (srcvol_l<<8) + ((int)(poslo * (p[poshi*2+2] - srcvol_l)));\
406 int srcvol_r = p[poshi*2+1];\
407 int vol_r = (srcvol_r<<8) + ((int)(poslo * (p[poshi*2+3] - srcvol_r)));
408
409 #define SNDMIX_GETSTEREOVOL16LINEAR\
410 int poshi = nPos >> 16;\
411 int poslo = (nPos >> 8) & 0xFF;\
412 int srcvol_l = p[poshi*2];\
413 int vol_l = srcvol_l + ((int)(poslo * (p[poshi*2+2] - srcvol_l)) >> 8);\
414 int srcvol_r = p[poshi*2+1];\
415 int vol_r = srcvol_r + ((int)(poslo * (p[poshi*2+3] - srcvol_r)) >> 8);\
416
417 // Spline Interpolation
418 #define SNDMIX_GETSTEREOVOL8SPLINE \
419 int poshi = nPos >> 16; \
420 int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
421 int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \
422 CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \
423 CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \
424 CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_8SHIFT; \
425 int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \
426 CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \
427 CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \
428 CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_8SHIFT;
429
430 #define SNDMIX_GETSTEREOVOL16SPLINE \
431 int poshi = nPos >> 16; \
432 int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
433 int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \
434 CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \
435 CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \
436 CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_16SHIFT; \
437 int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \
438 CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \
439 CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \
440 CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_16SHIFT;
441
442 // fir interpolation
443 #define SNDMIX_GETSTEREOVOL8FIRFILTER \
444 int poshi = nPos >> 16;\
445 int poslo = (nPos & 0xFFFF);\
446 int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
447 int vol_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \
448 vol_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \
449 vol_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \
450 vol_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \
451 vol_l += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \
452 vol_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \
453 vol_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \
454 vol_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \
455 vol_l >>= WFIR_8SHIFT; \
456 int vol_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \
457 vol_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \
458 vol_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \
459 vol_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \
460 vol_r += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \
461 vol_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \
462 vol_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \
463 vol_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \
464 vol_r >>= WFIR_8SHIFT;
465
466 #define SNDMIX_GETSTEREOVOL16FIRFILTER \
467 int poshi = nPos >> 16;\
468 int poslo = (nPos & 0xFFFF);\
469 int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
470 int vol1_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \
471 vol1_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \
472 vol1_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \
473 vol1_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \
474 int vol2_l = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \
475 vol2_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \
476 vol2_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \
477 vol2_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \
478 int vol_l = ((vol1_l>>1)+(vol2_l>>1)) >> (WFIR_16BITSHIFT-1); \
479 int vol1_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \
480 vol1_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \
481 vol1_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \
482 vol1_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \
483 int vol2_r = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \
484 vol2_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \
485 vol2_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \
486 vol2_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \
487 int vol_r = ((vol1_r>>1)+(vol2_r>>1)) >> (WFIR_16BITSHIFT-1);
488
489 /////////////////////////////////////////////////////////////////////////////
490
491 #define SNDMIX_STOREMONOVOL\
492 pvol[0] += vol * pChn->nRightVol;\
493 pvol[1] += vol * pChn->nLeftVol;\
494 pvol += 2;
495
496 #define SNDMIX_STORESTEREOVOL\
497 pvol[0] += vol_l * pChn->nRightVol;\
498 pvol[1] += vol_r * pChn->nLeftVol;\
499 pvol += 2;
500
501 #define SNDMIX_STOREFASTMONOVOL\
502 int v = vol * pChn->nRightVol;\
503 pvol[0] += v;\
504 pvol[1] += v;\
505 pvol += 2;
506
507 #define SNDMIX_RAMPMONOVOL\
508 nRampLeftVol += pChn->nLeftRamp;\
509 nRampRightVol += pChn->nRightRamp;\
510 pvol[0] += vol * (nRampRightVol >> VOLUMERAMPPRECISION);\
511 pvol[1] += vol * (nRampLeftVol >> VOLUMERAMPPRECISION);\
512 pvol += 2;
513
514 #define SNDMIX_RAMPFASTMONOVOL\
515 nRampRightVol += pChn->nRightRamp;\
516 int fastvol = vol * (nRampRightVol >> VOLUMERAMPPRECISION);\
517 pvol[0] += fastvol;\
518 pvol[1] += fastvol;\
519 pvol += 2;
520
521 #define SNDMIX_RAMPSTEREOVOL\
522 nRampLeftVol += pChn->nLeftRamp;\
523 nRampRightVol += pChn->nRightRamp;\
524 pvol[0] += vol_l * (nRampRightVol >> VOLUMERAMPPRECISION);\
525 pvol[1] += vol_r * (nRampLeftVol >> VOLUMERAMPPRECISION);\
526 pvol += 2;
527
528
529 ///////////////////////////////////////////////////
530 // Resonant Filters
531
532 // Mono
533 #define MIX_BEGIN_FILTER\
534 int fy1 = pChannel->nFilter_Y1;\
535 int fy2 = pChannel->nFilter_Y2;\
536
537 #define MIX_END_FILTER\
538 pChannel->nFilter_Y1 = fy1;\
539 pChannel->nFilter_Y2 = fy2;
540
541 #define SNDMIX_PROCESSFILTER\
542 vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
543 fy2 = fy1;\
544 fy1 = vol;\
545
546 // Stereo
547 #define MIX_BEGIN_STEREO_FILTER\
548 int fy1 = pChannel->nFilter_Y1;\
549 int fy2 = pChannel->nFilter_Y2;\
550 int fy3 = pChannel->nFilter_Y3;\
551 int fy4 = pChannel->nFilter_Y4;\
552
553 #define MIX_END_STEREO_FILTER\
554 pChannel->nFilter_Y1 = fy1;\
555 pChannel->nFilter_Y2 = fy2;\
556 pChannel->nFilter_Y3 = fy3;\
557 pChannel->nFilter_Y4 = fy4;\
558
559 #define SNDMIX_PROCESSSTEREOFILTER\
560 vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
561 vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\
562 fy2 = fy1; fy1 = vol_l;\
563 fy4 = fy3; fy3 = vol_r;\
564
565 //////////////////////////////////////////////////////////
566 // Interfaces
567
568 typedef VOID (MPPASMCALL * LPMIXINTERFACE)(MODCHANNEL *, int *, int *);
569
570 #define BEGIN_MIX_INTERFACE(func)\
571 VOID MPPASMCALL func(MODCHANNEL *pChannel, int *pbuffer, int *pbufmax)\
572 {\
573 LONG nPos;
574
575 #define END_MIX_INTERFACE()\
576 SNDMIX_ENDSAMPLELOOP\
577 }
578
579 // Volume Ramps
580 #define BEGIN_RAMPMIX_INTERFACE(func)\
581 BEGIN_MIX_INTERFACE(func)\
582 LONG nRampRightVol = pChannel->nRampRightVol;\
583 LONG nRampLeftVol = pChannel->nRampLeftVol;
584
585 #define END_RAMPMIX_INTERFACE()\
586 SNDMIX_ENDSAMPLELOOP\
587 pChannel->nRampRightVol = nRampRightVol;\
588 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
589 pChannel->nRampLeftVol = nRampLeftVol;\
590 pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
591 }
592
593 #define BEGIN_FASTRAMPMIX_INTERFACE(func)\
594 BEGIN_MIX_INTERFACE(func)\
595 LONG nRampRightVol = pChannel->nRampRightVol;
596
597 #define END_FASTRAMPMIX_INTERFACE()\
598 SNDMIX_ENDSAMPLELOOP\
599 pChannel->nRampRightVol = nRampRightVol;\
600 pChannel->nRampLeftVol = nRampRightVol;\
601 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
602 pChannel->nLeftVol = pChannel->nRightVol;\
603 }
604
605
606 // Mono Resonant Filters
607 #define BEGIN_MIX_FLT_INTERFACE(func)\
608 BEGIN_MIX_INTERFACE(func)\
609 MIX_BEGIN_FILTER
610
611
612 #define END_MIX_FLT_INTERFACE()\
613 SNDMIX_ENDSAMPLELOOP\
614 MIX_END_FILTER\
615 }
616
617 #define BEGIN_RAMPMIX_FLT_INTERFACE(func)\
618 BEGIN_MIX_INTERFACE(func)\
619 LONG nRampRightVol = pChannel->nRampRightVol;\
620 LONG nRampLeftVol = pChannel->nRampLeftVol;\
621 MIX_BEGIN_FILTER
622
623 #define END_RAMPMIX_FLT_INTERFACE()\
624 SNDMIX_ENDSAMPLELOOP\
625 MIX_END_FILTER\
626 pChannel->nRampRightVol = nRampRightVol;\
627 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
628 pChannel->nRampLeftVol = nRampLeftVol;\
629 pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
630 }
631
632 // Stereo Resonant Filters
633 #define BEGIN_MIX_STFLT_INTERFACE(func)\
634 BEGIN_MIX_INTERFACE(func)\
635 MIX_BEGIN_STEREO_FILTER
636
637
638 #define END_MIX_STFLT_INTERFACE()\
639 SNDMIX_ENDSAMPLELOOP\
640 MIX_END_STEREO_FILTER\
641 }
642
643 #define BEGIN_RAMPMIX_STFLT_INTERFACE(func)\
644 BEGIN_MIX_INTERFACE(func)\
645 LONG nRampRightVol = pChannel->nRampRightVol;\
646 LONG nRampLeftVol = pChannel->nRampLeftVol;\
647 MIX_BEGIN_STEREO_FILTER
648
649 #define END_RAMPMIX_STFLT_INTERFACE()\
650 SNDMIX_ENDSAMPLELOOP\
651 MIX_END_STEREO_FILTER\
652 pChannel->nRampRightVol = nRampRightVol;\
653 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
654 pChannel->nRampLeftVol = nRampLeftVol;\
655 pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
656 }
657
658
659 /////////////////////////////////////////////////////
660 //
661
662 void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples);
663 void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
664 void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
665 void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount);
666 void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
667
668 /////////////////////////////////////////////////////
669 // Mono samples functions
670
671 BEGIN_MIX_INTERFACE(Mono8BitMix)
672 SNDMIX_BEGINSAMPLELOOP8
673 SNDMIX_GETMONOVOL8NOIDO
674 SNDMIX_STOREMONOVOL
675 END_MIX_INTERFACE()
676
677 BEGIN_MIX_INTERFACE(Mono16BitMix)
678 SNDMIX_BEGINSAMPLELOOP16
679 SNDMIX_GETMONOVOL16NOIDO
680 SNDMIX_STOREMONOVOL
681 END_MIX_INTERFACE()
682
683 BEGIN_MIX_INTERFACE(Mono8BitLinearMix)
684 SNDMIX_BEGINSAMPLELOOP8
685 SNDMIX_GETMONOVOL8LINEAR
686 SNDMIX_STOREMONOVOL
687 END_MIX_INTERFACE()
688
689 BEGIN_MIX_INTERFACE(Mono16BitLinearMix)
690 SNDMIX_BEGINSAMPLELOOP16
691 SNDMIX_GETMONOVOL16LINEAR
692 SNDMIX_STOREMONOVOL
693 END_MIX_INTERFACE()
694
695 BEGIN_MIX_INTERFACE(Mono8BitSplineMix)
696 SNDMIX_BEGINSAMPLELOOP8
697 SNDMIX_GETMONOVOL8SPLINE
698 SNDMIX_STOREMONOVOL
699 END_MIX_INTERFACE()
700
701 BEGIN_MIX_INTERFACE(Mono16BitSplineMix)
702 SNDMIX_BEGINSAMPLELOOP16
703 SNDMIX_GETMONOVOL16SPLINE
704 SNDMIX_STOREMONOVOL
705 END_MIX_INTERFACE()
706
707 BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix)
708 SNDMIX_BEGINSAMPLELOOP8
709 SNDMIX_GETMONOVOL8FIRFILTER
710 SNDMIX_STOREMONOVOL
711 END_MIX_INTERFACE()
712
713 BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix)
714 SNDMIX_BEGINSAMPLELOOP16
715 SNDMIX_GETMONOVOL16FIRFILTER
716 SNDMIX_STOREMONOVOL
717 END_MIX_INTERFACE()
718
719
720 // Volume Ramps
721 BEGIN_RAMPMIX_INTERFACE(Mono8BitRampMix)
722 SNDMIX_BEGINSAMPLELOOP8
723 SNDMIX_GETMONOVOL8NOIDO
724 SNDMIX_RAMPMONOVOL
725 END_RAMPMIX_INTERFACE()
726
727 BEGIN_RAMPMIX_INTERFACE(Mono16BitRampMix)
728 SNDMIX_BEGINSAMPLELOOP16
729 SNDMIX_GETMONOVOL16NOIDO
730 SNDMIX_RAMPMONOVOL
731 END_RAMPMIX_INTERFACE()
732
733 BEGIN_RAMPMIX_INTERFACE(Mono8BitLinearRampMix)
734 SNDMIX_BEGINSAMPLELOOP8
735 SNDMIX_GETMONOVOL8LINEAR
736 SNDMIX_RAMPMONOVOL
737 END_RAMPMIX_INTERFACE()
738
739 BEGIN_RAMPMIX_INTERFACE(Mono16BitLinearRampMix)
740 SNDMIX_BEGINSAMPLELOOP16
741 SNDMIX_GETMONOVOL16LINEAR
742 SNDMIX_RAMPMONOVOL
743 END_RAMPMIX_INTERFACE()
744
745 BEGIN_RAMPMIX_INTERFACE(Mono8BitSplineRampMix)
746 SNDMIX_BEGINSAMPLELOOP8
747 SNDMIX_GETMONOVOL8SPLINE
748 SNDMIX_RAMPMONOVOL
749 END_RAMPMIX_INTERFACE()
750
751 BEGIN_RAMPMIX_INTERFACE(Mono16BitSplineRampMix)
752 SNDMIX_BEGINSAMPLELOOP16
753 SNDMIX_GETMONOVOL16SPLINE
754 SNDMIX_RAMPMONOVOL
755 END_RAMPMIX_INTERFACE()
756
757 BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix)
758 SNDMIX_BEGINSAMPLELOOP8
759 SNDMIX_GETMONOVOL8FIRFILTER
760 SNDMIX_RAMPMONOVOL
761 END_RAMPMIX_INTERFACE()
762
763 BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix)
764 SNDMIX_BEGINSAMPLELOOP16
765 SNDMIX_GETMONOVOL16FIRFILTER
766 SNDMIX_RAMPMONOVOL
767 END_RAMPMIX_INTERFACE()
768
769
770 //////////////////////////////////////////////////////
771 // Fast mono mix for leftvol=rightvol (1 less imul)
772
773 BEGIN_MIX_INTERFACE(FastMono8BitMix)
774 SNDMIX_BEGINSAMPLELOOP8
775 SNDMIX_GETMONOVOL8NOIDO
776 SNDMIX_STOREFASTMONOVOL
777 END_MIX_INTERFACE()
778
779 BEGIN_MIX_INTERFACE(FastMono16BitMix)
780 SNDMIX_BEGINSAMPLELOOP16
781 SNDMIX_GETMONOVOL16NOIDO
782 SNDMIX_STOREFASTMONOVOL
783 END_MIX_INTERFACE()
784
785 BEGIN_MIX_INTERFACE(FastMono8BitLinearMix)
786 SNDMIX_BEGINSAMPLELOOP8
787 SNDMIX_GETMONOVOL8LINEAR
788 SNDMIX_STOREFASTMONOVOL
789 END_MIX_INTERFACE()
790
791 BEGIN_MIX_INTERFACE(FastMono16BitLinearMix)
792 SNDMIX_BEGINSAMPLELOOP16
793 SNDMIX_GETMONOVOL16LINEAR
794 SNDMIX_STOREFASTMONOVOL
795 END_MIX_INTERFACE()
796
797 BEGIN_MIX_INTERFACE(FastMono8BitSplineMix)
798 SNDMIX_BEGINSAMPLELOOP8
799 SNDMIX_GETMONOVOL8SPLINE
800 SNDMIX_STOREFASTMONOVOL
801 END_MIX_INTERFACE()
802
803 BEGIN_MIX_INTERFACE(FastMono16BitSplineMix)
804 SNDMIX_BEGINSAMPLELOOP16
805 SNDMIX_GETMONOVOL16SPLINE
806 SNDMIX_STOREFASTMONOVOL
807 END_MIX_INTERFACE()
808
809 BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix)
810 SNDMIX_BEGINSAMPLELOOP8
811 SNDMIX_GETMONOVOL8FIRFILTER
812 SNDMIX_STOREFASTMONOVOL
813 END_MIX_INTERFACE()
814
815 BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix)
816 SNDMIX_BEGINSAMPLELOOP16
817 SNDMIX_GETMONOVOL16FIRFILTER
818 SNDMIX_STOREFASTMONOVOL
819 END_MIX_INTERFACE()
820
821
822 // Fast Ramps
823 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitRampMix)
824 SNDMIX_BEGINSAMPLELOOP8
825 SNDMIX_GETMONOVOL8NOIDO
826 SNDMIX_RAMPFASTMONOVOL
827 END_FASTRAMPMIX_INTERFACE()
828
829 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitRampMix)
830 SNDMIX_BEGINSAMPLELOOP16
831 SNDMIX_GETMONOVOL16NOIDO
832 SNDMIX_RAMPFASTMONOVOL
833 END_FASTRAMPMIX_INTERFACE()
834
835 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitLinearRampMix)
836 SNDMIX_BEGINSAMPLELOOP8
837 SNDMIX_GETMONOVOL8LINEAR
838 SNDMIX_RAMPFASTMONOVOL
839 END_FASTRAMPMIX_INTERFACE()
840
841 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitLinearRampMix)
842 SNDMIX_BEGINSAMPLELOOP16
843 SNDMIX_GETMONOVOL16LINEAR
844 SNDMIX_RAMPFASTMONOVOL
845 END_FASTRAMPMIX_INTERFACE()
846
847 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitSplineRampMix)
848 SNDMIX_BEGINSAMPLELOOP8
849 SNDMIX_GETMONOVOL8SPLINE
850 SNDMIX_RAMPFASTMONOVOL
851 END_FASTRAMPMIX_INTERFACE()
852
853 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitSplineRampMix)
854 SNDMIX_BEGINSAMPLELOOP16
855 SNDMIX_GETMONOVOL16SPLINE
856 SNDMIX_RAMPFASTMONOVOL
857 END_FASTRAMPMIX_INTERFACE()
858
859 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix)
860 SNDMIX_BEGINSAMPLELOOP8
861 SNDMIX_GETMONOVOL8FIRFILTER
862 SNDMIX_RAMPFASTMONOVOL
863 END_FASTRAMPMIX_INTERFACE()
864
865 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix)
866 SNDMIX_BEGINSAMPLELOOP16
867 SNDMIX_GETMONOVOL16FIRFILTER
868 SNDMIX_RAMPFASTMONOVOL
869 END_FASTRAMPMIX_INTERFACE()
870
871
872 //////////////////////////////////////////////////////
873 // Stereo samples
874
875 BEGIN_MIX_INTERFACE(Stereo8BitMix)
876 SNDMIX_BEGINSAMPLELOOP8
877 SNDMIX_GETSTEREOVOL8NOIDO
878 SNDMIX_STORESTEREOVOL
879 END_MIX_INTERFACE()
880
881 BEGIN_MIX_INTERFACE(Stereo16BitMix)
882 SNDMIX_BEGINSAMPLELOOP16
883 SNDMIX_GETSTEREOVOL16NOIDO
884 SNDMIX_STORESTEREOVOL
885 END_MIX_INTERFACE()
886
887 BEGIN_MIX_INTERFACE(Stereo8BitLinearMix)
888 SNDMIX_BEGINSAMPLELOOP8
889 SNDMIX_GETSTEREOVOL8LINEAR
890 SNDMIX_STORESTEREOVOL
891 END_MIX_INTERFACE()
892
893 BEGIN_MIX_INTERFACE(Stereo16BitLinearMix)
894 SNDMIX_BEGINSAMPLELOOP16
895 SNDMIX_GETSTEREOVOL16LINEAR
896 SNDMIX_STORESTEREOVOL
897 END_MIX_INTERFACE()
898
899 BEGIN_MIX_INTERFACE(Stereo8BitSplineMix)
900 SNDMIX_BEGINSAMPLELOOP8
901 SNDMIX_GETSTEREOVOL8SPLINE
902 SNDMIX_STORESTEREOVOL
903 END_MIX_INTERFACE()
904
905 BEGIN_MIX_INTERFACE(Stereo16BitSplineMix)
906 SNDMIX_BEGINSAMPLELOOP16
907 SNDMIX_GETSTEREOVOL16SPLINE
908 SNDMIX_STORESTEREOVOL
909 END_MIX_INTERFACE()
910
911 BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix)
912 SNDMIX_BEGINSAMPLELOOP8
913 SNDMIX_GETSTEREOVOL8FIRFILTER
914 SNDMIX_STORESTEREOVOL
915 END_MIX_INTERFACE()
916
917 BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix)
918 SNDMIX_BEGINSAMPLELOOP16
919 SNDMIX_GETSTEREOVOL16FIRFILTER
920 SNDMIX_STORESTEREOVOL
921 END_MIX_INTERFACE()
922
923
924 // Volume Ramps
925 BEGIN_RAMPMIX_INTERFACE(Stereo8BitRampMix)
926 SNDMIX_BEGINSAMPLELOOP8
927 SNDMIX_GETSTEREOVOL8NOIDO
928 SNDMIX_RAMPSTEREOVOL
929 END_RAMPMIX_INTERFACE()
930
931 BEGIN_RAMPMIX_INTERFACE(Stereo16BitRampMix)
932 SNDMIX_BEGINSAMPLELOOP16
933 SNDMIX_GETSTEREOVOL16NOIDO
934 SNDMIX_RAMPSTEREOVOL
935 END_RAMPMIX_INTERFACE()
936
937 BEGIN_RAMPMIX_INTERFACE(Stereo8BitLinearRampMix)
938 SNDMIX_BEGINSAMPLELOOP8
939 SNDMIX_GETSTEREOVOL8LINEAR
940 SNDMIX_RAMPSTEREOVOL
941 END_RAMPMIX_INTERFACE()
942
943 BEGIN_RAMPMIX_INTERFACE(Stereo16BitLinearRampMix)
944 SNDMIX_BEGINSAMPLELOOP16
945 SNDMIX_GETSTEREOVOL16LINEAR
946 SNDMIX_RAMPSTEREOVOL
947 END_RAMPMIX_INTERFACE()
948
949 BEGIN_RAMPMIX_INTERFACE(Stereo8BitSplineRampMix)
950 SNDMIX_BEGINSAMPLELOOP8
951 SNDMIX_GETSTEREOVOL8SPLINE
952 SNDMIX_RAMPSTEREOVOL
953 END_RAMPMIX_INTERFACE()
954
955 BEGIN_RAMPMIX_INTERFACE(Stereo16BitSplineRampMix)
956 SNDMIX_BEGINSAMPLELOOP16
957 SNDMIX_GETSTEREOVOL16SPLINE
958 SNDMIX_RAMPSTEREOVOL
959 END_RAMPMIX_INTERFACE()
960
961 BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix)
962 SNDMIX_BEGINSAMPLELOOP8
963 SNDMIX_GETSTEREOVOL8FIRFILTER
964 SNDMIX_RAMPSTEREOVOL
965 END_RAMPMIX_INTERFACE()
966
967 BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix)
968 SNDMIX_BEGINSAMPLELOOP16
969 SNDMIX_GETSTEREOVOL16FIRFILTER
970 SNDMIX_RAMPSTEREOVOL
971 END_RAMPMIX_INTERFACE()
972
973
974
975 //////////////////////////////////////////////////////
976 // Resonant Filter Mix
977
978 #ifndef NO_FILTER
979
980 // Mono Filter Mix
981 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitMix)
982 SNDMIX_BEGINSAMPLELOOP8
983 SNDMIX_GETMONOVOL8NOIDO
984 SNDMIX_PROCESSFILTER
985 SNDMIX_STOREMONOVOL
986 END_MIX_FLT_INTERFACE()
987
988 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitMix)
989 SNDMIX_BEGINSAMPLELOOP16
990 SNDMIX_GETMONOVOL16NOIDO
991 SNDMIX_PROCESSFILTER
992 SNDMIX_STOREMONOVOL
993 END_MIX_FLT_INTERFACE()
994
995 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitLinearMix)
996 SNDMIX_BEGINSAMPLELOOP8
997 SNDMIX_GETMONOVOL8LINEAR
998 SNDMIX_PROCESSFILTER
999 SNDMIX_STOREMONOVOL
1000 END_MIX_FLT_INTERFACE()
1001
1002 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitLinearMix)
1003 SNDMIX_BEGINSAMPLELOOP16
1004 SNDMIX_GETMONOVOL16LINEAR
1005 SNDMIX_PROCESSFILTER
1006 SNDMIX_STOREMONOVOL
1007 END_MIX_FLT_INTERFACE()
1008
1009 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitSplineMix)
1010 SNDMIX_BEGINSAMPLELOOP8
1011 SNDMIX_GETMONOVOL8SPLINE
1012 SNDMIX_PROCESSFILTER
1013 SNDMIX_STOREMONOVOL
1014 END_MIX_FLT_INTERFACE()
1015
1016 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitSplineMix)
1017 SNDMIX_BEGINSAMPLELOOP16
1018 SNDMIX_GETMONOVOL16SPLINE
1019 SNDMIX_PROCESSFILTER
1020 SNDMIX_STOREMONOVOL
1021 END_MIX_FLT_INTERFACE()
1022
1023 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix)
1024 SNDMIX_BEGINSAMPLELOOP8
1025 SNDMIX_GETMONOVOL8FIRFILTER
1026 SNDMIX_PROCESSFILTER
1027 SNDMIX_STOREMONOVOL
1028 END_MIX_FLT_INTERFACE()
1029
1030 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix)
1031 SNDMIX_BEGINSAMPLELOOP16
1032 SNDMIX_GETMONOVOL16FIRFILTER
1033 SNDMIX_PROCESSFILTER
1034 SNDMIX_STOREMONOVOL
1035 END_MIX_FLT_INTERFACE()
1036
1037 // Filter + Ramp
1038 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitRampMix)
1039 SNDMIX_BEGINSAMPLELOOP8
1040 SNDMIX_GETMONOVOL8NOIDO
1041 SNDMIX_PROCESSFILTER
1042 SNDMIX_RAMPMONOVOL
1043 END_RAMPMIX_FLT_INTERFACE()
1044
1045 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitRampMix)
1046 SNDMIX_BEGINSAMPLELOOP16
1047 SNDMIX_GETMONOVOL16NOIDO
1048 SNDMIX_PROCESSFILTER
1049 SNDMIX_RAMPMONOVOL
1050 END_RAMPMIX_FLT_INTERFACE()
1051
1052 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitLinearRampMix)
1053 SNDMIX_BEGINSAMPLELOOP8
1054 SNDMIX_GETMONOVOL8LINEAR
1055 SNDMIX_PROCESSFILTER
1056 SNDMIX_RAMPMONOVOL
1057 END_RAMPMIX_FLT_INTERFACE()
1058
1059 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitLinearRampMix)
1060 SNDMIX_BEGINSAMPLELOOP16
1061 SNDMIX_GETMONOVOL16LINEAR
1062 SNDMIX_PROCESSFILTER
1063 SNDMIX_RAMPMONOVOL
1064 END_RAMPMIX_FLT_INTERFACE()
1065
1066 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitSplineRampMix)
1067 SNDMIX_BEGINSAMPLELOOP8
1068 SNDMIX_GETMONOVOL8SPLINE
1069 SNDMIX_PROCESSFILTER
1070 SNDMIX_RAMPMONOVOL
1071 END_RAMPMIX_FLT_INTERFACE()
1072
1073 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitSplineRampMix)
1074 SNDMIX_BEGINSAMPLELOOP16
1075 SNDMIX_GETMONOVOL16SPLINE
1076 SNDMIX_PROCESSFILTER
1077 SNDMIX_RAMPMONOVOL
1078 END_RAMPMIX_FLT_INTERFACE()
1079
1080 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix)
1081 SNDMIX_BEGINSAMPLELOOP8
1082 SNDMIX_GETMONOVOL8FIRFILTER
1083 SNDMIX_PROCESSFILTER
1084 SNDMIX_RAMPMONOVOL
1085 END_RAMPMIX_FLT_INTERFACE()
1086
1087 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix)
1088 SNDMIX_BEGINSAMPLELOOP16
1089 SNDMIX_GETMONOVOL16FIRFILTER
1090 SNDMIX_PROCESSFILTER
1091 SNDMIX_RAMPMONOVOL
1092 END_RAMPMIX_FLT_INTERFACE()
1093
1094
1095 // Stereo Filter Mix
1096 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitMix)
1097 SNDMIX_BEGINSAMPLELOOP8
1098 SNDMIX_GETSTEREOVOL8NOIDO
1099 SNDMIX_PROCESSSTEREOFILTER
1100 SNDMIX_STORESTEREOVOL
1101 END_MIX_STFLT_INTERFACE()
1102
1103 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitMix)
1104 SNDMIX_BEGINSAMPLELOOP16
1105 SNDMIX_GETSTEREOVOL16NOIDO
1106 SNDMIX_PROCESSSTEREOFILTER
1107 SNDMIX_STORESTEREOVOL
1108 END_MIX_STFLT_INTERFACE()
1109
1110 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitLinearMix)
1111 SNDMIX_BEGINSAMPLELOOP8
1112 SNDMIX_GETSTEREOVOL8LINEAR
1113 SNDMIX_PROCESSSTEREOFILTER
1114 SNDMIX_STORESTEREOVOL
1115 END_MIX_STFLT_INTERFACE()
1116
1117 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitLinearMix)
1118 SNDMIX_BEGINSAMPLELOOP16
1119 SNDMIX_GETSTEREOVOL16LINEAR
1120 SNDMIX_PROCESSSTEREOFILTER
1121 SNDMIX_STORESTEREOVOL
1122 END_MIX_STFLT_INTERFACE()
1123
1124 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitSplineMix)
1125 SNDMIX_BEGINSAMPLELOOP8
1126 SNDMIX_GETSTEREOVOL8SPLINE
1127 SNDMIX_PROCESSSTEREOFILTER
1128 SNDMIX_STORESTEREOVOL
1129 END_MIX_STFLT_INTERFACE()
1130
1131 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitSplineMix)
1132 SNDMIX_BEGINSAMPLELOOP16
1133 SNDMIX_GETSTEREOVOL16SPLINE
1134 SNDMIX_PROCESSSTEREOFILTER
1135 SNDMIX_STORESTEREOVOL
1136 END_MIX_STFLT_INTERFACE()
1137
1138 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix)
1139 SNDMIX_BEGINSAMPLELOOP8
1140 SNDMIX_GETSTEREOVOL8FIRFILTER
1141 SNDMIX_PROCESSSTEREOFILTER
1142 SNDMIX_STORESTEREOVOL
1143 END_MIX_STFLT_INTERFACE()
1144
1145 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix)
1146 SNDMIX_BEGINSAMPLELOOP16
1147 SNDMIX_GETSTEREOVOL16FIRFILTER
1148 SNDMIX_PROCESSSTEREOFILTER
1149 SNDMIX_STORESTEREOVOL
1150 END_MIX_STFLT_INTERFACE()
1151
1152 // Stereo Filter + Ramp
1153 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitRampMix)
1154 SNDMIX_BEGINSAMPLELOOP8
1155 SNDMIX_GETSTEREOVOL8NOIDO
1156 SNDMIX_PROCESSSTEREOFILTER
1157 SNDMIX_RAMPSTEREOVOL
1158 END_RAMPMIX_STFLT_INTERFACE()
1159
1160 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitRampMix)
1161 SNDMIX_BEGINSAMPLELOOP16
1162 SNDMIX_GETSTEREOVOL16NOIDO
1163 SNDMIX_PROCESSSTEREOFILTER
1164 SNDMIX_RAMPSTEREOVOL
1165 END_RAMPMIX_STFLT_INTERFACE()
1166
1167 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitLinearRampMix)
1168 SNDMIX_BEGINSAMPLELOOP8
1169 SNDMIX_GETSTEREOVOL8LINEAR
1170 SNDMIX_PROCESSSTEREOFILTER
1171 SNDMIX_RAMPSTEREOVOL
1172 END_RAMPMIX_STFLT_INTERFACE()
1173
1174 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitLinearRampMix)
1175 SNDMIX_BEGINSAMPLELOOP16
1176 SNDMIX_GETSTEREOVOL16LINEAR
1177 SNDMIX_PROCESSSTEREOFILTER
1178 SNDMIX_RAMPSTEREOVOL
1179 END_RAMPMIX_STFLT_INTERFACE()
1180
1181 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitSplineRampMix)
1182 SNDMIX_BEGINSAMPLELOOP8
1183 SNDMIX_GETSTEREOVOL8SPLINE
1184 SNDMIX_PROCESSSTEREOFILTER
1185 SNDMIX_RAMPSTEREOVOL
1186 END_RAMPMIX_STFLT_INTERFACE()
1187
1188 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitSplineRampMix)
1189 SNDMIX_BEGINSAMPLELOOP16
1190 SNDMIX_GETSTEREOVOL16SPLINE
1191 SNDMIX_PROCESSSTEREOFILTER
1192 SNDMIX_RAMPSTEREOVOL
1193 END_RAMPMIX_STFLT_INTERFACE()
1194
1195 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix)
1196 SNDMIX_BEGINSAMPLELOOP8
1197 SNDMIX_GETSTEREOVOL8FIRFILTER
1198 SNDMIX_PROCESSSTEREOFILTER
1199 SNDMIX_RAMPSTEREOVOL
1200 END_RAMPMIX_STFLT_INTERFACE()
1201
1202 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix)
1203 SNDMIX_BEGINSAMPLELOOP16
1204 SNDMIX_GETSTEREOVOL16FIRFILTER
1205 SNDMIX_PROCESSSTEREOFILTER
1206 SNDMIX_RAMPSTEREOVOL
1207 END_RAMPMIX_STFLT_INTERFACE()
1208
1209
1210 #else
1211 // Mono
1212 #define FilterMono8BitMix Mono8BitMix
1213 #define FilterMono16BitMix Mono16BitMix
1214 #define FilterMono8BitLinearMix Mono8BitLinearMix
1215 #define FilterMono16BitLinearMix Mono16BitLinearMix
1216 #define FilterMono8BitSplineMix Mono8BitSplineMix
1217 #define FilterMono16BitSplineMix Mono16BitSplineMix
1218 #define FilterMono8BitFirFilterMix Mono8BitFirFilterMix
1219 #define FilterMono16BitFirFilterMix Mono16BitFirFilterMix
1220 #define FilterMono8BitRampMix Mono8BitRampMix
1221 #define FilterMono16BitRampMix Mono16BitRampMix
1222 #define FilterMono8BitLinearRampMix Mono8BitLinearRampMix
1223 #define FilterMono16BitLinearRampMix Mono16BitLinearRampMix
1224 #define FilterMono8BitSplineRampMix Mono8BitSplineRampMix
1225 #define FilterMono16BitSplineRampMix Mono16BitSplineRampMix
1226 #define FilterMono8BitFirFilterRampMix Mono8BitFirFilterRampMix
1227 #define FilterMono16BitFirFilterRampMix Mono16BitFirFilterRampMix
1228 // Stereo
1229 #define FilterStereo8BitMix Stereo8BitMix
1230 #define FilterStereo16BitMix Stereo16BitMix
1231 #define FilterStereo8BitLinearMix Stereo8BitLinearMix
1232 #define FilterStereo16BitLinearMix Stereo16BitLinearMix
1233 #define FilterStereo8BitSplineMix Stereo8BitSplineMix
1234 #define FilterStereo16BitSplineMix Stereo16BitSplineMix
1235 #define FilterStereo8BitFirFilterMix Stereo8BitFirFilterMix
1236 #define FilterStereo16BitFirFilterMix Stereo16BitFirFilterMix
1237 #define FilterStereo8BitRampMix Stereo8BitRampMix
1238 #define FilterStereo16BitRampMix Stereo16BitRampMix
1239 #define FilterStereo8BitLinearRampMix Stereo8BitLinearRampMix
1240 #define FilterStereo16BitLinearRampMix Stereo16BitLinearRampMix
1241 #define FilterStereo8BitSplineRampMix Stereo8BitSplineRampMix
1242 #define FilterStereo16BitSplineRampMix Stereo16BitSplineRampMix
1243 #define FilterStereo8BitFirFilterRampMix Stereo8BitFirFilterRampMix
1244 #define FilterStereo16BitFirFilterRampMix Stereo16BitFirFilterRampMix
1245
1246 #endif
1247
1248 /////////////////////////////////////////////////////////////////////////////////////
1249 //
1250 // Mix function tables
1251 //
1252 //
1253 // Index is as follow:
1254 // [b1-b0] format (8-bit-mono, 16-bit-mono, 8-bit-stereo, 16-bit-stereo)
1255 // [b2] ramp
1256 // [b3] filter
1257 // [b5-b4] src type
1258 //
1259
1260 #define MIXNDX_16BIT 0x01
1261 #define MIXNDX_STEREO 0x02
1262 #define MIXNDX_RAMP 0x04
1263 #define MIXNDX_FILTER 0x08
1264 #define MIXNDX_LINEARSRC 0x10
1265 #define MIXNDX_SPLINESRC 0x20
1266 #define MIXNDX_FIRSRC 0x30
1267
1268 const LPMIXINTERFACE gpMixFunctionTable[2*2*16] =
1269 {
1270 // No SRC
1271 Mono8BitMix, Mono16BitMix, Stereo8BitMix, Stereo16BitMix,
1272 Mono8BitRampMix, Mono16BitRampMix, Stereo8BitRampMix,
1273 Stereo16BitRampMix,
1274 // No SRC, Filter
1275 FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix,
1276 FilterStereo16BitMix, FilterMono8BitRampMix, FilterMono16BitRampMix,
1277 FilterStereo8BitRampMix, FilterStereo16BitRampMix,
1278 // Linear SRC
1279 Mono8BitLinearMix, Mono16BitLinearMix, Stereo8BitLinearMix,
1280 Stereo16BitLinearMix, Mono8BitLinearRampMix, Mono16BitLinearRampMix,
1281 Stereo8BitLinearRampMix,Stereo16BitLinearRampMix,
1282 // Linear SRC, Filter
1283 FilterMono8BitLinearMix, FilterMono16BitLinearMix,
1284 FilterStereo8BitLinearMix, FilterStereo16BitLinearMix,
1285 FilterMono8BitLinearRampMix, FilterMono16BitLinearRampMix,
1286 FilterStereo8BitLinearRampMix, FilterStereo16BitLinearRampMix,
1287
1288 // FirFilter SRC
1289 Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix,
1290 Stereo16BitSplineMix, Mono8BitSplineRampMix, Mono16BitSplineRampMix,
1291 Stereo8BitSplineRampMix,Stereo16BitSplineRampMix,
1292 // Spline SRC, Filter
1293 FilterMono8BitSplineMix, FilterMono16BitSplineMix,
1294 FilterStereo8BitSplineMix, FilterStereo16BitSplineMix,
1295 FilterMono8BitSplineRampMix, FilterMono16BitSplineRampMix,
1296 FilterStereo8BitSplineRampMix, FilterStereo16BitSplineRampMix,
1297
1298 // FirFilter SRC
1299 Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix,
1300 Stereo16BitFirFilterMix, Mono8BitFirFilterRampMix,
1301 Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix,
1302 Stereo16BitFirFilterRampMix,
1303 // FirFilter SRC, Filter
1304 FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix,
1305 FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix,
1306 FilterMono8BitFirFilterRampMix, FilterMono16BitFirFilterRampMix,
1307 FilterStereo8BitFirFilterRampMix, FilterStereo16BitFirFilterRampMix
1308 };
1309
1310 const LPMIXINTERFACE gpFastMixFunctionTable[2*2*16] =
1311 {
1312 // No SRC
1313 FastMono8BitMix, FastMono16BitMix, Stereo8BitMix, Stereo16BitMix,
1314 FastMono8BitRampMix, FastMono16BitRampMix, Stereo8BitRampMix,
1315 Stereo16BitRampMix,
1316 // No SRC, Filter
1317 FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix,
1318 FilterStereo16BitMix, FilterMono8BitRampMix, FilterMono16BitRampMix,
1319 FilterStereo8BitRampMix, FilterStereo16BitRampMix,
1320 // Linear SRC
1321 FastMono8BitLinearMix, FastMono16BitLinearMix, Stereo8BitLinearMix,
1322 Stereo16BitLinearMix, FastMono8BitLinearRampMix,
1323 FastMono16BitLinearRampMix, Stereo8BitLinearRampMix,
1324 Stereo16BitLinearRampMix,
1325 // Linear SRC, Filter
1326 FilterMono8BitLinearMix, FilterMono16BitLinearMix,
1327 FilterStereo8BitLinearMix, FilterStereo16BitLinearMix,
1328 FilterMono8BitLinearRampMix, FilterMono16BitLinearRampMix,
1329 FilterStereo8BitLinearRampMix, FilterStereo16BitLinearRampMix,
1330
1331 // Spline SRC
1332 Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix,
1333 Stereo16BitSplineMix, Mono8BitSplineRampMix, Mono16BitSplineRampMix,
1334 Stereo8BitSplineRampMix, Stereo16BitSplineRampMix,
1335 // Spline SRC, Filter
1336 FilterMono8BitSplineMix, FilterMono16BitSplineMix,
1337 FilterStereo8BitSplineMix, FilterStereo16BitSplineMix,
1338 FilterMono8BitSplineRampMix, FilterMono16BitSplineRampMix,
1339 FilterStereo8BitSplineRampMix, FilterStereo16BitSplineRampMix,
1340
1341 // FirFilter SRC
1342 Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix,
1343 Stereo16BitFirFilterMix, Mono8BitFirFilterRampMix,
1344 Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix,
1345 Stereo16BitFirFilterRampMix,
1346 // FirFilter SRC, Filter
1347 FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix,
1348 FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix,
1349 FilterMono8BitFirFilterRampMix, FilterMono16BitFirFilterRampMix,
1350 FilterStereo8BitFirFilterRampMix, FilterStereo16BitFirFilterRampMix,
1351 };
1352
1353
1354 /////////////////////////////////////////////////////////////////////////
1355
1356 static LONG MPPFASTCALL GetSampleCount(MODCHANNEL *pChn, LONG nSamples)
1357 //---------------------------------------------------------------------
1358 {
1359 LONG nLoopStart = (pChn->dwFlags & CHN_LOOP) ? pChn->nLoopStart : 0;
1360 LONG nInc = pChn->nInc;
1361
1362 if ((nSamples <= 0) || (!nInc) || (!pChn->nLength)) return 0;
1363 // Under zero ?
1364 if ((LONG)pChn->nPos < nLoopStart)
1365 {
1366 if (nInc < 0)
1367 {
1368 // Invert loop for bidi loops
1369 LONG nDelta = ((nLoopStart - pChn->nPos) << 16) - (pChn->nPosLo & 0xffff);
1370 pChn->nPos = nLoopStart | (nDelta>>16);
1371 pChn->nPosLo = nDelta & 0xffff;
1372 if (((LONG)pChn->nPos < nLoopStart) || (pChn->nPos >= (nLoopStart+pChn->nLength)/2))
1373 {
1374 pChn->nPos = nLoopStart; pChn->nPosLo = 0;
1375 }
1376 nInc = -nInc;
1377 pChn->nInc = nInc;
1378 pChn->dwFlags &= ~(CHN_PINGPONGFLAG); // go forward
1379 if ((!(pChn->dwFlags & CHN_LOOP)) || (pChn->nPos >= pChn->nLength))
1380 {
1381 pChn->nPos = pChn->nLength;
1382 pChn->nPosLo = 0;
1383 return 0;
1384 }
1385 } else
1386 {
1387 // We probably didn't hit the loop end yet (first loop), so we do nothing
1388 if ((LONG)pChn->nPos < 0) pChn->nPos = 0;
1389 }
1390 } else
1391 // Past the end
1392 if (pChn->nPos >= pChn->nLength)
1393 {
1394 if (!(pChn->dwFlags & CHN_LOOP)) return 0; // not looping -> stop this channel
1395 if (pChn->dwFlags & CHN_PINGPONGLOOP)
1396 {
1397 // Invert loop
1398 if (nInc > 0)
1399 {
1400 nInc = -nInc;
1401 pChn->nInc = nInc;
1402 }
1403 pChn->dwFlags |= CHN_PINGPONGFLAG;
1404 // adjust loop position
1405 LONG nDeltaHi = (pChn->nPos - pChn->nLength);
1406 LONG nDeltaLo = 0x10000 - (pChn->nPosLo & 0xffff);
1407 pChn->nPos = pChn->nLength - nDeltaHi - (nDeltaLo>>16);
1408 pChn->nPosLo = nDeltaLo & 0xffff;
1409 if ((pChn->nPos <= pChn->nLoopStart) || (pChn->nPos >= pChn->nLength)) pChn->nPos = pChn->nLength-1;
1410 } else
1411 {
1412 if (nInc < 0) // This is a bug
1413 {
1414 nInc = -nInc;
1415 pChn->nInc = nInc;
1416 }
1417 // Restart at loop start
1418 pChn->nPos += nLoopStart - pChn->nLength;
1419 if ((LONG)pChn->nPos < nLoopStart) pChn->nPos = pChn->nLoopStart;
1420 }
1421 }
1422 LONG nPos = pChn->nPos;
1423 // too big increment, and/or too small loop length
1424 if (nPos < nLoopStart)
1425 {
1426 if ((nPos < 0) || (nInc < 0)) return 0;
1427 }
1428 if ((nPos < 0) || (nPos >= (LONG)pChn->nLength)) return 0;
1429 LONG nPosLo = (USHORT)pChn->nPosLo, nSmpCount = nSamples;
1430 if (nInc < 0)
1431 {
1432 LONG nInv = -nInc;
1433 LONG maxsamples = 16384 / ((nInv>>16)+1);
1434 if (maxsamples < 2) maxsamples = 2;
1435 if (nSamples > maxsamples) nSamples = maxsamples;
1436 LONG nDeltaHi = (nInv>>16) * (nSamples - 1);
1437 LONG nDeltaLo = (nInv&0xffff) * (nSamples - 1);
1438 LONG nPosDest = nPos - nDeltaHi + ((nPosLo - nDeltaLo) >> 16);
1439 if (nPosDest < nLoopStart)
1440 {
1441 nSmpCount = (ULONG)(((((LONGLONG)nPos - nLoopStart) << 16) + nPosLo - 1) / nInv) + 1;
1442 }
1443 } else
1444 {
1445 LONG maxsamples = 16384 / ((nInc>>16)+1);
1446 if (maxsamples < 2) maxsamples = 2;
1447 if (nSamples > maxsamples) nSamples = maxsamples;
1448 LONG nDeltaHi = (nInc>>16) * (nSamples - 1);
1449 LONG nDeltaLo = (nInc&0xffff) * (nSamples - 1);
1450 LONG nPosDest = nPos + nDeltaHi + ((nPosLo + nDeltaLo)>>16);
1451 if (nPosDest >= (LONG)pChn->nLength)
1452 {
1453 nSmpCount = (ULONG)(((((LONGLONG)pChn->nLength - nPos) << 16) - nPosLo - 1) / nInc) + 1;
1454 }
1455 }
1456 if (nSmpCount <= 1) return 1;
1457 if (nSmpCount > nSamples) return nSamples;
1458 return nSmpCount;
1459 }
1460
1461
1462 UINT CSoundFile::CreateStereoMix(int count)
1463 //-----------------------------------------
1464 {
1465 LPLONG pOfsL, pOfsR;
1466 DWORD nchused, nchmixed;
1467
1468 if (!count) return 0;
1469 #ifndef MODPLUG_FASTSOUNDLIB
1470 if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2);
1471 #endif
1472 nchused = nchmixed = 0;
1473 for (UINT nChn=0; nChn<m_nMixChannels; nChn++)
1474 {
1475 const LPMIXINTERFACE *pMixFuncTable;
1476 MODCHANNEL * const pChannel = &Chn[ChnMix[nChn]];
1477 UINT nFlags, nMasterCh;
1478 LONG nSmpCount;
1479 int nsamples;
1480 int *pbuffer;
1481
1482 if (!pChannel->pCurrentSample) continue;
1483 nMasterCh = (ChnMix[nChn] < m_nChannels) ? ChnMix[nChn]+1 : pChannel->nMasterChn;
1484 pOfsR = &gnDryROfsVol;
1485 pOfsL = &gnDryLOfsVol;
1486 nFlags = 0;
1487 if (pChannel->dwFlags & CHN_16BIT) nFlags |= MIXNDX_16BIT;
1488 if (pChannel->dwFlags & CHN_STEREO) nFlags |= MIXNDX_STEREO;
1489 #ifndef NO_FILTER
1490 if (pChannel->dwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER;
1491 #endif
1492 if (!(pChannel->dwFlags & CHN_NOIDO))
1493 {
1494 // use hq-fir mixer?
1495 if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) )
1496 nFlags += MIXNDX_FIRSRC;
1497 else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER )
1498 nFlags += MIXNDX_SPLINESRC;
1499 else
1500 nFlags += MIXNDX_LINEARSRC; // use
1501 }
1502 if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol)
1503 && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp)))
1504 {
1505 pMixFuncTable = gpFastMixFunctionTable;
1506 } else
1507 {
1508 pMixFuncTable = gpMixFunctionTable;
1509 }
1510 nsamples = count;
1511 #ifndef MODPLUG_NO_REVERB
1512 pbuffer = (gdwSoundSetup & SNDMIX_REVERB) ? MixReverbBuffer : MixSoundBuffer;
1513 if (pChannel->dwFlags & CHN_NOREVERB) pbuffer = MixSoundBuffer;
1514 if (pChannel->dwFlags & CHN_REVERB) pbuffer = MixReverbBuffer;
1515 if (pbuffer == MixReverbBuffer)
1516 {
1517 if (!gnReverbSend) memset(MixReverbBuffer, 0, count * 8);
1518 gnReverbSend += count;
1519 }
1520 #else
1521 pbuffer = MixSoundBuffer;
1522 #endif
1523 nchused++;
1524 ////////////////////////////////////////////////////
1525 SampleLooping:
1526 UINT nrampsamples = nsamples;
1527 if (pChannel->nRampLength > 0)
1528 {
1529 if ((LONG)nrampsamples > pChannel->nRampLength) nrampsamples = pChannel->nRampLength;
1530 }
1531 if ((nSmpCount = GetSampleCount(pChannel, nrampsamples)) <= 0)
1532 {
1533 // Stopping the channel
1534 pChannel->pCurrentSample = NULL;
1535 pChannel->nLength = 0;
1536 pChannel->nPos = 0;
1537 pChannel->nPosLo = 0;
1538 pChannel->nRampLength = 0;
1539 X86_EndChannelOfs(pChannel, pbuffer, nsamples);
1540 *pOfsR += pChannel->nROfs;
1541 *pOfsL += pChannel->nLOfs;
1542 pChannel->nROfs = pChannel->nLOfs = 0;
1543 pChannel->dwFlags &= ~CHN_PINGPONGFLAG;
1544 continue;
1545 }
1546 // Should we mix this channel ?
1547 UINT naddmix;
1548 if (((nchmixed >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)))
1549 || ((!pChannel->nRampLength) && (!(pChannel->nLeftVol|pChannel->nRightVol))))
1550 {
1551 LONG delta = (pChannel->nInc * (LONG)nSmpCount) + (LONG)pChannel->nPosLo;
1552 pChannel->nPosLo = delta & 0xFFFF;
1553 pChannel->nPos += (delta >> 16);
1554 pChannel->nROfs = pChannel->nLOfs = 0;
1555 pbuffer += nSmpCount*2;
1556 naddmix = 0;
1557 } else
1558 // Do mixing
1559 {
1560 // Choose function for mixing
1561 LPMIXINTERFACE pMixFunc;
1562 pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags];
1563 int *pbufmax = pbuffer + (nSmpCount*2);
1564 pChannel->nROfs = - *(pbufmax-2);
1565 pChannel->nLOfs = - *(pbufmax-1);
1566 pMixFunc(pChannel, pbuffer, pbufmax);
1567 pChannel->nROfs += *(pbufmax-2);
1568 pChannel->nLOfs += *(pbufmax-1);
1569 pbuffer = pbufmax;
1570 naddmix = 1;
1571
1572 }
1573 nsamples -= nSmpCount;
1574 if (pChannel->nRampLength)
1575 {
1576 pChannel->nRampLength -= nSmpCount;
1577 if (pChannel->nRampLength <= 0)
1578 {
1579 pChannel->nRampLength = 0;
1580 pChannel->nRightVol = pChannel->nNewRightVol;
1581 pChannel->nLeftVol = pChannel->nNewLeftVol;
1582 pChannel->nRightRamp = pChannel->nLeftRamp = 0;
1583 if ((pChannel->dwFlags & CHN_NOTEFADE) && (!(pChannel->nFadeOutVol)))
1584 {
1585 pChannel->nLength = 0;
1586 pChannel->pCurrentSample = NULL;
1587 }
1588 }
1589 }
1590 if (nsamples > 0) goto SampleLooping;
1591 nchmixed += naddmix;
1592 }
1593 return nchused;
1594 }
1595
1596
1597 #ifdef MSC_VER
1598 #pragma warning (disable:4100)
1599 #endif
1600
1601 // Clip and convert to 8 bit
1602 #ifdef MSC_VER
1603 __declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1604 //----------------------------------------------------------------------------------------------------------------------------
1605 {
1606 _asm {
1607 push ebx
1608 push esi
1609 push edi
1610 mov ebx, 16[esp] // ebx = 8-bit buffer
1611 mov esi, 20[esp] // esi = pBuffer
1612 mov edi, 24[esp] // edi = lSampleCount
1613 mov eax, 28[esp]
1614 mov ecx, dword ptr [eax] // ecx = clipmin
1615 mov eax, 32[esp]
1616 mov edx, dword ptr [eax] // edx = clipmax
1617 cliploop:
1618 mov eax, dword ptr [esi]
1619 inc ebx
1620 cdq
1621 and edx, (1 << (24-MIXING_ATTENUATION)) - 1
1622 add eax, edx
1623 cmp eax, MIXING_CLIPMIN
1624 jl cliplow
1625 cmp eax, MIXING_CLIPMAX
1626 jg cliphigh
1627 cmp eax, ecx
1628 jl updatemin
1629 cmp eax, edx
1630 jg updatemax
1631 cliprecover:
1632 add esi, 4
1633 sar eax, 24-MIXING_ATTENUATION
1634 xor eax, 0x80
1635 dec edi
1636 mov byte ptr [ebx-1], al
1637 jnz cliploop
1638 mov eax, 28[esp]
1639 mov dword ptr [eax], ecx
1640 mov eax, 32[esp]
1641 mov dword ptr [eax], edx
1642 mov eax, 24[esp]
1643 pop edi
1644 pop esi
1645 pop ebx
1646 ret
1647 updatemin:
1648 mov ecx, eax
1649 jmp cliprecover
1650 updatemax:
1651 mov edx, eax
1652 jmp cliprecover
1653 cliplow:
1654 mov ecx, MIXING_CLIPMIN
1655 mov edx, MIXING_CLIPMAX
1656 mov eax, MIXING_CLIPMIN
1657 jmp cliprecover
1658 cliphigh:
1659 mov ecx, MIXING_CLIPMIN
1660 mov edx, MIXING_CLIPMAX
1661 mov eax, MIXING_CLIPMAX
1662 jmp cliprecover
1663 }
1664 }
1665 #else //MSC_VER
1666 //---GCCFIX: Asm replaced with C function
1667 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
1668 DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1669 {
1670 int vumin = *lpMin, vumax = *lpMax;
1671 unsigned char *p = (unsigned char *)lp8;
1672 for (UINT i=0; i<lSampleCount; i++)
1673 {
1674 int n = pBuffer[i];
1675 if (n < MIXING_CLIPMIN)
1676 n = MIXING_CLIPMIN;
1677 else if (n > MIXING_CLIPMAX)
1678 n = MIXING_CLIPMAX;
1679 if (n < vumin)
1680 vumin = n;
1681 else if (n > vumax)
1682 vumax = n;
1683 p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80; // 8-bit unsigned
1684 }
1685 *lpMin = vumin;
1686 *lpMax = vumax;
1687 return lSampleCount;
1688 }
1689 #endif //MSC_VER, else
1690
1691
1692 #ifdef MSC_VER
1693 // Clip and convert to 16 bit
1694 __declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1695 //-----------------------------------------------------------------------------------------------------------------------------
1696 {
1697 _asm {
1698 push ebx
1699 push esi
1700 push edi
1701 mov ebx, 16[esp] // ebx = 16-bit buffer
1702 mov eax, 28[esp]
1703 mov esi, 20[esp] // esi = pBuffer
1704 mov ecx, dword ptr [eax] // ecx = clipmin
1705 mov edi, 24[esp] // edi = lSampleCount
1706 mov eax, 32[esp]
1707 push ebp
1708 mov ebp, dword ptr [eax] // edx = clipmax
1709 cliploop:
1710 mov eax, dword ptr [esi]
1711 add ebx, 2
1712 cdq
1713 and edx, (1 << (16-MIXING_ATTENUATION)) - 1
1714 add esi, 4
1715 add eax, edx
1716 cmp eax, MIXING_CLIPMIN
1717 jl cliplow
1718 cmp eax, MIXING_CLIPMAX
1719 jg cliphigh
1720 cmp eax, ecx
1721 jl updatemin
1722 cmp eax, ebp
1723 jg updatemax
1724 cliprecover:
1725 sar eax, 16-MIXING_ATTENUATION
1726 dec edi
1727 mov word ptr [ebx-2], ax
1728 jnz cliploop
1729 mov edx, ebp
1730 pop ebp
1731 mov eax, 28[esp]
1732 mov dword ptr [eax], ecx
1733 mov eax, 32[esp]
1734 mov dword ptr [eax], edx
1735 mov eax, 24[esp]
1736 pop edi
1737 shl eax, 1
1738 pop esi
1739 pop ebx
1740 ret
1741 updatemin:
1742 mov ecx, eax
1743 jmp cliprecover
1744 updatemax:
1745 mov ebp, eax
1746 jmp cliprecover
1747 cliplow:
1748 mov ecx, MIXING_CLIPMIN
1749 mov ebp, MIXING_CLIPMAX
1750 mov eax, MIXING_CLIPMIN
1751 jmp cliprecover
1752 cliphigh:
1753 mov ecx, MIXING_CLIPMIN
1754 mov ebp, MIXING_CLIPMAX
1755 mov eax, MIXING_CLIPMAX
1756 jmp cliprecover
1757 }
1758 }
1759 #else //MSC_VER
1760 //---GCCFIX: Asm replaced with C function
1761 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
1762 DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1763 {
1764 int vumin = *lpMin, vumax = *lpMax;
1765 signed short *p = (signed short *)lp16;
1766 for (UINT i=0; i<lSampleCount; i++)
1767 {
1768 int n = pBuffer[i];
1769 if (n < MIXING_CLIPMIN)
1770 n = MIXING_CLIPMIN;
1771 else if (n > MIXING_CLIPMAX)
1772 n = MIXING_CLIPMAX;
1773 if (n < vumin)
1774 vumin = n;
1775 else if (n > vumax)
1776 vumax = n;
1777 p[i] = n >> (16-MIXING_ATTENUATION); // 16-bit signed
1778 }
1779 *lpMin = vumin;
1780 *lpMax = vumax;
1781 return lSampleCount * 2;
1782 }
1783 #endif //MSC_VER, else
1784
1785 #ifdef MSC_VER
1786 // Clip and convert to 24 bit
1787 __declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1788 //-----------------------------------------------------------------------------------------------------------------------------
1789 {
1790 _asm {
1791 push ebx
1792 push esi
1793 push edi
1794 mov ebx, 16[esp] // ebx = 8-bit buffer
1795 mov esi, 20[esp] // esi = pBuffer
1796 mov edi, 24[esp] // edi = lSampleCount
1797 mov eax, 28[esp]
1798 mov ecx, dword ptr [eax] // ecx = clipmin
1799 mov eax, 32[esp]
1800 push ebp
1801 mov edx, dword ptr [eax] // edx = clipmax
1802 cliploop:
1803 mov eax, dword ptr [esi]
1804 mov ebp, eax
1805 sar ebp, 31
1806 and ebp, (1 << (8-MIXING_ATTENUATION)) - 1
1807 add eax, ebp
1808 cmp eax, MIXING_CLIPMIN
1809 jl cliplow
1810 cmp eax, MIXING_CLIPMAX
1811 jg cliphigh
1812 cmp eax, ecx
1813 jl updatemin
1814 cmp eax, edx
1815 jg updatemax
1816 cliprecover:
1817 add ebx, 3
1818 sar eax, 8-MIXING_ATTENUATION
1819 add esi, 4
1820 mov word ptr [ebx-3], ax
1821 shr eax, 16
1822 dec edi
1823 mov byte ptr [ebx-1], al
1824 jnz cliploop
1825 pop ebp
1826 mov eax, 28[esp]
1827 mov dword ptr [eax], ecx
1828 mov eax, 32[esp]
1829 mov dword ptr [eax], edx
1830 mov edx, 24[esp]
1831 mov eax, edx
1832 pop edi
1833 shl eax, 1
1834 pop esi
1835 add eax, edx
1836 pop ebx
1837 ret
1838 updatemin:
1839 mov ecx, eax
1840 jmp cliprecover
1841 updatemax:
1842 mov edx, eax
1843 jmp cliprecover
1844 cliplow:
1845 mov ecx, MIXING_CLIPMIN
1846 mov edx, MIXING_CLIPMAX
1847 mov eax, MIXING_CLIPMIN
1848 jmp cliprecover
1849 cliphigh:
1850 mov ecx, MIXING_CLIPMIN
1851 mov edx, MIXING_CLIPMAX
1852 mov eax, MIXING_CLIPMAX
1853 jmp cliprecover
1854 }
1855 }
1856 #else //MSC_VER
1857 //---GCCFIX: Asm replaced with C function
1858 DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1859 {
1860 UINT i ;
1861 int vumin = *lpMin, vumax = *lpMax;
1862 int n,p ;
1863 unsigned char* buf = (unsigned char*)lp16 ;
1864
1865 for ( i=0; i<lSampleCount; i++)
1866 {
1867 n = pBuffer[i];
1868 if (n < MIXING_CLIPMIN)
1869 n = MIXING_CLIPMIN;
1870 else if (n > MIXING_CLIPMAX)
1871 n = MIXING_CLIPMAX;
1872 if (n < vumin)
1873 vumin = n;
1874 else if (n > vumax)
1875 vumax = n;
1876 p = n >> (8-MIXING_ATTENUATION) ; // 24-bit signed
1877 buf[i*3] = p & 0xFF0000 ;
1878 buf[i*3+1] = p & 0x00FF00 ;
1879 buf[i*3+2] = p & 0x0000FF ;
1880 }
1881 *lpMin = vumin;
1882 *lpMax = vumax;
1883 return lSampleCount * 3;
1884 }
1885 #endif
1886
1887 #ifdef MSC_VER
1888 // Clip and convert to 32 bit
1889 __declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1890 //-----------------------------------------------------------------------------------------------------------------------------
1891 {
1892 _asm {
1893 push ebx
1894 push esi
1895 push edi
1896 mov ebx, 16[esp] // ebx = 32-bit buffer
1897 mov esi, 20[esp] // esi = pBuffer
1898 mov edi, 24[esp] // edi = lSampleCount
1899 mov eax, 28[esp]
1900 mov ecx, dword ptr [eax] // ecx = clipmin
1901 mov eax, 32[esp]
1902 mov edx, dword ptr [eax] // edx = clipmax
1903 cliploop:
1904 mov eax, dword ptr [esi]
1905 add ebx, 4
1906 add esi, 4
1907 cmp eax, MIXING_CLIPMIN
1908 jl cliplow
1909 cmp eax, MIXING_CLIPMAX
1910 jg cliphigh
1911 cmp eax, ecx
1912 jl updatemin
1913 cmp eax, edx
1914 jg updatemax
1915 cliprecover:
1916 shl eax, MIXING_ATTENUATION
1917 dec edi
1918 mov dword ptr [ebx-4], eax
1919 jnz cliploop
1920 mov eax, 28[esp]
1921 mov dword ptr [eax], ecx
1922 mov eax, 32[esp]
1923 mov dword ptr [eax], edx
1924 mov edx, 24[esp]
1925 pop edi
1926 mov eax, edx
1927 pop esi
1928 shl eax, 2
1929 pop ebx
1930 ret
1931 updatemin:
1932 mov ecx, eax
1933 jmp cliprecover
1934 updatemax:
1935 mov edx, eax
1936 jmp cliprecover
1937 cliplow:
1938 mov ecx, MIXING_CLIPMIN
1939 mov edx, MIXING_CLIPMAX
1940 mov eax, MIXING_CLIPMIN
1941 jmp cliprecover
1942 cliphigh:
1943 mov ecx, MIXING_CLIPMIN
1944 mov edx, MIXING_CLIPMAX
1945 mov eax, MIXING_CLIPMAX
1946 jmp cliprecover
1947 }
1948 }
1949 #else
1950 //---GCCFIX: Asm replaced with C function
1951 DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
1952 {
1953 UINT i ;
1954 int vumin = *lpMin, vumax = *lpMax;
1955 signed long *p = (signed long *)lp16;
1956
1957 for ( i=0; i<lSampleCount; i++)
1958 {
1959 int n = pBuffer[i];
1960 if (n < MIXING_CLIPMIN)
1961 n = MIXING_CLIPMIN;
1962 else if (n > MIXING_CLIPMAX)
1963 n = MIXING_CLIPMAX;
1964 if (n < vumin)
1965 vumin = n;
1966 else if (n > vumax)
1967 vumax = n;
1968 p[i] = n << MIXING_ATTENUATION; // 32-bit signed
1969 }
1970 *lpMin = vumin;
1971 *lpMax = vumax;
1972 return lSampleCount * 4;
1973 }
1974 #endif
1975
1976
1977 #ifdef MSC_VER
1978 void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
1979 //------------------------------------------------------------
1980 {
1981 _asm {
1982 mov ecx, nSamples
1983 mov esi, pBuffer
1984 xor eax, eax
1985 mov edx, ecx
1986 shr ecx, 2
1987 and edx, 3
1988 jz unroll4x
1989 loop1x:
1990 add esi, 4
1991 dec edx
1992 mov dword ptr [esi-4], eax
1993 jnz loop1x
1994 unroll4x:
1995 or ecx, ecx
1996 jnz loop4x
1997 jmp done
1998 loop4x:
1999 add esi, 16
2000 dec ecx
2001 mov dword ptr [esi-16], eax
2002 mov dword ptr [esi-12], eax
2003 mov dword ptr [esi-8], eax
2004 mov dword ptr [esi-4], eax
2005 jnz loop4x
2006 done:;
2007 }
2008 }
2009 #else
2010 //---GCCFIX: Asm replaced with C function
2011 // Will fill in later.
2012 void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
2013 {
2014 memset(pBuffer, 0, nSamples * sizeof(int));
2015 }
2016 #endif
2017
2018
2019 #ifdef MSC_VER
2020 __declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
2021 //------------------------------------------------------------------------------------------------------
2022 {
2023 _asm {
2024 push ebx
2025 push ebp
2026 push esi
2027 push edi
2028 mov ecx, 28[esp] // ecx = samplecount
2029 mov esi, 20[esp] // esi = front buffer
2030 mov edi, 24[esp] // edi = rear buffer
2031 lea esi, [esi+ecx*4] // esi = &front[N]
2032 lea edi, [edi+ecx*4] // edi = &rear[N]
2033 lea ebx, [esi+ecx*4] // ebx = &front[N*2]
2034 interleaveloop:
2035 mov eax, dword ptr [esi-8]
2036 mov edx, dword ptr [esi-4]
2037 sub ebx, 16
2038 mov ebp, dword ptr [edi-8]
2039 mov dword ptr [ebx], eax
2040 mov dword ptr [ebx+4], edx
2041 mov eax, dword ptr [edi-4]
2042 sub esi, 8
2043 sub edi, 8
2044 dec ecx
2045 mov dword ptr [ebx+8], ebp
2046 mov dword ptr [ebx+12], eax
2047 jnz interleaveloop
2048 pop edi
2049 pop esi
2050 pop ebp
2051 pop ebx
2052 ret
2053 }
2054 }
2055 #else
2056 //---GCCFIX: Asm replaced with C function
2057 // Multichannel not supported.
2058 void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
2059 {
2060 }
2061 #endif
2062
2063
2064 #ifdef MSC_VER
2065 VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
2066 //-------------------------------------------------------------
2067 {
2068 _asm {
2069 mov ecx, nSamples
2070 mov esi, pMixBuf
2071 mov edi, esi
2072 stloop:
2073 mov eax, dword ptr [esi]
2074 mov edx, dword ptr [esi+4]
2075 add edi, 4
2076 add esi, 8
2077 add eax, edx
2078 sar eax, 1
2079 dec ecx
2080 mov dword ptr [edi-4], eax
2081 jnz stloop
2082 }
2083 }
2084 #else
2085 //---GCCFIX: Asm replaced with C function
2086 VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
2087 {
2088 UINT j;
2089 for(UINT i = 0; i < nSamples; i++)
2090 {
2091 j = i << 1;
2092 pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1;
2093 }
2094 }
2095 #endif
2096
2097 #define OFSDECAYSHIFT 8
2098 #define OFSDECAYMASK 0xFF
2099
2100
2101 #ifdef MSC_VER
2102 void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
2103 //---------------------------------------------------------------------------------------
2104 {
2105 _asm {
2106 mov edi, pBuffer
2107 mov ecx, nSamples
2108 mov eax, lpROfs
2109 mov edx, lpLOfs
2110 mov eax, [eax]
2111 mov edx, [edx]
2112 or ecx, ecx
2113 jz fill_loop
2114 mov ebx, eax
2115 or ebx, edx
2116 jz fill_loop
2117 ofsloop:
2118 mov ebx, eax
2119 mov esi, edx
2120 neg ebx
2121 neg esi
2122 sar ebx, 31
2123 sar esi, 31
2124 and ebx, OFSDECAYMASK
2125 and esi, OFSDECAYMASK
2126 add ebx, eax
2127 add esi, edx
2128 sar ebx, OFSDECAYSHIFT
2129 sar esi, OFSDECAYSHIFT
2130 sub eax, ebx
2131 sub edx, esi
2132 mov ebx, eax
2133 or ebx, edx
2134 jz fill_loop
2135 add edi, 8
2136 dec ecx
2137 mov [edi-8], eax
2138 mov [edi-4], edx
2139 jnz ofsloop
2140 fill_loop:
2141 mov ebx, ecx
2142 and ebx, 3
2143 jz fill4x
2144 fill1x:
2145 mov [edi], eax
2146 mov [edi+4], edx
2147 add edi, 8
2148 dec ebx
2149 jnz fill1x
2150 fill4x:
2151 shr ecx, 2
2152 or ecx, ecx
2153 jz done
2154 fill4xloop:
2155 mov [edi], eax
2156 mov [edi+4], edx
2157 mov [edi+8], eax
2158 mov [edi+12], edx
2159 add edi, 8*4
2160 dec ecx
2161 mov [edi-16], eax
2162 mov [edi-12], edx
2163 mov [edi-8], eax
2164 mov [edi-4], edx
2165 jnz fill4xloop
2166 done:
2167 mov esi, lpROfs
2168 mov edi, lpLOfs
2169 mov [esi], eax
2170 mov [edi], edx
2171 }
2172 }
2173 #else
2174 //---GCCFIX: Asm replaced with C function
2175 #define OFSDECAYSHIFT 8
2176 #define OFSDECAYMASK 0xFF
2177 void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
2178 //---------------------------------------------------------------------------------------------------------
2179 {
2180 int rofs = *lpROfs;
2181 int lofs = *lpLOfs;
2182
2183 if ((!rofs) && (!lofs))
2184 {
2185 X86_InitMixBuffer(pBuffer, nSamples*2);
2186 return;
2187 }
2188 for (UINT i=0; i<nSamples; i++)
2189 {
2190 int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
2191 int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
2192 rofs -= x_r;
2193 lofs -= x_l;
2194 pBuffer[i*2] = x_r;
2195 pBuffer[i*2+1] = x_l;
2196 }
2197 *lpROfs = rofs;
2198 *lpLOfs = lofs;
2199 }
2200 #endif
2201
2202 #ifdef MSC_VER
2203 void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
2204 //----------------------------------------------------------------------------------
2205 {
2206 _asm {
2207 mov esi, pChannel
2208 mov edi, pBuffer
2209 mov ecx, nSamples
2210 mov eax, dword ptr [esi+MODCHANNEL.nROfs]
2211 mov edx, dword ptr [esi+MODCHANNEL.nLOfs]
2212 or ecx, ecx
2213 jz brkloop
2214 ofsloop:
2215 mov ebx, eax
2216 mov esi, edx
2217 neg ebx
2218 neg esi
2219 sar ebx, 31
2220 sar esi, 31
2221 and ebx, OFSDECAYMASK
2222 and esi, OFSDECAYMASK
2223 add ebx, eax
2224 add esi, edx
2225 sar ebx, OFSDECAYSHIFT
2226 sar esi, OFSDECAYSHIFT
2227 sub eax, ebx
2228 sub edx, esi
2229 mov ebx, eax
2230 add dword ptr [edi], eax
2231 add dword ptr [edi+4], edx
2232 or ebx, edx
2233 jz brkloop
2234 add edi, 8
2235 dec ecx
2236 jnz ofsloop
2237 brkloop:
2238 mov esi, pChannel
2239 mov dword ptr [esi+MODCHANNEL.nROfs], eax
2240 mov dword ptr [esi+MODCHANNEL.nLOfs], edx
2241 }
2242 }
2243 #else
2244 //---GCCFIX: Asm replaced with C function
2245 // Will fill in later.
2246 void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
2247 {
2248 int rofs = pChannel->nROfs;
2249 int lofs = pChannel->nLOfs;
2250
2251 if ((!rofs) && (!lofs)) return;
2252 for (UINT i=0; i<nSamples; i++)
2253 {
2254 int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
2255 int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
2256 rofs -= x_r;
2257 lofs -= x_l;
2258 pBuffer[i*2] += x_r;
2259 pBuffer[i*2+1] += x_l;
2260 }
2261 pChannel->nROfs = rofs;
2262 pChannel->nLOfs = lofs;
2263 }
2264 #endif
2265
2266
2267 //////////////////////////////////////////////////////////////////////////////////
2268 // Automatic Gain Control
2269
2270 #ifndef NO_AGC
2271
2272 // Limiter
2273 #define MIXING_LIMITMAX (0x08100000)
2274 #define MIXING_LIMITMIN (-MIXING_LIMITMAX)
2275
2276 #ifdef MSC_VER
2277 __declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
2278 //-------------------------------------------------------------------------------
2279 {
2280 __asm {
2281 push ebx
2282 push ebp
2283 push esi
2284 push edi
2285 mov esi, 20[esp] // esi = pBuffer+i
2286 mov ecx, 24[esp] // ecx = i
2287 mov edi, 28[esp] // edi = AGC (0..256)
2288 agcloop:
2289 mov eax, dword ptr [esi]
2290 imul edi
2291 shrd eax, edx, AGC_PRECISION
2292 add esi, 4
2293 cmp eax, MIXING_LIMITMIN
2294 jl agcupdate
2295 cmp eax, MIXING_LIMITMAX
2296 jg agcupdate
2297 agcrecover:
2298 dec ecx
2299 mov dword ptr [esi-4], eax
2300 jnz agcloop
2301 mov eax, edi
2302 pop edi
2303 pop esi
2304 pop ebp
2305 pop ebx
2306 ret
2307 agcupdate:
2308 dec edi
2309 jmp agcrecover
2310 }
2311 }
2312
2313 #pragma warning (default:4100)
2314 #else
2315 // Version for GCC
2316 UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
2317 {
2318 int x;
2319
2320 while(nSamples)
2321 {
2322 x = ((long long int)(*pBuffer) * nAGC) >> AGC_PRECISION;
2323
2324 if((x < MIXING_LIMITMIN) || (x > MIXING_LIMITMAX))
2325 nAGC--;
2326
2327 *pBuffer = x;
2328
2329 pBuffer++;
2330 nSamples--;
2331 }
2332
2333 return nAGC;
2334 }
2335 #endif
2336
2337 void CSoundFile::ProcessAGC(int count)
2338 //------------------------------------
2339 {
2340 static DWORD gAGCRecoverCount = 0;
2341 UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC);
2342 // Some kind custom law, so that the AGC stays quite stable, but slowly
2343 // goes back up if the sound level stays below a level inversely proportional
2344 // to the AGC level. (J'me comprends)
2345 if ((agc >= gnAGC) && (gnAGC < AGC_UNITY) && (gnVUMeter < (0xFF - (gnAGC >> (AGC_PRECISION-7))) ))
2346 {
2347 gAGCRecoverCount += count;
2348 UINT agctimeout = gdwMixingFreq + gnAGC;
2349 if (gnChannels >= 2) agctimeout <<= 1;
2350 if (gAGCRecoverCount >= agctimeout)
2351 {
2352 gAGCRecoverCount = 0;
2353 gnAGC++;
2354 }
2355 } else
2356 {
2357 gnAGC = agc;
2358 gAGCRecoverCount = 0;
2359 }
2360 }
2361
2362
2363
2364 void CSoundFile::ResetAGC()
2365 //-------------------------
2366 {
2367 gnAGC = AGC_UNITY;
2368 }
2369
2370 #endif // NO_AGC