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