Diffstat (limited to 'core/multimedia/opieplayer/modplug/fastmix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/modplug/fastmix.cpp | 2280 |
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) | ||
20 | int MixSoundBuffer[MIXBUFFERSIZE*4]; | ||
21 | |||
22 | // Reverb Mix Buffer | ||
23 | #ifndef NO_REVERB | ||
24 | int MixReverbBuffer[MIXBUFFERSIZE*2]; | ||
25 | extern UINT gnReverbSend; | ||
26 | #endif | ||
27 | |||
28 | #ifndef FASTSOUNDLIB | ||
29 | int MixRearBuffer[MIXBUFFERSIZE*2]; | ||
30 | float MixFloatBuffer[MIXBUFFERSIZE*2]; | ||
31 | #endif | ||
32 | |||
33 | #ifdef WIN32 | ||
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_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 | |||
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_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 | |||
192 | class 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 | |||
245 | signed short CzWINDOWEDFIR::lut[WFIR_LUTLEN*WFIR_WIDTH]; | ||
246 | |||
247 | CzWINDOWEDFIR::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 | |||
268 | CzWINDOWEDFIR::~CzWINDOWEDFIR() | ||
269 | {// nothing todo | ||
270 | } | ||
271 | |||
272 | CzWINDOWEDFIR 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 | |||
565 | typedef 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 | |||
659 | void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples); | ||
660 | void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples); | ||
661 | void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); | ||
662 | void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount); | ||
663 | void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount); | ||
664 | |||
665 | ///////////////////////////////////////////////////// | ||
666 | // Mono samples functions | ||
667 | |||
668 | BEGIN_MIX_INTERFACE(Mono8BitMix) | ||
669 | SNDMIX_BEGINSAMPLELOOP8 | ||
670 | SNDMIX_GETMONOVOL8NOIDO | ||
671 | SNDMIX_STOREMONOVOL | ||
672 | END_MIX_INTERFACE() | ||
673 | |||
674 | BEGIN_MIX_INTERFACE(Mono16BitMix) | ||
675 | SNDMIX_BEGINSAMPLELOOP16 | ||
676 | SNDMIX_GETMONOVOL16NOIDO | ||
677 | SNDMIX_STOREMONOVOL | ||
678 | END_MIX_INTERFACE() | ||
679 | |||
680 | BEGIN_MIX_INTERFACE(Mono8BitLinearMix) | ||
681 | SNDMIX_BEGINSAMPLELOOP8 | ||
682 | SNDMIX_GETMONOVOL8LINEAR | ||
683 | SNDMIX_STOREMONOVOL | ||
684 | END_MIX_INTERFACE() | ||
685 | |||
686 | BEGIN_MIX_INTERFACE(Mono16BitLinearMix) | ||
687 | SNDMIX_BEGINSAMPLELOOP16 | ||
688 | SNDMIX_GETMONOVOL16LINEAR | ||
689 | SNDMIX_STOREMONOVOL | ||
690 | END_MIX_INTERFACE() | ||
691 | |||
692 | BEGIN_MIX_INTERFACE(Mono8BitSplineMix) | ||
693 | SNDMIX_BEGINSAMPLELOOP8 | ||
694 | SNDMIX_GETMONOVOL8SPLINE | ||
695 | SNDMIX_STOREMONOVOL | ||
696 | END_MIX_INTERFACE() | ||
697 | |||
698 | BEGIN_MIX_INTERFACE(Mono16BitSplineMix) | ||
699 | SNDMIX_BEGINSAMPLELOOP16 | ||
700 | SNDMIX_GETMONOVOL16SPLINE | ||
701 | SNDMIX_STOREMONOVOL | ||
702 | END_MIX_INTERFACE() | ||
703 | |||
704 | BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix) | ||
705 | SNDMIX_BEGINSAMPLELOOP8 | ||
706 | SNDMIX_GETMONOVOL8FIRFILTER | ||
707 | SNDMIX_STOREMONOVOL | ||
708 | END_MIX_INTERFACE() | ||
709 | |||
710 | BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix) | ||
711 | SNDMIX_BEGINSAMPLELOOP16 | ||
712 | SNDMIX_GETMONOVOL16FIRFILTER | ||
713 | SNDMIX_STOREMONOVOL | ||
714 | END_MIX_INTERFACE() | ||
715 | |||
716 | |||
717 | // Volume Ramps | ||
718 | BEGIN_RAMPMIX_INTERFACE(Mono8BitRampMix) | ||
719 | SNDMIX_BEGINSAMPLELOOP8 | ||
720 | SNDMIX_GETMONOVOL8NOIDO | ||
721 | SNDMIX_RAMPMONOVOL | ||
722 | END_RAMPMIX_INTERFACE() | ||
723 | |||
724 | BEGIN_RAMPMIX_INTERFACE(Mono16BitRampMix) | ||
725 | SNDMIX_BEGINSAMPLELOOP16 | ||
726 | SNDMIX_GETMONOVOL16NOIDO | ||
727 | SNDMIX_RAMPMONOVOL | ||
728 | END_RAMPMIX_INTERFACE() | ||
729 | |||
730 | BEGIN_RAMPMIX_INTERFACE(Mono8BitLinearRampMix) | ||
731 | SNDMIX_BEGINSAMPLELOOP8 | ||
732 | SNDMIX_GETMONOVOL8LINEAR | ||
733 | SNDMIX_RAMPMONOVOL | ||
734 | END_RAMPMIX_INTERFACE() | ||
735 | |||
736 | BEGIN_RAMPMIX_INTERFACE(Mono16BitLinearRampMix) | ||
737 | SNDMIX_BEGINSAMPLELOOP16 | ||
738 | SNDMIX_GETMONOVOL16LINEAR | ||
739 | SNDMIX_RAMPMONOVOL | ||
740 | END_RAMPMIX_INTERFACE() | ||
741 | |||
742 | BEGIN_RAMPMIX_INTERFACE(Mono8BitSplineRampMix) | ||
743 | SNDMIX_BEGINSAMPLELOOP8 | ||
744 | SNDMIX_GETMONOVOL8SPLINE | ||
745 | SNDMIX_RAMPMONOVOL | ||
746 | END_RAMPMIX_INTERFACE() | ||
747 | |||
748 | BEGIN_RAMPMIX_INTERFACE(Mono16BitSplineRampMix) | ||
749 | SNDMIX_BEGINSAMPLELOOP16 | ||
750 | SNDMIX_GETMONOVOL16SPLINE | ||
751 | SNDMIX_RAMPMONOVOL | ||
752 | END_RAMPMIX_INTERFACE() | ||
753 | |||
754 | BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix) | ||
755 | SNDMIX_BEGINSAMPLELOOP8 | ||
756 | SNDMIX_GETMONOVOL8FIRFILTER | ||
757 | SNDMIX_RAMPMONOVOL | ||
758 | END_RAMPMIX_INTERFACE() | ||
759 | |||
760 | BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix) | ||
761 | SNDMIX_BEGINSAMPLELOOP16 | ||
762 | SNDMIX_GETMONOVOL16FIRFILTER | ||
763 | SNDMIX_RAMPMONOVOL | ||
764 | END_RAMPMIX_INTERFACE() | ||
765 | |||
766 | |||
767 | ////////////////////////////////////////////////////// | ||
768 | // Fast mono mix for leftvol=rightvol (1 less imul) | ||
769 | |||
770 | BEGIN_MIX_INTERFACE(FastMono8BitMix) | ||
771 | SNDMIX_BEGINSAMPLELOOP8 | ||
772 | SNDMIX_GETMONOVOL8NOIDO | ||
773 | SNDMIX_STOREFASTMONOVOL | ||
774 | END_MIX_INTERFACE() | ||
775 | |||
776 | BEGIN_MIX_INTERFACE(FastMono16BitMix) | ||
777 | SNDMIX_BEGINSAMPLELOOP16 | ||
778 | SNDMIX_GETMONOVOL16NOIDO | ||
779 | SNDMIX_STOREFASTMONOVOL | ||
780 | END_MIX_INTERFACE() | ||
781 | |||
782 | BEGIN_MIX_INTERFACE(FastMono8BitLinearMix) | ||
783 | SNDMIX_BEGINSAMPLELOOP8 | ||
784 | SNDMIX_GETMONOVOL8LINEAR | ||
785 | SNDMIX_STOREFASTMONOVOL | ||
786 | END_MIX_INTERFACE() | ||
787 | |||
788 | BEGIN_MIX_INTERFACE(FastMono16BitLinearMix) | ||
789 | SNDMIX_BEGINSAMPLELOOP16 | ||
790 | SNDMIX_GETMONOVOL16LINEAR | ||
791 | SNDMIX_STOREFASTMONOVOL | ||
792 | END_MIX_INTERFACE() | ||
793 | |||
794 | BEGIN_MIX_INTERFACE(FastMono8BitSplineMix) | ||
795 | SNDMIX_BEGINSAMPLELOOP8 | ||
796 | SNDMIX_GETMONOVOL8SPLINE | ||
797 | SNDMIX_STOREFASTMONOVOL | ||
798 | END_MIX_INTERFACE() | ||
799 | |||
800 | BEGIN_MIX_INTERFACE(FastMono16BitSplineMix) | ||
801 | SNDMIX_BEGINSAMPLELOOP16 | ||
802 | SNDMIX_GETMONOVOL16SPLINE | ||
803 | SNDMIX_STOREFASTMONOVOL | ||
804 | END_MIX_INTERFACE() | ||
805 | |||
806 | BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix) | ||
807 | SNDMIX_BEGINSAMPLELOOP8 | ||
808 | SNDMIX_GETMONOVOL8FIRFILTER | ||
809 | SNDMIX_STOREFASTMONOVOL | ||
810 | END_MIX_INTERFACE() | ||
811 | |||
812 | BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix) | ||
813 | SNDMIX_BEGINSAMPLELOOP16 | ||
814 | SNDMIX_GETMONOVOL16FIRFILTER | ||
815 | SNDMIX_STOREFASTMONOVOL | ||
816 | END_MIX_INTERFACE() | ||
817 | |||
818 | |||
819 | // Fast Ramps | ||
820 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitRampMix) | ||
821 | SNDMIX_BEGINSAMPLELOOP8 | ||
822 | SNDMIX_GETMONOVOL8NOIDO | ||
823 | SNDMIX_RAMPFASTMONOVOL | ||
824 | END_FASTRAMPMIX_INTERFACE() | ||
825 | |||
826 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitRampMix) | ||
827 | SNDMIX_BEGINSAMPLELOOP16 | ||
828 | SNDMIX_GETMONOVOL16NOIDO | ||
829 | SNDMIX_RAMPFASTMONOVOL | ||
830 | END_FASTRAMPMIX_INTERFACE() | ||
831 | |||
832 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitLinearRampMix) | ||
833 | SNDMIX_BEGINSAMPLELOOP8 | ||
834 | SNDMIX_GETMONOVOL8LINEAR | ||
835 | SNDMIX_RAMPFASTMONOVOL | ||
836 | END_FASTRAMPMIX_INTERFACE() | ||
837 | |||
838 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitLinearRampMix) | ||
839 | SNDMIX_BEGINSAMPLELOOP16 | ||
840 | SNDMIX_GETMONOVOL16LINEAR | ||
841 | SNDMIX_RAMPFASTMONOVOL | ||
842 | END_FASTRAMPMIX_INTERFACE() | ||
843 | |||
844 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitSplineRampMix) | ||
845 | SNDMIX_BEGINSAMPLELOOP8 | ||
846 | SNDMIX_GETMONOVOL8SPLINE | ||
847 | SNDMIX_RAMPFASTMONOVOL | ||
848 | END_FASTRAMPMIX_INTERFACE() | ||
849 | |||
850 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitSplineRampMix) | ||
851 | SNDMIX_BEGINSAMPLELOOP16 | ||
852 | SNDMIX_GETMONOVOL16SPLINE | ||
853 | SNDMIX_RAMPFASTMONOVOL | ||
854 | END_FASTRAMPMIX_INTERFACE() | ||
855 | |||
856 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix) | ||
857 | SNDMIX_BEGINSAMPLELOOP8 | ||
858 | SNDMIX_GETMONOVOL8FIRFILTER | ||
859 | SNDMIX_RAMPFASTMONOVOL | ||
860 | END_FASTRAMPMIX_INTERFACE() | ||
861 | |||
862 | BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix) | ||
863 | SNDMIX_BEGINSAMPLELOOP16 | ||
864 | SNDMIX_GETMONOVOL16FIRFILTER | ||
865 | SNDMIX_RAMPFASTMONOVOL | ||
866 | END_FASTRAMPMIX_INTERFACE() | ||
867 | |||
868 | |||
869 | ////////////////////////////////////////////////////// | ||
870 | // Stereo samples | ||
871 | |||
872 | BEGIN_MIX_INTERFACE(Stereo8BitMix) | ||
873 | SNDMIX_BEGINSAMPLELOOP8 | ||
874 | SNDMIX_GETSTEREOVOL8NOIDO | ||
875 | SNDMIX_STORESTEREOVOL | ||
876 | END_MIX_INTERFACE() | ||
877 | |||
878 | BEGIN_MIX_INTERFACE(Stereo16BitMix) | ||
879 | SNDMIX_BEGINSAMPLELOOP16 | ||
880 | SNDMIX_GETSTEREOVOL16NOIDO | ||
881 | SNDMIX_STORESTEREOVOL | ||
882 | END_MIX_INTERFACE() | ||
883 | |||
884 | BEGIN_MIX_INTERFACE(Stereo8BitLinearMix) | ||
885 | SNDMIX_BEGINSAMPLELOOP8 | ||
886 | SNDMIX_GETSTEREOVOL8LINEAR | ||
887 | SNDMIX_STORESTEREOVOL | ||
888 | END_MIX_INTERFACE() | ||
889 | |||
890 | BEGIN_MIX_INTERFACE(Stereo16BitLinearMix) | ||
891 | SNDMIX_BEGINSAMPLELOOP16 | ||
892 | SNDMIX_GETSTEREOVOL16LINEAR | ||
893 | SNDMIX_STORESTEREOVOL | ||
894 | END_MIX_INTERFACE() | ||
895 | |||
896 | BEGIN_MIX_INTERFACE(Stereo8BitSplineMix) | ||
897 | SNDMIX_BEGINSAMPLELOOP8 | ||
898 | SNDMIX_GETSTEREOVOL8SPLINE | ||
899 | SNDMIX_STORESTEREOVOL | ||
900 | END_MIX_INTERFACE() | ||
901 | |||
902 | BEGIN_MIX_INTERFACE(Stereo16BitSplineMix) | ||
903 | SNDMIX_BEGINSAMPLELOOP16 | ||
904 | SNDMIX_GETSTEREOVOL16SPLINE | ||
905 | SNDMIX_STORESTEREOVOL | ||
906 | END_MIX_INTERFACE() | ||
907 | |||
908 | BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix) | ||
909 | SNDMIX_BEGINSAMPLELOOP8 | ||
910 | SNDMIX_GETSTEREOVOL8FIRFILTER | ||
911 | SNDMIX_STORESTEREOVOL | ||
912 | END_MIX_INTERFACE() | ||
913 | |||
914 | BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix) | ||
915 | SNDMIX_BEGINSAMPLELOOP16 | ||
916 | SNDMIX_GETSTEREOVOL16FIRFILTER | ||
917 | SNDMIX_STORESTEREOVOL | ||
918 | END_MIX_INTERFACE() | ||
919 | |||
920 | |||
921 | // Volume Ramps | ||
922 | BEGIN_RAMPMIX_INTERFACE(Stereo8BitRampMix) | ||
923 | SNDMIX_BEGINSAMPLELOOP8 | ||
924 | SNDMIX_GETSTEREOVOL8NOIDO | ||
925 | SNDMIX_RAMPSTEREOVOL | ||
926 | END_RAMPMIX_INTERFACE() | ||
927 | |||
928 | BEGIN_RAMPMIX_INTERFACE(Stereo16BitRampMix) | ||
929 | SNDMIX_BEGINSAMPLELOOP16 | ||
930 | SNDMIX_GETSTEREOVOL16NOIDO | ||
931 | SNDMIX_RAMPSTEREOVOL | ||
932 | END_RAMPMIX_INTERFACE() | ||
933 | |||
934 | BEGIN_RAMPMIX_INTERFACE(Stereo8BitLinearRampMix) | ||
935 | SNDMIX_BEGINSAMPLELOOP8 | ||
936 | SNDMIX_GETSTEREOVOL8LINEAR | ||
937 | SNDMIX_RAMPSTEREOVOL | ||
938 | END_RAMPMIX_INTERFACE() | ||
939 | |||
940 | BEGIN_RAMPMIX_INTERFACE(Stereo16BitLinearRampMix) | ||
941 | SNDMIX_BEGINSAMPLELOOP16 | ||
942 | SNDMIX_GETSTEREOVOL16LINEAR | ||
943 | SNDMIX_RAMPSTEREOVOL | ||
944 | END_RAMPMIX_INTERFACE() | ||
945 | |||
946 | BEGIN_RAMPMIX_INTERFACE(Stereo8BitSplineRampMix) | ||
947 | SNDMIX_BEGINSAMPLELOOP8 | ||
948 | SNDMIX_GETSTEREOVOL8SPLINE | ||
949 | SNDMIX_RAMPSTEREOVOL | ||
950 | END_RAMPMIX_INTERFACE() | ||
951 | |||
952 | BEGIN_RAMPMIX_INTERFACE(Stereo16BitSplineRampMix) | ||
953 | SNDMIX_BEGINSAMPLELOOP16 | ||
954 | SNDMIX_GETSTEREOVOL16SPLINE | ||
955 | SNDMIX_RAMPSTEREOVOL | ||
956 | END_RAMPMIX_INTERFACE() | ||
957 | |||
958 | BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix) | ||
959 | SNDMIX_BEGINSAMPLELOOP8 | ||
960 | SNDMIX_GETSTEREOVOL8FIRFILTER | ||
961 | SNDMIX_RAMPSTEREOVOL | ||
962 | END_RAMPMIX_INTERFACE() | ||
963 | |||
964 | BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix) | ||
965 | SNDMIX_BEGINSAMPLELOOP16 | ||
966 | SNDMIX_GETSTEREOVOL16FIRFILTER | ||
967 | SNDMIX_RAMPSTEREOVOL | ||
968 | END_RAMPMIX_INTERFACE() | ||
969 | |||
970 | |||
971 | |||
972 | ////////////////////////////////////////////////////// | ||
973 | // Resonant Filter Mix | ||
974 | |||
975 | #ifndef NO_FILTER | ||
976 | |||
977 | // Mono Filter Mix | ||
978 | BEGIN_MIX_FLT_INTERFACE(FilterMono8BitMix) | ||
979 | SNDMIX_BEGINSAMPLELOOP8 | ||
980 | SNDMIX_GETMONOVOL8NOIDO | ||
981 | SNDMIX_PROCESSFILTER | ||
982 | SNDMIX_STOREMONOVOL | ||
983 | END_MIX_FLT_INTERFACE() | ||
984 | |||
985 | BEGIN_MIX_FLT_INTERFACE(FilterMono16BitMix) | ||
986 | SNDMIX_BEGINSAMPLELOOP16 | ||
987 | SNDMIX_GETMONOVOL16NOIDO | ||
988 | SNDMIX_PROCESSFILTER | ||
989 | SNDMIX_STOREMONOVOL | ||
990 | END_MIX_FLT_INTERFACE() | ||
991 | |||
992 | BEGIN_MIX_FLT_INTERFACE(FilterMono8BitLinearMix) | ||
993 | SNDMIX_BEGINSAMPLELOOP8 | ||
994 | SNDMIX_GETMONOVOL8LINEAR | ||
995 | SNDMIX_PROCESSFILTER | ||
996 | SNDMIX_STOREMONOVOL | ||
997 | END_MIX_FLT_INTERFACE() | ||
998 | |||
999 | BEGIN_MIX_FLT_INTERFACE(FilterMono16BitLinearMix) | ||
1000 | SNDMIX_BEGINSAMPLELOOP16 | ||
1001 | SNDMIX_GETMONOVOL16LINEAR | ||
1002 | SNDMIX_PROCESSFILTER | ||
1003 | SNDMIX_STOREMONOVOL | ||
1004 | END_MIX_FLT_INTERFACE() | ||
1005 | |||
1006 | BEGIN_MIX_FLT_INTERFACE(FilterMono8BitSplineMix) | ||
1007 | SNDMIX_BEGINSAMPLELOOP8 | ||
1008 | SNDMIX_GETMONOVOL8SPLINE | ||
1009 | SNDMIX_PROCESSFILTER | ||
1010 | SNDMIX_STOREMONOVOL | ||
1011 | END_MIX_FLT_INTERFACE() | ||
1012 | |||
1013 | BEGIN_MIX_FLT_INTERFACE(FilterMono16BitSplineMix) | ||
1014 | SNDMIX_BEGINSAMPLELOOP16 | ||
1015 | SNDMIX_GETMONOVOL16SPLINE | ||
1016 | SNDMIX_PROCESSFILTER | ||
1017 | SNDMIX_STOREMONOVOL | ||
1018 | END_MIX_FLT_INTERFACE() | ||
1019 | |||
1020 | BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix) | ||
1021 | SNDMIX_BEGINSAMPLELOOP8 | ||
1022 | SNDMIX_GETMONOVOL8FIRFILTER | ||
1023 | SNDMIX_PROCESSFILTER | ||
1024 | SNDMIX_STOREMONOVOL | ||
1025 | END_MIX_FLT_INTERFACE() | ||
1026 | |||
1027 | BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix) | ||
1028 | SNDMIX_BEGINSAMPLELOOP16 | ||
1029 | SNDMIX_GETMONOVOL16FIRFILTER | ||
1030 | SNDMIX_PROCESSFILTER | ||
1031 | SNDMIX_STOREMONOVOL | ||
1032 | END_MIX_FLT_INTERFACE() | ||
1033 | |||
1034 | // Filter + Ramp | ||
1035 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitRampMix) | ||
1036 | SNDMIX_BEGINSAMPLELOOP8 | ||
1037 | SNDMIX_GETMONOVOL8NOIDO | ||
1038 | SNDMIX_PROCESSFILTER | ||
1039 | SNDMIX_RAMPMONOVOL | ||
1040 | END_RAMPMIX_FLT_INTERFACE() | ||
1041 | |||
1042 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitRampMix) | ||
1043 | SNDMIX_BEGINSAMPLELOOP16 | ||
1044 | SNDMIX_GETMONOVOL16NOIDO | ||
1045 | SNDMIX_PROCESSFILTER | ||
1046 | SNDMIX_RAMPMONOVOL | ||
1047 | END_RAMPMIX_FLT_INTERFACE() | ||
1048 | |||
1049 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitLinearRampMix) | ||
1050 | SNDMIX_BEGINSAMPLELOOP8 | ||
1051 | SNDMIX_GETMONOVOL8LINEAR | ||
1052 | SNDMIX_PROCESSFILTER | ||
1053 | SNDMIX_RAMPMONOVOL | ||
1054 | END_RAMPMIX_FLT_INTERFACE() | ||
1055 | |||
1056 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitLinearRampMix) | ||
1057 | SNDMIX_BEGINSAMPLELOOP16 | ||
1058 | SNDMIX_GETMONOVOL16LINEAR | ||
1059 | SNDMIX_PROCESSFILTER | ||
1060 | SNDMIX_RAMPMONOVOL | ||
1061 | END_RAMPMIX_FLT_INTERFACE() | ||
1062 | |||
1063 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitSplineRampMix) | ||
1064 | SNDMIX_BEGINSAMPLELOOP8 | ||
1065 | SNDMIX_GETMONOVOL8SPLINE | ||
1066 | SNDMIX_PROCESSFILTER | ||
1067 | SNDMIX_RAMPMONOVOL | ||
1068 | END_RAMPMIX_FLT_INTERFACE() | ||
1069 | |||
1070 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitSplineRampMix) | ||
1071 | SNDMIX_BEGINSAMPLELOOP16 | ||
1072 | SNDMIX_GETMONOVOL16SPLINE | ||
1073 | SNDMIX_PROCESSFILTER | ||
1074 | SNDMIX_RAMPMONOVOL | ||
1075 | END_RAMPMIX_FLT_INTERFACE() | ||
1076 | |||
1077 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix) | ||
1078 | SNDMIX_BEGINSAMPLELOOP8 | ||
1079 | SNDMIX_GETMONOVOL8FIRFILTER | ||
1080 | SNDMIX_PROCESSFILTER | ||
1081 | SNDMIX_RAMPMONOVOL | ||
1082 | END_RAMPMIX_FLT_INTERFACE() | ||
1083 | |||
1084 | BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix) | ||
1085 | SNDMIX_BEGINSAMPLELOOP16 | ||
1086 | SNDMIX_GETMONOVOL16FIRFILTER | ||
1087 | SNDMIX_PROCESSFILTER | ||
1088 | SNDMIX_RAMPMONOVOL | ||
1089 | END_RAMPMIX_FLT_INTERFACE() | ||
1090 | |||
1091 | |||
1092 | // Stereo Filter Mix | ||
1093 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitMix) | ||
1094 | SNDMIX_BEGINSAMPLELOOP8 | ||
1095 | SNDMIX_GETSTEREOVOL8NOIDO | ||
1096 | SNDMIX_PROCESSSTEREOFILTER | ||
1097 | SNDMIX_STORESTEREOVOL | ||
1098 | END_MIX_STFLT_INTERFACE() | ||
1099 | |||
1100 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitMix) | ||
1101 | SNDMIX_BEGINSAMPLELOOP16 | ||
1102 | SNDMIX_GETSTEREOVOL16NOIDO | ||
1103 | SNDMIX_PROCESSSTEREOFILTER | ||
1104 | SNDMIX_STORESTEREOVOL | ||
1105 | END_MIX_STFLT_INTERFACE() | ||
1106 | |||
1107 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitLinearMix) | ||
1108 | SNDMIX_BEGINSAMPLELOOP8 | ||
1109 | SNDMIX_GETSTEREOVOL8LINEAR | ||
1110 | SNDMIX_PROCESSSTEREOFILTER | ||
1111 | SNDMIX_STORESTEREOVOL | ||
1112 | END_MIX_STFLT_INTERFACE() | ||
1113 | |||
1114 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitLinearMix) | ||
1115 | SNDMIX_BEGINSAMPLELOOP16 | ||
1116 | SNDMIX_GETSTEREOVOL16LINEAR | ||
1117 | SNDMIX_PROCESSSTEREOFILTER | ||
1118 | SNDMIX_STORESTEREOVOL | ||
1119 | END_MIX_STFLT_INTERFACE() | ||
1120 | |||
1121 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitSplineMix) | ||
1122 | SNDMIX_BEGINSAMPLELOOP8 | ||
1123 | SNDMIX_GETSTEREOVOL8SPLINE | ||
1124 | SNDMIX_PROCESSSTEREOFILTER | ||
1125 | SNDMIX_STORESTEREOVOL | ||
1126 | END_MIX_STFLT_INTERFACE() | ||
1127 | |||
1128 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitSplineMix) | ||
1129 | SNDMIX_BEGINSAMPLELOOP16 | ||
1130 | SNDMIX_GETSTEREOVOL16SPLINE | ||
1131 | SNDMIX_PROCESSSTEREOFILTER | ||
1132 | SNDMIX_STORESTEREOVOL | ||
1133 | END_MIX_STFLT_INTERFACE() | ||
1134 | |||
1135 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix) | ||
1136 | SNDMIX_BEGINSAMPLELOOP8 | ||
1137 | SNDMIX_GETSTEREOVOL8FIRFILTER | ||
1138 | SNDMIX_PROCESSSTEREOFILTER | ||
1139 | SNDMIX_STORESTEREOVOL | ||
1140 | END_MIX_STFLT_INTERFACE() | ||
1141 | |||
1142 | BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix) | ||
1143 | SNDMIX_BEGINSAMPLELOOP16 | ||
1144 | SNDMIX_GETSTEREOVOL16FIRFILTER | ||
1145 | SNDMIX_PROCESSSTEREOFILTER | ||
1146 | SNDMIX_STORESTEREOVOL | ||
1147 | END_MIX_STFLT_INTERFACE() | ||
1148 | |||
1149 | // Stereo Filter + Ramp | ||
1150 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitRampMix) | ||
1151 | SNDMIX_BEGINSAMPLELOOP8 | ||
1152 | SNDMIX_GETSTEREOVOL8NOIDO | ||
1153 | SNDMIX_PROCESSSTEREOFILTER | ||
1154 | SNDMIX_RAMPSTEREOVOL | ||
1155 | END_RAMPMIX_STFLT_INTERFACE() | ||
1156 | |||
1157 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitRampMix) | ||
1158 | SNDMIX_BEGINSAMPLELOOP16 | ||
1159 | SNDMIX_GETSTEREOVOL16NOIDO | ||
1160 | SNDMIX_PROCESSSTEREOFILTER | ||
1161 | SNDMIX_RAMPSTEREOVOL | ||
1162 | END_RAMPMIX_STFLT_INTERFACE() | ||
1163 | |||
1164 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitLinearRampMix) | ||
1165 | SNDMIX_BEGINSAMPLELOOP8 | ||
1166 | SNDMIX_GETSTEREOVOL8LINEAR | ||
1167 | SNDMIX_PROCESSSTEREOFILTER | ||
1168 | SNDMIX_RAMPSTEREOVOL | ||
1169 | END_RAMPMIX_STFLT_INTERFACE() | ||
1170 | |||
1171 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitLinearRampMix) | ||
1172 | SNDMIX_BEGINSAMPLELOOP16 | ||
1173 | SNDMIX_GETSTEREOVOL16LINEAR | ||
1174 | SNDMIX_PROCESSSTEREOFILTER | ||
1175 | SNDMIX_RAMPSTEREOVOL | ||
1176 | END_RAMPMIX_STFLT_INTERFACE() | ||
1177 | |||
1178 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitSplineRampMix) | ||
1179 | SNDMIX_BEGINSAMPLELOOP8 | ||
1180 | SNDMIX_GETSTEREOVOL8SPLINE | ||
1181 | SNDMIX_PROCESSSTEREOFILTER | ||
1182 | SNDMIX_RAMPSTEREOVOL | ||
1183 | END_RAMPMIX_STFLT_INTERFACE() | ||
1184 | |||
1185 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitSplineRampMix) | ||
1186 | SNDMIX_BEGINSAMPLELOOP16 | ||
1187 | SNDMIX_GETSTEREOVOL16SPLINE | ||
1188 | SNDMIX_PROCESSSTEREOFILTER | ||
1189 | SNDMIX_RAMPSTEREOVOL | ||
1190 | END_RAMPMIX_STFLT_INTERFACE() | ||
1191 | |||
1192 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix) | ||
1193 | SNDMIX_BEGINSAMPLELOOP8 | ||
1194 | SNDMIX_GETSTEREOVOL8FIRFILTER | ||
1195 | SNDMIX_PROCESSSTEREOFILTER | ||
1196 | SNDMIX_RAMPSTEREOVOL | ||
1197 | END_RAMPMIX_STFLT_INTERFACE() | ||
1198 | |||
1199 | BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix) | ||
1200 | SNDMIX_BEGINSAMPLELOOP16 | ||
1201 | SNDMIX_GETSTEREOVOL16FIRFILTER | ||
1202 | SNDMIX_PROCESSSTEREOFILTER | ||
1203 | SNDMIX_RAMPSTEREOVOL | ||
1204 | END_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 | |||
1265 | const 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 | |||
1295 | const 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 | |||
1328 | static 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 | |||
1434 | UINT 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 | ||
1589 | cliploop: | ||
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 | ||
1603 | cliprecover: | ||
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 | ||
1619 | updatemin: | ||
1620 | mov ecx, eax | ||
1621 | jmp cliprecover | ||
1622 | updatemax: | ||
1623 | mov edx, eax | ||
1624 | jmp cliprecover | ||
1625 | cliplow: | ||
1626 | mov ecx, MIXING_CLIPMIN | ||
1627 | mov edx, MIXING_CLIPMAX | ||
1628 | mov eax, MIXING_CLIPMIN | ||
1629 | jmp cliprecover | ||
1630 | cliphigh: | ||
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 | ||
1681 | cliploop: | ||
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 | ||
1696 | cliprecover: | ||
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 | ||
1713 | updatemin: | ||
1714 | mov ecx, eax | ||
1715 | jmp cliprecover | ||
1716 | updatemax: | ||
1717 | mov ebp, eax | ||
1718 | jmp cliprecover | ||
1719 | cliplow: | ||
1720 | mov ecx, MIXING_CLIPMIN | ||
1721 | mov ebp, MIXING_CLIPMAX | ||
1722 | mov eax, MIXING_CLIPMIN | ||
1723 | jmp cliprecover | ||
1724 | cliphigh: | ||
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 | ||
1774 | cliploop: | ||
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 | ||
1788 | cliprecover: | ||
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 | ||
1810 | updatemin: | ||
1811 | mov ecx, eax | ||
1812 | jmp cliprecover | ||
1813 | updatemax: | ||
1814 | mov edx, eax | ||
1815 | jmp cliprecover | ||
1816 | cliplow: | ||
1817 | mov ecx, MIXING_CLIPMIN | ||
1818 | mov edx, MIXING_CLIPMAX | ||
1819 | mov eax, MIXING_CLIPMIN | ||
1820 | jmp cliprecover | ||
1821 | cliphigh: | ||
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 | ||
1853 | cliploop: | ||
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 | ||
1865 | cliprecover: | ||
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 | ||
1881 | updatemin: | ||
1882 | mov ecx, eax | ||
1883 | jmp cliprecover | ||
1884 | updatemax: | ||
1885 | mov edx, eax | ||
1886 | jmp cliprecover | ||
1887 | cliplow: | ||
1888 | mov ecx, MIXING_CLIPMIN | ||
1889 | mov edx, MIXING_CLIPMAX | ||
1890 | mov eax, MIXING_CLIPMIN | ||
1891 | jmp cliprecover | ||
1892 | cliphigh: | ||
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 | ||
1910 | void 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 | ||
1921 | loop1x: | ||
1922 | add esi, 4 | ||
1923 | dec edx | ||
1924 | mov dword ptr [esi-4], eax | ||
1925 | jnz loop1x | ||
1926 | unroll4x: | ||
1927 | or ecx, ecx | ||
1928 | jnz loop4x | ||
1929 | jmp done | ||
1930 | loop4x: | ||
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 | ||
1938 | done:; | ||
1939 | } | ||
1940 | } | ||
1941 | #else | ||
1942 | //---GCCFIX: Asm replaced with C function | ||
1943 | // Will fill in later. | ||
1944 | void 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] | ||
1966 | interleaveloop: | ||
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 | ||
1997 | VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples) | ||
1998 | //------------------------------------------------------------- | ||
1999 | { | ||
2000 | _asm { | ||
2001 | mov ecx, nSamples | ||
2002 | mov esi, pMixBuf | ||
2003 | mov edi, esi | ||
2004 | stloop: | ||
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 | ||
2018 | VOID 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 | ||
2034 | void 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 | ||
2049 | ofsloop: | ||
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 | ||
2072 | fill_loop: | ||
2073 | mov ebx, ecx | ||
2074 | and ebx, 3 | ||
2075 | jz fill4x | ||
2076 | fill1x: | ||
2077 | mov [edi], eax | ||
2078 | mov [edi+4], edx | ||
2079 | add edi, 8 | ||
2080 | dec ebx | ||
2081 | jnz fill1x | ||
2082 | fill4x: | ||
2083 | shr ecx, 2 | ||
2084 | or ecx, ecx | ||
2085 | jz done | ||
2086 | fill4xloop: | ||
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 | ||
2098 | done: | ||
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 | ||
2135 | void 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 | ||
2146 | ofsloop: | ||
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 | ||
2169 | brkloop: | ||
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. | ||
2178 | void 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) | ||
2219 | agcloop: | ||
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 | ||
2228 | agcrecover: | ||
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 | ||
2238 | agcupdate: | ||
2239 | dec edi | ||
2240 | jmp agcrecover | ||
2241 | } | ||
2242 | } | ||
2243 | |||
2244 | #pragma warning (default:4100) | ||
2245 | |||
2246 | void 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 | |||
2273 | void CSoundFile::ResetAGC() | ||
2274 | //------------------------- | ||
2275 | { | ||
2276 | gnAGC = AGC_UNITY; | ||
2277 | } | ||
2278 | |||
2279 | #endif // NO_AGC | ||
2280 | |||