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