Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

fastmix.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is  free software; you can redistribute it  and modify it
00003  * under the terms of the GNU  General Public License as published by the
00004  * Free Software Foundation; either version 2  of the license or (at your
00005  * option) any later version.
00006  *
00007  * Authors: Olivier Lapicque <olivierl@jps.net>
00008  *          Markus Fick <webmaster@mark-f.de> spline + fir-resampler
00009 */
00010 
00011 #include "stdafx.h"
00012 #include "sndfile.h"
00013 #include <math.h>
00014 
00015 #ifdef WIN32
00016 #pragma bss_seg(".modplug")
00017 #endif
00018 
00019 // Front Mix Buffer (Also room for interleaved rear mix)
00020 int MixSoundBuffer[MIXBUFFERSIZE*4];
00021 
00022 // Reverb Mix Buffer
00023 #ifndef NO_REVERB
00024 int MixReverbBuffer[MIXBUFFERSIZE*2];
00025 extern UINT gnReverbSend;
00026 #endif
00027 
00028 #ifndef FASTSOUNDLIB
00029 int MixRearBuffer[MIXBUFFERSIZE*2];
00030 float MixFloatBuffer[MIXBUFFERSIZE*2];
00031 #endif
00032 
00033 #ifdef WIN32
00034 #pragma bss_seg()
00035 #endif
00036 
00037 
00038 extern LONG gnDryROfsVol;
00039 extern LONG gnDryLOfsVol;
00040 extern LONG gnRvbROfsVol;
00041 extern LONG gnRvbLOfsVol;
00042 
00043 // 4x256 taps polyphase FIR resampling filter
00044 extern short int gFastSinc[];
00045 extern short int gKaiserSinc[]; // 8-taps polyphase
00046 /* 
00047   ------------------------------------------------------------------------------------------------
00048    cubic spline interpolation doc,
00049         (derived from "digital image warping", g. wolberg)
00050 
00051         interpolation polynomial: f(x) = A3*(x-floor(x))**3 + A2*(x-floor(x))**2 + A1*(x-floor(x)) + A0
00052 
00053         with Y = equispaced data points (dist=1), YD = first derivates of data points and IP = floor(x)
00054         the A[0..3] can be found by solving
00055           A0  = Y[IP]
00056           A1  = YD[IP]
00057           A2  = 3*(Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1]
00058           A3  = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] - YD[IP+1]
00059 
00060         with the first derivates as
00061           YD[IP]    = 0.5 * (Y[IP+1] - Y[IP-1]);
00062           YD[IP+1]  = 0.5 * (Y[IP+2] - Y[IP])
00063 
00064         the coefs becomes
00065           A0  = Y[IP]
00066           A1  = YD[IP]
00067               =  0.5 * (Y[IP+1] - Y[IP-1]);
00068           A2  =  3.0 * (Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1]
00069               =  3.0 * (Y[IP+1] - Y[IP]) - 0.5 * 2.0 * (Y[IP+1] - Y[IP-1]) - 0.5 * (Y[IP+2] - Y[IP])
00070               =  3.0 * Y[IP+1] - 3.0 * Y[IP] - Y[IP+1] + Y[IP-1] - 0.5 * Y[IP+2] + 0.5 * Y[IP]
00071               = -0.5 * Y[IP+2] + 2.0 * Y[IP+1] - 2.5 * Y[IP] + Y[IP-1]
00072                   = Y[IP-1] + 2 * Y[IP+1] - 0.5 * (5.0 * Y[IP] + Y[IP+2])
00073           A3  = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] + YD[IP+1]
00074               = -2.0 * Y[IP+1] + 2.0 * Y[IP] + 0.5 * (Y[IP+1] - Y[IP-1]) + 0.5 * (Y[IP+2] - Y[IP])
00075               = -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]
00076               =  0.5 * Y[IP+2] - 1.5 * Y[IP+1] + 1.5 * Y[IP] - 0.5 * Y[IP-1]
00077                   =  0.5 * (3.0 * (Y[IP] - Y[IP+1]) - Y[IP-1] + YP[IP+2])
00078 
00079         then interpolated data value is (horner rule)
00080           out = (((A3*x)+A2)*x+A1)*x+A0
00081 
00082         this gives parts of data points Y[IP-1] to Y[IP+2] of
00083           part       x**3    x**2    x**1    x**0
00084           Y[IP-1]    -0.5     1      -0.5    0
00085           Y[IP]       1.5    -2.5     0      1
00086           Y[IP+1]    -1.5     2       0.5    0
00087           Y[IP+2]     0.5    -0.5     0      0
00088   --------------------------------------------------------------------------------------------------
00089 */
00090 // number of bits used to scale spline coefs
00091 #define SPLINE_QUANTBITS        14
00092 #define SPLINE_QUANTSCALE       (1L<<SPLINE_QUANTBITS)
00093 #define SPLINE_8SHIFT           (SPLINE_QUANTBITS-8)
00094 #define SPLINE_16SHIFT          (SPLINE_QUANTBITS)
00095 // forces coefsset to unity gain
00096 #define SPLINE_CLAMPFORUNITY
00097 // log2(number) of precalculated splines (range is [4..14])
00098 #define SPLINE_FRACBITS 10
00099 #define SPLINE_LUTLEN (1L<<SPLINE_FRACBITS)
00100 
00101 class CzCUBICSPLINE
00102 {       public:
00103                 CzCUBICSPLINE( );
00104                 ~CzCUBICSPLINE( );
00105                 static signed short lut[4*(1L<<SPLINE_FRACBITS)];
00106 };
00107 
00108 signed short CzCUBICSPLINE::lut[4*(1L<<SPLINE_FRACBITS)];
00109 
00110 CzCUBICSPLINE::CzCUBICSPLINE( )
00111 {       int _LIi;
00112         int _LLen               = (1L<<SPLINE_FRACBITS);
00113         float _LFlen    = 1.0f / (float)_LLen;
00114         float _LScale   = (float)SPLINE_QUANTSCALE;
00115         for(_LIi=0;_LIi<_LLen;_LIi++)
00116         {       float _LCm1, _LC0, _LC1, _LC2;
00117                 float _LX               = ((float)_LIi)*_LFlen;
00118                 int _LSum,_LIdx = _LIi<<2;
00119                 _LCm1                   = (float)floor( 0.5 + _LScale * (-0.5*_LX*_LX*_LX + 1.0 * _LX*_LX - 0.5 * _LX       ) );
00120                 _LC0                    = (float)floor( 0.5 + _LScale * ( 1.5*_LX*_LX*_LX - 2.5 * _LX*_LX             + 1.0 ) );
00121                 _LC1                    = (float)floor( 0.5 + _LScale * (-1.5*_LX*_LX*_LX + 2.0 * _LX*_LX + 0.5 * _LX       ) );
00122                 _LC2                    = (float)floor( 0.5 + _LScale * ( 0.5*_LX*_LX*_LX - 0.5 * _LX*_LX                   ) );
00123                 lut[_LIdx+0]    = (signed short)( (_LCm1 < -_LScale) ? -_LScale : ((_LCm1 > _LScale) ? _LScale : _LCm1) );
00124                 lut[_LIdx+1]    = (signed short)( (_LC0  < -_LScale) ? -_LScale : ((_LC0  > _LScale) ? _LScale : _LC0 ) );
00125                 lut[_LIdx+2]    = (signed short)( (_LC1  < -_LScale) ? -_LScale : ((_LC1  > _LScale) ? _LScale : _LC1 ) );
00126                 lut[_LIdx+3]    = (signed short)( (_LC2  < -_LScale) ? -_LScale : ((_LC2  > _LScale) ? _LScale : _LC2 ) );
00127 #ifdef SPLINE_CLAMPFORUNITY
00128                 _LSum                   = lut[_LIdx+0]+lut[_LIdx+1]+lut[_LIdx+2]+lut[_LIdx+3];
00129                 if( _LSum != SPLINE_QUANTSCALE )
00130                 {       int _LMax = _LIdx;
00131                         if( lut[_LIdx+1]>lut[_LMax] ) _LMax = _LIdx+1;
00132                         if( lut[_LIdx+2]>lut[_LMax] ) _LMax = _LIdx+2;
00133                         if( lut[_LIdx+3]>lut[_LMax] ) _LMax = _LIdx+3;
00134                         lut[_LMax] += (SPLINE_QUANTSCALE-_LSum);
00135                 }
00136 #endif
00137         }
00138 }
00139 
00140 CzCUBICSPLINE::~CzCUBICSPLINE( )
00141 {       // nothing todo
00142 }
00143 
00144 CzCUBICSPLINE sspline;
00145 
00146 /* 
00147   ------------------------------------------------------------------------------------------------
00148    fir interpolation doc,
00149         (derived from "an engineer's guide to fir digital filters", n.j. loy)
00150 
00151         calculate coefficients for ideal lowpass filter (with cutoff = fc in 0..1 (mapped to 0..nyquist))
00152           c[-N..N] = (i==0) ? fc : sin(fc*pi*i)/(pi*i)
00153 
00154         then apply selected window to coefficients
00155           c[-N..N] *= w(0..N)
00156         with n in 2*N and w(n) being a window function (see loy)
00157 
00158         then calculate gain and scale filter coefs to have unity gain.
00159   ------------------------------------------------------------------------------------------------
00160 */
00161 // quantizer scale of window coefs
00162 #define WFIR_QUANTBITS          15
00163 #define WFIR_QUANTSCALE         (1L<<WFIR_QUANTBITS)
00164 #define WFIR_8SHIFT                     (WFIR_QUANTBITS-8)
00165 #define WFIR_16BITSHIFT         (WFIR_QUANTBITS)
00166 // log2(number)-1 of precalculated taps range is [4..12]
00167 #define WFIR_FRACBITS           10
00168 #define WFIR_LUTLEN                     ((1L<<(WFIR_FRACBITS+1))+1)
00169 // number of samples in window
00170 #define WFIR_LOG2WIDTH          3
00171 #define WFIR_WIDTH                      (1L<<WFIR_LOG2WIDTH)
00172 #define WFIR_SMPSPERWING        ((WFIR_WIDTH-1)>>1)
00173 // cutoff (1.0 == pi/2)
00174 #define WFIR_CUTOFF                     0.90f
00175 // wfir type
00176 #define WFIR_HANN                       0
00177 #define WFIR_HAMMING            1
00178 #define WFIR_BLACKMANEXACT      2
00179 #define WFIR_BLACKMAN3T61       3
00180 #define WFIR_BLACKMAN3T67       4
00181 #define WFIR_BLACKMAN4T92       5
00182 #define WFIR_BLACKMAN4T74       6
00183 #define WFIR_KAISER4T           7
00184 #define WFIR_TYPE                       WFIR_BLACKMANEXACT
00185 // wfir help
00186 #ifndef M_zPI
00187 #define M_zPI                   3.1415926535897932384626433832795
00188 #endif
00189 #define M_zEPS                  1e-8
00190 #define M_zBESSELEPS    1e-21
00191 
00192 class CzWINDOWEDFIR
00193 {       public:
00194                 CzWINDOWEDFIR( );
00195                 ~CzWINDOWEDFIR( );
00196                 float coef( int _PCnr, float _POfs, float _PCut, int _PWidth, int _PType ) //float _PPos, float _PFc, int _PLen )
00197                 {       double  _LWidthM1               = _PWidth-1;
00198                         double  _LWidthM1Half   = 0.5*_LWidthM1;
00199                         double  _LPosU                  = ((double)_PCnr - _POfs);
00200                         double  _LPos                   = _LPosU-_LWidthM1Half;
00201                         double  _LPIdl                  = 2.0*M_zPI/_LWidthM1;
00202                         double  _LWc,_LSi;
00203                         if( fabs(_LPos)<M_zEPS )
00204                         {       _LWc    = 1.0;
00205                                 _LSi    = _PCut;
00206                         }
00207                         else
00208                         {       switch( _PType )
00209                                 {       case WFIR_HANN:
00210                                                 _LWc = 0.50 - 0.50 * cos(_LPIdl*_LPosU);
00211                                                 break;
00212                                         case WFIR_HAMMING:
00213                                                 _LWc = 0.54 - 0.46 * cos(_LPIdl*_LPosU);
00214                                                 break;
00215                                         case WFIR_BLACKMANEXACT:
00216                                                 _LWc = 0.42 - 0.50 * cos(_LPIdl*_LPosU) + 0.08 * cos(2.0*_LPIdl*_LPosU);
00217                                                 break;
00218                                         case WFIR_BLACKMAN3T61:
00219                                                 _LWc = 0.44959 - 0.49364 * cos(_LPIdl*_LPosU) + 0.05677 * cos(2.0*_LPIdl*_LPosU);
00220                                                 break;
00221                                         case WFIR_BLACKMAN3T67:
00222                                                 _LWc = 0.42323 - 0.49755 * cos(_LPIdl*_LPosU) + 0.07922 * cos(2.0*_LPIdl*_LPosU);
00223                                                 break;
00224                                         case WFIR_BLACKMAN4T92:
00225                                                 _LWc = 0.35875 - 0.48829 * cos(_LPIdl*_LPosU) + 0.14128 * cos(2.0*_LPIdl*_LPosU) - 0.01168 * cos(3.0*_LPIdl*_LPosU);
00226                                                 break;
00227                                         case WFIR_BLACKMAN4T74:
00228                                                 _LWc = 0.40217 - 0.49703 * cos(_LPIdl*_LPosU) + 0.09392 * cos(2.0*_LPIdl*_LPosU) - 0.00183 * cos(3.0*_LPIdl*_LPosU);
00229                                                 break;
00230                                         case WFIR_KAISER4T:
00231                                                 _LWc = 0.40243 - 0.49804 * cos(_LPIdl*_LPosU) + 0.09831 * cos(2.0*_LPIdl*_LPosU) - 0.00122 * cos(3.0*_LPIdl*_LPosU);
00232                                                 break;
00233                                         default:
00234                                                 _LWc = 1.0;
00235                                                 break;
00236                                 }
00237                                 _LPos    *= M_zPI;
00238                                 _LSi     = sin(_PCut*_LPos)/_LPos;
00239                         }
00240                         return (float)(_LWc*_LSi);
00241                 }
00242                 static signed short lut[WFIR_LUTLEN*WFIR_WIDTH];
00243 };
00244 
00245 signed short CzWINDOWEDFIR::lut[WFIR_LUTLEN*WFIR_WIDTH];
00246 
00247 CzWINDOWEDFIR::CzWINDOWEDFIR()
00248 {       int _LPcl;
00249         float _LPcllen  = (float)(1L<<WFIR_FRACBITS);   // number of precalculated lines for 0..1 (-1..0)
00250         float _LNorm    = 1.0f / (float)(2.0f * _LPcllen);
00251         float _LCut             = WFIR_CUTOFF;
00252         float _LScale   = (float)WFIR_QUANTSCALE;
00253         for( _LPcl=0;_LPcl<WFIR_LUTLEN;_LPcl++ )
00254         {       float _LGain,_LCoefs[WFIR_WIDTH];
00255                 float _LOfs             = ((float)_LPcl-_LPcllen)*_LNorm;
00256                 int _LCc,_LIdx  = _LPcl<<WFIR_LOG2WIDTH;
00257                 for( _LCc=0,_LGain=0.0f;_LCc<WFIR_WIDTH;_LCc++ )
00258                 {       _LGain  += (_LCoefs[_LCc] = coef( _LCc, _LOfs, _LCut, WFIR_WIDTH, WFIR_TYPE ));
00259                 }
00260                 _LGain = 1.0f/_LGain;
00261                 for( _LCc=0;_LCc<WFIR_WIDTH;_LCc++ )
00262                 {       float _LCoef = (float)floor( 0.5 + _LScale*_LCoefs[_LCc]*_LGain );
00263                         lut[_LIdx+_LCc] = (signed short)( (_LCoef<-_LScale)?-_LScale:((_LCoef>_LScale)?_LScale:_LCoef) );
00264                 }
00265         }
00266 }
00267 
00268 CzWINDOWEDFIR::~CzWINDOWEDFIR()
00269 {       // nothing todo
00270 }
00271 
00272 CzWINDOWEDFIR sfir;
00273 
00274 // ------------------------------------------------------------------------------------------------
00275 // MIXING MACROS
00276 // ------------------------------------------------------------------------------------------------
00278 // Mixing Macros
00279 
00280 #define SNDMIX_BEGINSAMPLELOOP8\
00281         register MODCHANNEL * const pChn = pChannel;\
00282         nPos = pChn->nPosLo;\
00283         const signed char *p = (signed char *)(pChn->pCurrentSample+pChn->nPos);\
00284         if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\
00285         int *pvol = pbuffer;\
00286         do {
00287 
00288 #define SNDMIX_BEGINSAMPLELOOP16\
00289         register MODCHANNEL * const pChn = pChannel;\
00290         nPos = pChn->nPosLo;\
00291         const signed short *p = (signed short *)(pChn->pCurrentSample+(pChn->nPos*2));\
00292         if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\
00293         int *pvol = pbuffer;\
00294         do {
00295 
00296 #define SNDMIX_ENDSAMPLELOOP\
00297                 nPos += pChn->nInc;\
00298         } while (pvol < pbufmax);\
00299         pChn->nPos += nPos >> 16;\
00300         pChn->nPosLo = nPos & 0xFFFF;
00301 
00302 #define SNDMIX_ENDSAMPLELOOP8   SNDMIX_ENDSAMPLELOOP
00303 #define SNDMIX_ENDSAMPLELOOP16  SNDMIX_ENDSAMPLELOOP
00304 
00306 // Mono
00307 
00308 // No interpolation
00309 #define SNDMIX_GETMONOVOL8NOIDO\
00310         int vol = p[nPos >> 16] << 8;
00311 
00312 #define SNDMIX_GETMONOVOL16NOIDO\
00313         int vol = p[nPos >> 16];
00314 
00315 // Linear Interpolation
00316 #define SNDMIX_GETMONOVOL8LINEAR\
00317         int poshi = nPos >> 16;\
00318         int poslo = (nPos >> 8) & 0xFF;\
00319         int srcvol = p[poshi];\
00320         int destvol = p[poshi+1];\
00321         int vol = (srcvol<<8) + ((int)(poslo * (destvol - srcvol)));
00322 
00323 #define SNDMIX_GETMONOVOL16LINEAR\
00324         int poshi = nPos >> 16;\
00325         int poslo = (nPos >> 8) & 0xFF;\
00326         int srcvol = p[poshi];\
00327         int destvol = p[poshi+1];\
00328         int vol = srcvol + ((int)(poslo * (destvol - srcvol)) >> 8);
00329 
00330 // spline interpolation (2 guard bits should be enough???)
00331 #define SPLINE_FRACSHIFT ((16-SPLINE_FRACBITS)-2)
00332 #define SPLINE_FRACMASK  (((1L<<(16-SPLINE_FRACSHIFT))-1)&~3)
00333 
00334 #define SNDMIX_GETMONOVOL8SPLINE \
00335         int poshi       = nPos >> 16; \
00336         int poslo       = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
00337         int vol         = (CzCUBICSPLINE::lut[poslo  ]*(int)p[poshi-1] + \
00338                        CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi  ] + \
00339                        CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \
00340                        CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_8SHIFT;
00341 
00342 #define SNDMIX_GETMONOVOL16SPLINE \
00343         int poshi       = nPos >> 16; \
00344         int poslo       = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
00345         int vol         = (CzCUBICSPLINE::lut[poslo  ]*(int)p[poshi-1] + \
00346                        CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi  ] + \
00347                        CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \
00348                        CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_16SHIFT;
00349 
00350 
00351 // fir interpolation
00352 #define WFIR_FRACSHIFT  (16-(WFIR_FRACBITS+1+WFIR_LOG2WIDTH))
00353 #define WFIR_FRACMASK   ((((1L<<(17-WFIR_FRACSHIFT))-1)&~((1L<<WFIR_LOG2WIDTH)-1)))
00354 #define WFIR_FRACHALVE  (1L<<(16-(WFIR_FRACBITS+2)))
00355 
00356 #define SNDMIX_GETMONOVOL8FIRFILTER \
00357         int poshi  = nPos >> 16;\
00358         int poslo  = (nPos & 0xFFFF);\
00359         int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
00360         int vol    = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]);  \
00361                 vol   += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]);      \
00362                 vol   += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]);      \
00363                 vol   += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]);      \
00364                 vol   += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]);      \
00365                 vol   += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]);      \
00366                 vol   += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]);      \
00367                 vol   += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]);      \
00368                 vol  >>= WFIR_8SHIFT;
00369 
00370 #define SNDMIX_GETMONOVOL16FIRFILTER \
00371         int poshi  = nPos >> 16;\
00372         int poslo  = (nPos & 0xFFFF);\
00373         int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
00374     int vol1   = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]);      \
00375                 vol1  += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]);      \
00376                 vol1  += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]);      \
00377                 vol1  += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]);      \
00378         int vol2   = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]);  \
00379                 vol2  += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]);      \
00380                 vol2  += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]);      \
00381                 vol2  += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]);      \
00382         int vol    = ((vol1>>1)+(vol2>>1)) >> (WFIR_16BITSHIFT-1);
00383 
00385 // Stereo
00386 
00387 // No interpolation
00388 #define SNDMIX_GETSTEREOVOL8NOIDO\
00389         int vol_l = p[(nPos>>16)*2] << 8;\
00390         int vol_r = p[(nPos>>16)*2+1] << 8;
00391 
00392 #define SNDMIX_GETSTEREOVOL16NOIDO\
00393         int vol_l = p[(nPos>>16)*2];\
00394         int vol_r = p[(nPos>>16)*2+1];
00395 
00396 // Linear Interpolation
00397 #define SNDMIX_GETSTEREOVOL8LINEAR\
00398         int poshi = nPos >> 16;\
00399         int poslo = (nPos >> 8) & 0xFF;\
00400         int srcvol_l = p[poshi*2];\
00401         int vol_l = (srcvol_l<<8) + ((int)(poslo * (p[poshi*2+2] - srcvol_l)));\
00402         int srcvol_r = p[poshi*2+1];\
00403         int vol_r = (srcvol_r<<8) + ((int)(poslo * (p[poshi*2+3] - srcvol_r)));
00404 
00405 #define SNDMIX_GETSTEREOVOL16LINEAR\
00406         int poshi = nPos >> 16;\
00407         int poslo = (nPos >> 8) & 0xFF;\
00408         int srcvol_l = p[poshi*2];\
00409         int vol_l = srcvol_l + ((int)(poslo * (p[poshi*2+2] - srcvol_l)) >> 8);\
00410         int srcvol_r = p[poshi*2+1];\
00411         int vol_r = srcvol_r + ((int)(poslo * (p[poshi*2+3] - srcvol_r)) >> 8);\
00412 
00413 // Spline Interpolation
00414 #define SNDMIX_GETSTEREOVOL8SPLINE \
00415         int poshi       = nPos >> 16; \
00416         int poslo       = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
00417         int vol_l       = (CzCUBICSPLINE::lut[poslo  ]*(int)p[(poshi-1)*2  ] + \
00418                        CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi  )*2  ] + \
00419                        CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2  ] + \
00420                        CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2  ]) >> SPLINE_8SHIFT; \
00421         int vol_r       = (CzCUBICSPLINE::lut[poslo  ]*(int)p[(poshi-1)*2+1] + \
00422                        CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi  )*2+1] + \
00423                        CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \
00424                        CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_8SHIFT;
00425 
00426 #define SNDMIX_GETSTEREOVOL16SPLINE \
00427         int poshi       = nPos >> 16; \
00428         int poslo       = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
00429         int vol_l       = (CzCUBICSPLINE::lut[poslo  ]*(int)p[(poshi-1)*2  ] + \
00430                        CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi  )*2  ] + \
00431                        CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2  ] + \
00432                        CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2  ]) >> SPLINE_16SHIFT; \
00433         int vol_r       = (CzCUBICSPLINE::lut[poslo  ]*(int)p[(poshi-1)*2+1] + \
00434                        CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi  )*2+1] + \
00435                        CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \
00436                        CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_16SHIFT;
00437 
00438 // fir interpolation
00439 #define SNDMIX_GETSTEREOVOL8FIRFILTER \
00440         int poshi   = nPos >> 16;\
00441         int poslo   = (nPos & 0xFFFF);\
00442         int firidx  = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
00443         int vol_l   = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2  ]);   \
00444                 vol_l  += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2  ]);       \
00445                 vol_l  += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2  ]);       \
00446                 vol_l  += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2  ]);       \
00447                 vol_l  += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2  ]);       \
00448                 vol_l  += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2  ]);       \
00449                 vol_l  += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2  ]);       \
00450                 vol_l  += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2  ]);       \
00451                 vol_l >>= WFIR_8SHIFT; \
00452         int vol_r   = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]);   \
00453                 vol_r  += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]);       \
00454                 vol_r  += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]);       \
00455                 vol_r  += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]);       \
00456                 vol_r  += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]);       \
00457                 vol_r  += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]);       \
00458                 vol_r  += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]);       \
00459                 vol_r  += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]);       \
00460                 vol_r >>= WFIR_8SHIFT;
00461                         
00462 #define SNDMIX_GETSTEREOVOL16FIRFILTER \
00463         int poshi   = nPos >> 16;\
00464         int poslo   = (nPos & 0xFFFF);\
00465         int firidx  = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
00466     int vol1_l  = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2  ]);       \
00467                 vol1_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2  ]);       \
00468                 vol1_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2  ]);       \
00469                 vol1_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2  ]);       \
00470         int vol2_l  = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2  ]);   \
00471                 vol2_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2  ]);       \
00472                 vol2_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2  ]);       \
00473                 vol2_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2  ]);       \
00474         int vol_l   = ((vol1_l>>1)+(vol2_l>>1)) >> (WFIR_16BITSHIFT-1); \
00475         int vol1_r  = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]);   \
00476                 vol1_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]);       \
00477                 vol1_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]);       \
00478                 vol1_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]);       \
00479         int vol2_r  = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]);   \
00480                 vol2_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]);       \
00481                 vol2_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]);       \
00482                 vol2_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]);       \
00483         int vol_r   = ((vol1_r>>1)+(vol2_r>>1)) >> (WFIR_16BITSHIFT-1);
00484 
00485 
00487 
00488 #define SNDMIX_STOREMONOVOL\
00489         pvol[0] += vol * pChn->nRightVol;\
00490         pvol[1] += vol * pChn->nLeftVol;\
00491         pvol += 2;
00492 
00493 #define SNDMIX_STORESTEREOVOL\
00494         pvol[0] += vol_l * pChn->nRightVol;\
00495         pvol[1] += vol_r * pChn->nLeftVol;\
00496         pvol += 2;
00497 
00498 #define SNDMIX_STOREFASTMONOVOL\
00499         int v = vol * pChn->nRightVol;\
00500         pvol[0] += v;\
00501         pvol[1] += v;\
00502         pvol += 2;
00503 
00504 #define SNDMIX_RAMPMONOVOL\
00505         nRampLeftVol += pChn->nLeftRamp;\
00506         nRampRightVol += pChn->nRightRamp;\
00507         pvol[0] += vol * (nRampRightVol >> VOLUMERAMPPRECISION);\
00508         pvol[1] += vol * (nRampLeftVol >> VOLUMERAMPPRECISION);\
00509         pvol += 2;
00510 
00511 #define SNDMIX_RAMPFASTMONOVOL\
00512         nRampRightVol += pChn->nRightRamp;\
00513         int fastvol = vol * (nRampRightVol >> VOLUMERAMPPRECISION);\
00514         pvol[0] += fastvol;\
00515         pvol[1] += fastvol;\
00516         pvol += 2;
00517 
00518 #define SNDMIX_RAMPSTEREOVOL\
00519         nRampLeftVol += pChn->nLeftRamp;\
00520         nRampRightVol += pChn->nRightRamp;\
00521         pvol[0] += vol_l * (nRampRightVol >> VOLUMERAMPPRECISION);\
00522         pvol[1] += vol_r * (nRampLeftVol >> VOLUMERAMPPRECISION);\
00523         pvol += 2;
00524 
00525 
00527 // Resonant Filters
00528 
00529 // Mono
00530 #define MIX_BEGIN_FILTER\
00531         int fy1 = pChannel->nFilter_Y1;\
00532         int fy2 = pChannel->nFilter_Y2;\
00533 
00534 #define MIX_END_FILTER\
00535         pChannel->nFilter_Y1 = fy1;\
00536         pChannel->nFilter_Y2 = fy2;
00537 
00538 #define SNDMIX_PROCESSFILTER\
00539         vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
00540         fy2 = fy1;\
00541         fy1 = vol;\
00542 
00543 // Stereo
00544 #define MIX_BEGIN_STEREO_FILTER\
00545         int fy1 = pChannel->nFilter_Y1;\
00546         int fy2 = pChannel->nFilter_Y2;\
00547         int fy3 = pChannel->nFilter_Y3;\
00548         int fy4 = pChannel->nFilter_Y4;\
00549 
00550 #define MIX_END_STEREO_FILTER\
00551         pChannel->nFilter_Y1 = fy1;\
00552         pChannel->nFilter_Y2 = fy2;\
00553         pChannel->nFilter_Y3 = fy3;\
00554         pChannel->nFilter_Y4 = fy4;\
00555 
00556 #define SNDMIX_PROCESSSTEREOFILTER\
00557         vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
00558         vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\
00559         fy2 = fy1; fy1 = vol_l;\
00560         fy4 = fy3; fy3 = vol_r;\
00561 
00562 
00563 // Interfaces
00564 
00565 typedef VOID (MPPASMCALL * LPMIXINTERFACE)(MODCHANNEL *, int *, int *);
00566 
00567 #define BEGIN_MIX_INTERFACE(func)\
00568         VOID MPPASMCALL func(MODCHANNEL *pChannel, int *pbuffer, int *pbufmax)\
00569         {\
00570                 LONG nPos;
00571 
00572 #define END_MIX_INTERFACE()\
00573                 SNDMIX_ENDSAMPLELOOP\
00574         }
00575 
00576 // Volume Ramps
00577 #define BEGIN_RAMPMIX_INTERFACE(func)\
00578         BEGIN_MIX_INTERFACE(func)\
00579                 LONG nRampRightVol = pChannel->nRampRightVol;\
00580                 LONG nRampLeftVol = pChannel->nRampLeftVol;
00581 
00582 #define END_RAMPMIX_INTERFACE()\
00583                 SNDMIX_ENDSAMPLELOOP\
00584                 pChannel->nRampRightVol = nRampRightVol;\
00585                 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
00586                 pChannel->nRampLeftVol = nRampLeftVol;\
00587                 pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
00588         }
00589 
00590 #define BEGIN_FASTRAMPMIX_INTERFACE(func)\
00591         BEGIN_MIX_INTERFACE(func)\
00592                 LONG nRampRightVol = pChannel->nRampRightVol;
00593 
00594 #define END_FASTRAMPMIX_INTERFACE()\
00595                 SNDMIX_ENDSAMPLELOOP\
00596                 pChannel->nRampRightVol = nRampRightVol;\
00597                 pChannel->nRampLeftVol = nRampRightVol;\
00598                 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
00599                 pChannel->nLeftVol = pChannel->nRightVol;\
00600         }
00601 
00602 
00603 // Mono Resonant Filters
00604 #define BEGIN_MIX_FLT_INTERFACE(func)\
00605         BEGIN_MIX_INTERFACE(func)\
00606         MIX_BEGIN_FILTER
00607         
00608 
00609 #define END_MIX_FLT_INTERFACE()\
00610         SNDMIX_ENDSAMPLELOOP\
00611         MIX_END_FILTER\
00612         }
00613 
00614 #define BEGIN_RAMPMIX_FLT_INTERFACE(func)\
00615         BEGIN_MIX_INTERFACE(func)\
00616                 LONG nRampRightVol = pChannel->nRampRightVol;\
00617                 LONG nRampLeftVol = pChannel->nRampLeftVol;\
00618                 MIX_BEGIN_FILTER
00619 
00620 #define END_RAMPMIX_FLT_INTERFACE()\
00621                 SNDMIX_ENDSAMPLELOOP\
00622                 MIX_END_FILTER\
00623                 pChannel->nRampRightVol = nRampRightVol;\
00624                 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
00625                 pChannel->nRampLeftVol = nRampLeftVol;\
00626                 pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
00627         }
00628 
00629 // Stereo Resonant Filters
00630 #define BEGIN_MIX_STFLT_INTERFACE(func)\
00631         BEGIN_MIX_INTERFACE(func)\
00632         MIX_BEGIN_STEREO_FILTER
00633         
00634 
00635 #define END_MIX_STFLT_INTERFACE()\
00636         SNDMIX_ENDSAMPLELOOP\
00637         MIX_END_STEREO_FILTER\
00638         }
00639 
00640 #define BEGIN_RAMPMIX_STFLT_INTERFACE(func)\
00641         BEGIN_MIX_INTERFACE(func)\
00642                 LONG nRampRightVol = pChannel->nRampRightVol;\
00643                 LONG nRampLeftVol = pChannel->nRampLeftVol;\
00644                 MIX_BEGIN_STEREO_FILTER
00645 
00646 #define END_RAMPMIX_STFLT_INTERFACE()\
00647                 SNDMIX_ENDSAMPLELOOP\
00648                 MIX_END_STEREO_FILTER\
00649                 pChannel->nRampRightVol = nRampRightVol;\
00650                 pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
00651                 pChannel->nRampLeftVol = nRampLeftVol;\
00652                 pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
00653         }
00654 
00655 
00657 //
00658 
00659 void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples);
00660 void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
00661 void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
00662 void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount);
00663 void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
00664 
00666 // Mono samples functions
00667 
00668 BEGIN_MIX_INTERFACE(Mono8BitMix)
00669         SNDMIX_BEGINSAMPLELOOP8
00670         SNDMIX_GETMONOVOL8NOIDO
00671         SNDMIX_STOREMONOVOL
00672 END_MIX_INTERFACE()
00673 
00674 BEGIN_MIX_INTERFACE(Mono16BitMix)
00675         SNDMIX_BEGINSAMPLELOOP16
00676         SNDMIX_GETMONOVOL16NOIDO
00677         SNDMIX_STOREMONOVOL
00678 END_MIX_INTERFACE()
00679 
00680 BEGIN_MIX_INTERFACE(Mono8BitLinearMix)
00681         SNDMIX_BEGINSAMPLELOOP8
00682         SNDMIX_GETMONOVOL8LINEAR
00683         SNDMIX_STOREMONOVOL
00684 END_MIX_INTERFACE()
00685 
00686 BEGIN_MIX_INTERFACE(Mono16BitLinearMix)
00687         SNDMIX_BEGINSAMPLELOOP16
00688         SNDMIX_GETMONOVOL16LINEAR
00689         SNDMIX_STOREMONOVOL
00690 END_MIX_INTERFACE()
00691 
00692 BEGIN_MIX_INTERFACE(Mono8BitSplineMix)
00693         SNDMIX_BEGINSAMPLELOOP8
00694         SNDMIX_GETMONOVOL8SPLINE
00695         SNDMIX_STOREMONOVOL
00696 END_MIX_INTERFACE()
00697 
00698 BEGIN_MIX_INTERFACE(Mono16BitSplineMix)
00699         SNDMIX_BEGINSAMPLELOOP16
00700         SNDMIX_GETMONOVOL16SPLINE
00701         SNDMIX_STOREMONOVOL
00702 END_MIX_INTERFACE()
00703 
00704 BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix)
00705         SNDMIX_BEGINSAMPLELOOP8
00706         SNDMIX_GETMONOVOL8FIRFILTER
00707         SNDMIX_STOREMONOVOL
00708 END_MIX_INTERFACE()
00709 
00710 BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix)
00711         SNDMIX_BEGINSAMPLELOOP16
00712         SNDMIX_GETMONOVOL16FIRFILTER
00713         SNDMIX_STOREMONOVOL
00714 END_MIX_INTERFACE()
00715 
00716 
00717 // Volume Ramps
00718 BEGIN_RAMPMIX_INTERFACE(Mono8BitRampMix)
00719         SNDMIX_BEGINSAMPLELOOP8
00720         SNDMIX_GETMONOVOL8NOIDO
00721         SNDMIX_RAMPMONOVOL
00722 END_RAMPMIX_INTERFACE()
00723 
00724 BEGIN_RAMPMIX_INTERFACE(Mono16BitRampMix)
00725         SNDMIX_BEGINSAMPLELOOP16
00726         SNDMIX_GETMONOVOL16NOIDO
00727         SNDMIX_RAMPMONOVOL
00728 END_RAMPMIX_INTERFACE()
00729 
00730 BEGIN_RAMPMIX_INTERFACE(Mono8BitLinearRampMix)
00731         SNDMIX_BEGINSAMPLELOOP8
00732         SNDMIX_GETMONOVOL8LINEAR
00733         SNDMIX_RAMPMONOVOL
00734 END_RAMPMIX_INTERFACE()
00735 
00736 BEGIN_RAMPMIX_INTERFACE(Mono16BitLinearRampMix)
00737         SNDMIX_BEGINSAMPLELOOP16
00738         SNDMIX_GETMONOVOL16LINEAR
00739         SNDMIX_RAMPMONOVOL
00740 END_RAMPMIX_INTERFACE()
00741 
00742 BEGIN_RAMPMIX_INTERFACE(Mono8BitSplineRampMix)
00743         SNDMIX_BEGINSAMPLELOOP8
00744         SNDMIX_GETMONOVOL8SPLINE
00745         SNDMIX_RAMPMONOVOL
00746 END_RAMPMIX_INTERFACE()
00747 
00748 BEGIN_RAMPMIX_INTERFACE(Mono16BitSplineRampMix)
00749         SNDMIX_BEGINSAMPLELOOP16
00750         SNDMIX_GETMONOVOL16SPLINE
00751         SNDMIX_RAMPMONOVOL
00752 END_RAMPMIX_INTERFACE()
00753 
00754 BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix)
00755         SNDMIX_BEGINSAMPLELOOP8
00756         SNDMIX_GETMONOVOL8FIRFILTER
00757         SNDMIX_RAMPMONOVOL
00758 END_RAMPMIX_INTERFACE()
00759 
00760 BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix)
00761         SNDMIX_BEGINSAMPLELOOP16
00762         SNDMIX_GETMONOVOL16FIRFILTER
00763         SNDMIX_RAMPMONOVOL
00764 END_RAMPMIX_INTERFACE()
00765 
00766 
00768 // Fast mono mix for leftvol=rightvol (1 less imul)
00769 
00770 BEGIN_MIX_INTERFACE(FastMono8BitMix)
00771         SNDMIX_BEGINSAMPLELOOP8
00772         SNDMIX_GETMONOVOL8NOIDO
00773         SNDMIX_STOREFASTMONOVOL
00774 END_MIX_INTERFACE()
00775 
00776 BEGIN_MIX_INTERFACE(FastMono16BitMix)
00777         SNDMIX_BEGINSAMPLELOOP16
00778         SNDMIX_GETMONOVOL16NOIDO
00779         SNDMIX_STOREFASTMONOVOL
00780 END_MIX_INTERFACE()
00781 
00782 BEGIN_MIX_INTERFACE(FastMono8BitLinearMix)
00783         SNDMIX_BEGINSAMPLELOOP8
00784         SNDMIX_GETMONOVOL8LINEAR
00785         SNDMIX_STOREFASTMONOVOL
00786 END_MIX_INTERFACE()
00787 
00788 BEGIN_MIX_INTERFACE(FastMono16BitLinearMix)
00789         SNDMIX_BEGINSAMPLELOOP16
00790         SNDMIX_GETMONOVOL16LINEAR
00791         SNDMIX_STOREFASTMONOVOL
00792 END_MIX_INTERFACE()
00793 
00794 BEGIN_MIX_INTERFACE(FastMono8BitSplineMix)
00795         SNDMIX_BEGINSAMPLELOOP8
00796         SNDMIX_GETMONOVOL8SPLINE
00797         SNDMIX_STOREFASTMONOVOL
00798 END_MIX_INTERFACE()
00799 
00800 BEGIN_MIX_INTERFACE(FastMono16BitSplineMix)
00801         SNDMIX_BEGINSAMPLELOOP16
00802         SNDMIX_GETMONOVOL16SPLINE
00803         SNDMIX_STOREFASTMONOVOL
00804 END_MIX_INTERFACE()
00805 
00806 BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix)
00807         SNDMIX_BEGINSAMPLELOOP8
00808         SNDMIX_GETMONOVOL8FIRFILTER
00809         SNDMIX_STOREFASTMONOVOL
00810 END_MIX_INTERFACE()
00811 
00812 BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix)
00813         SNDMIX_BEGINSAMPLELOOP16
00814         SNDMIX_GETMONOVOL16FIRFILTER
00815         SNDMIX_STOREFASTMONOVOL
00816 END_MIX_INTERFACE()
00817 
00818 
00819 // Fast Ramps
00820 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitRampMix)
00821         SNDMIX_BEGINSAMPLELOOP8
00822         SNDMIX_GETMONOVOL8NOIDO
00823         SNDMIX_RAMPFASTMONOVOL
00824 END_FASTRAMPMIX_INTERFACE()
00825 
00826 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitRampMix)
00827         SNDMIX_BEGINSAMPLELOOP16
00828         SNDMIX_GETMONOVOL16NOIDO
00829         SNDMIX_RAMPFASTMONOVOL
00830 END_FASTRAMPMIX_INTERFACE()
00831 
00832 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitLinearRampMix)
00833         SNDMIX_BEGINSAMPLELOOP8
00834         SNDMIX_GETMONOVOL8LINEAR
00835         SNDMIX_RAMPFASTMONOVOL
00836 END_FASTRAMPMIX_INTERFACE()
00837 
00838 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitLinearRampMix)
00839         SNDMIX_BEGINSAMPLELOOP16
00840         SNDMIX_GETMONOVOL16LINEAR
00841         SNDMIX_RAMPFASTMONOVOL
00842 END_FASTRAMPMIX_INTERFACE()
00843 
00844 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitSplineRampMix)
00845         SNDMIX_BEGINSAMPLELOOP8
00846         SNDMIX_GETMONOVOL8SPLINE
00847         SNDMIX_RAMPFASTMONOVOL
00848 END_FASTRAMPMIX_INTERFACE()
00849 
00850 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitSplineRampMix)
00851         SNDMIX_BEGINSAMPLELOOP16
00852         SNDMIX_GETMONOVOL16SPLINE
00853         SNDMIX_RAMPFASTMONOVOL
00854 END_FASTRAMPMIX_INTERFACE()
00855 
00856 BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix)
00857         SNDMIX_BEGINSAMPLELOOP8
00858         SNDMIX_GETMONOVOL8FIRFILTER
00859         SNDMIX_RAMPFASTMONOVOL
00860 END_FASTRAMPMIX_INTERFACE()
00861 
00862 BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix)
00863         SNDMIX_BEGINSAMPLELOOP16
00864         SNDMIX_GETMONOVOL16FIRFILTER
00865         SNDMIX_RAMPFASTMONOVOL
00866 END_FASTRAMPMIX_INTERFACE()
00867 
00868 
00870 // Stereo samples
00871 
00872 BEGIN_MIX_INTERFACE(Stereo8BitMix)
00873         SNDMIX_BEGINSAMPLELOOP8
00874         SNDMIX_GETSTEREOVOL8NOIDO
00875         SNDMIX_STORESTEREOVOL
00876 END_MIX_INTERFACE()
00877 
00878 BEGIN_MIX_INTERFACE(Stereo16BitMix)
00879         SNDMIX_BEGINSAMPLELOOP16
00880         SNDMIX_GETSTEREOVOL16NOIDO
00881         SNDMIX_STORESTEREOVOL
00882 END_MIX_INTERFACE()
00883 
00884 BEGIN_MIX_INTERFACE(Stereo8BitLinearMix)
00885         SNDMIX_BEGINSAMPLELOOP8
00886         SNDMIX_GETSTEREOVOL8LINEAR
00887         SNDMIX_STORESTEREOVOL
00888 END_MIX_INTERFACE()
00889 
00890 BEGIN_MIX_INTERFACE(Stereo16BitLinearMix)
00891         SNDMIX_BEGINSAMPLELOOP16
00892         SNDMIX_GETSTEREOVOL16LINEAR
00893         SNDMIX_STORESTEREOVOL
00894 END_MIX_INTERFACE()
00895 
00896 BEGIN_MIX_INTERFACE(Stereo8BitSplineMix)
00897         SNDMIX_BEGINSAMPLELOOP8
00898         SNDMIX_GETSTEREOVOL8SPLINE
00899         SNDMIX_STORESTEREOVOL
00900 END_MIX_INTERFACE()
00901 
00902 BEGIN_MIX_INTERFACE(Stereo16BitSplineMix)
00903         SNDMIX_BEGINSAMPLELOOP16
00904         SNDMIX_GETSTEREOVOL16SPLINE
00905         SNDMIX_STORESTEREOVOL
00906 END_MIX_INTERFACE()
00907 
00908 BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix)
00909         SNDMIX_BEGINSAMPLELOOP8
00910         SNDMIX_GETSTEREOVOL8FIRFILTER
00911         SNDMIX_STORESTEREOVOL
00912 END_MIX_INTERFACE()
00913 
00914 BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix)
00915         SNDMIX_BEGINSAMPLELOOP16
00916         SNDMIX_GETSTEREOVOL16FIRFILTER
00917         SNDMIX_STORESTEREOVOL
00918 END_MIX_INTERFACE()
00919 
00920 
00921 // Volume Ramps
00922 BEGIN_RAMPMIX_INTERFACE(Stereo8BitRampMix)
00923         SNDMIX_BEGINSAMPLELOOP8
00924         SNDMIX_GETSTEREOVOL8NOIDO
00925         SNDMIX_RAMPSTEREOVOL
00926 END_RAMPMIX_INTERFACE()
00927 
00928 BEGIN_RAMPMIX_INTERFACE(Stereo16BitRampMix)
00929         SNDMIX_BEGINSAMPLELOOP16
00930         SNDMIX_GETSTEREOVOL16NOIDO
00931         SNDMIX_RAMPSTEREOVOL
00932 END_RAMPMIX_INTERFACE()
00933 
00934 BEGIN_RAMPMIX_INTERFACE(Stereo8BitLinearRampMix)
00935         SNDMIX_BEGINSAMPLELOOP8
00936         SNDMIX_GETSTEREOVOL8LINEAR
00937         SNDMIX_RAMPSTEREOVOL
00938 END_RAMPMIX_INTERFACE()
00939 
00940 BEGIN_RAMPMIX_INTERFACE(Stereo16BitLinearRampMix)
00941         SNDMIX_BEGINSAMPLELOOP16
00942         SNDMIX_GETSTEREOVOL16LINEAR
00943         SNDMIX_RAMPSTEREOVOL
00944 END_RAMPMIX_INTERFACE()
00945 
00946 BEGIN_RAMPMIX_INTERFACE(Stereo8BitSplineRampMix)
00947         SNDMIX_BEGINSAMPLELOOP8
00948         SNDMIX_GETSTEREOVOL8SPLINE
00949         SNDMIX_RAMPSTEREOVOL
00950 END_RAMPMIX_INTERFACE()
00951 
00952 BEGIN_RAMPMIX_INTERFACE(Stereo16BitSplineRampMix)
00953         SNDMIX_BEGINSAMPLELOOP16
00954         SNDMIX_GETSTEREOVOL16SPLINE
00955         SNDMIX_RAMPSTEREOVOL
00956 END_RAMPMIX_INTERFACE()
00957 
00958 BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix)
00959         SNDMIX_BEGINSAMPLELOOP8
00960         SNDMIX_GETSTEREOVOL8FIRFILTER
00961         SNDMIX_RAMPSTEREOVOL
00962 END_RAMPMIX_INTERFACE()
00963 
00964 BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix)
00965         SNDMIX_BEGINSAMPLELOOP16
00966         SNDMIX_GETSTEREOVOL16FIRFILTER
00967         SNDMIX_RAMPSTEREOVOL
00968 END_RAMPMIX_INTERFACE()
00969 
00970 
00971 
00973 // Resonant Filter Mix
00974 
00975 #ifndef NO_FILTER
00976 
00977 // Mono Filter Mix
00978 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitMix)
00979         SNDMIX_BEGINSAMPLELOOP8
00980         SNDMIX_GETMONOVOL8NOIDO
00981         SNDMIX_PROCESSFILTER
00982         SNDMIX_STOREMONOVOL
00983 END_MIX_FLT_INTERFACE()
00984 
00985 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitMix)
00986         SNDMIX_BEGINSAMPLELOOP16
00987         SNDMIX_GETMONOVOL16NOIDO
00988         SNDMIX_PROCESSFILTER
00989         SNDMIX_STOREMONOVOL
00990 END_MIX_FLT_INTERFACE()
00991 
00992 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitLinearMix)
00993         SNDMIX_BEGINSAMPLELOOP8
00994         SNDMIX_GETMONOVOL8LINEAR
00995         SNDMIX_PROCESSFILTER
00996         SNDMIX_STOREMONOVOL
00997 END_MIX_FLT_INTERFACE()
00998 
00999 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitLinearMix)
01000         SNDMIX_BEGINSAMPLELOOP16
01001         SNDMIX_GETMONOVOL16LINEAR
01002         SNDMIX_PROCESSFILTER
01003         SNDMIX_STOREMONOVOL
01004 END_MIX_FLT_INTERFACE()
01005 
01006 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitSplineMix)
01007         SNDMIX_BEGINSAMPLELOOP8
01008         SNDMIX_GETMONOVOL8SPLINE
01009         SNDMIX_PROCESSFILTER
01010         SNDMIX_STOREMONOVOL
01011 END_MIX_FLT_INTERFACE()
01012 
01013 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitSplineMix)
01014         SNDMIX_BEGINSAMPLELOOP16
01015         SNDMIX_GETMONOVOL16SPLINE
01016         SNDMIX_PROCESSFILTER
01017         SNDMIX_STOREMONOVOL
01018 END_MIX_FLT_INTERFACE()
01019 
01020 BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix)
01021         SNDMIX_BEGINSAMPLELOOP8
01022         SNDMIX_GETMONOVOL8FIRFILTER
01023         SNDMIX_PROCESSFILTER
01024         SNDMIX_STOREMONOVOL
01025 END_MIX_FLT_INTERFACE()
01026 
01027 BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix)
01028         SNDMIX_BEGINSAMPLELOOP16
01029         SNDMIX_GETMONOVOL16FIRFILTER
01030         SNDMIX_PROCESSFILTER
01031         SNDMIX_STOREMONOVOL
01032 END_MIX_FLT_INTERFACE()
01033 
01034 // Filter + Ramp
01035 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitRampMix)
01036         SNDMIX_BEGINSAMPLELOOP8
01037         SNDMIX_GETMONOVOL8NOIDO
01038         SNDMIX_PROCESSFILTER
01039         SNDMIX_RAMPMONOVOL
01040 END_RAMPMIX_FLT_INTERFACE()
01041 
01042 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitRampMix)
01043         SNDMIX_BEGINSAMPLELOOP16
01044         SNDMIX_GETMONOVOL16NOIDO
01045         SNDMIX_PROCESSFILTER
01046         SNDMIX_RAMPMONOVOL
01047 END_RAMPMIX_FLT_INTERFACE()
01048 
01049 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitLinearRampMix)
01050         SNDMIX_BEGINSAMPLELOOP8
01051         SNDMIX_GETMONOVOL8LINEAR
01052         SNDMIX_PROCESSFILTER
01053         SNDMIX_RAMPMONOVOL
01054 END_RAMPMIX_FLT_INTERFACE()
01055 
01056 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitLinearRampMix)
01057         SNDMIX_BEGINSAMPLELOOP16
01058         SNDMIX_GETMONOVOL16LINEAR
01059         SNDMIX_PROCESSFILTER
01060         SNDMIX_RAMPMONOVOL
01061 END_RAMPMIX_FLT_INTERFACE()
01062 
01063 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitSplineRampMix)
01064         SNDMIX_BEGINSAMPLELOOP8
01065         SNDMIX_GETMONOVOL8SPLINE
01066         SNDMIX_PROCESSFILTER
01067         SNDMIX_RAMPMONOVOL
01068 END_RAMPMIX_FLT_INTERFACE()
01069 
01070 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitSplineRampMix)
01071         SNDMIX_BEGINSAMPLELOOP16
01072         SNDMIX_GETMONOVOL16SPLINE
01073         SNDMIX_PROCESSFILTER
01074         SNDMIX_RAMPMONOVOL
01075 END_RAMPMIX_FLT_INTERFACE()
01076 
01077 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix)
01078         SNDMIX_BEGINSAMPLELOOP8
01079         SNDMIX_GETMONOVOL8FIRFILTER
01080         SNDMIX_PROCESSFILTER
01081         SNDMIX_RAMPMONOVOL
01082 END_RAMPMIX_FLT_INTERFACE()
01083 
01084 BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix)
01085         SNDMIX_BEGINSAMPLELOOP16
01086         SNDMIX_GETMONOVOL16FIRFILTER
01087         SNDMIX_PROCESSFILTER
01088         SNDMIX_RAMPMONOVOL
01089 END_RAMPMIX_FLT_INTERFACE()
01090 
01091 
01092 // Stereo Filter Mix
01093 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitMix)
01094         SNDMIX_BEGINSAMPLELOOP8
01095         SNDMIX_GETSTEREOVOL8NOIDO
01096         SNDMIX_PROCESSSTEREOFILTER
01097         SNDMIX_STORESTEREOVOL
01098 END_MIX_STFLT_INTERFACE()
01099 
01100 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitMix)
01101         SNDMIX_BEGINSAMPLELOOP16
01102         SNDMIX_GETSTEREOVOL16NOIDO
01103         SNDMIX_PROCESSSTEREOFILTER
01104         SNDMIX_STORESTEREOVOL
01105 END_MIX_STFLT_INTERFACE()
01106 
01107 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitLinearMix)
01108         SNDMIX_BEGINSAMPLELOOP8
01109         SNDMIX_GETSTEREOVOL8LINEAR
01110         SNDMIX_PROCESSSTEREOFILTER
01111         SNDMIX_STORESTEREOVOL
01112 END_MIX_STFLT_INTERFACE()
01113 
01114 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitLinearMix)
01115         SNDMIX_BEGINSAMPLELOOP16
01116         SNDMIX_GETSTEREOVOL16LINEAR
01117         SNDMIX_PROCESSSTEREOFILTER
01118         SNDMIX_STORESTEREOVOL
01119 END_MIX_STFLT_INTERFACE()
01120 
01121 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitSplineMix)
01122         SNDMIX_BEGINSAMPLELOOP8
01123         SNDMIX_GETSTEREOVOL8SPLINE
01124         SNDMIX_PROCESSSTEREOFILTER
01125         SNDMIX_STORESTEREOVOL
01126 END_MIX_STFLT_INTERFACE()
01127 
01128 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitSplineMix)
01129         SNDMIX_BEGINSAMPLELOOP16
01130         SNDMIX_GETSTEREOVOL16SPLINE
01131         SNDMIX_PROCESSSTEREOFILTER
01132         SNDMIX_STORESTEREOVOL
01133 END_MIX_STFLT_INTERFACE()
01134 
01135 BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix)
01136         SNDMIX_BEGINSAMPLELOOP8
01137         SNDMIX_GETSTEREOVOL8FIRFILTER
01138         SNDMIX_PROCESSSTEREOFILTER
01139         SNDMIX_STORESTEREOVOL
01140 END_MIX_STFLT_INTERFACE()
01141 
01142 BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix)
01143         SNDMIX_BEGINSAMPLELOOP16
01144         SNDMIX_GETSTEREOVOL16FIRFILTER
01145         SNDMIX_PROCESSSTEREOFILTER
01146         SNDMIX_STORESTEREOVOL
01147 END_MIX_STFLT_INTERFACE()
01148 
01149 // Stereo Filter + Ramp
01150 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitRampMix)
01151         SNDMIX_BEGINSAMPLELOOP8
01152         SNDMIX_GETSTEREOVOL8NOIDO
01153         SNDMIX_PROCESSSTEREOFILTER
01154         SNDMIX_RAMPSTEREOVOL
01155 END_RAMPMIX_STFLT_INTERFACE()
01156 
01157 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitRampMix)
01158         SNDMIX_BEGINSAMPLELOOP16
01159         SNDMIX_GETSTEREOVOL16NOIDO
01160         SNDMIX_PROCESSSTEREOFILTER
01161         SNDMIX_RAMPSTEREOVOL
01162 END_RAMPMIX_STFLT_INTERFACE()
01163 
01164 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitLinearRampMix)
01165         SNDMIX_BEGINSAMPLELOOP8
01166         SNDMIX_GETSTEREOVOL8LINEAR
01167         SNDMIX_PROCESSSTEREOFILTER
01168         SNDMIX_RAMPSTEREOVOL
01169 END_RAMPMIX_STFLT_INTERFACE()
01170 
01171 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitLinearRampMix)
01172         SNDMIX_BEGINSAMPLELOOP16
01173         SNDMIX_GETSTEREOVOL16LINEAR
01174         SNDMIX_PROCESSSTEREOFILTER
01175         SNDMIX_RAMPSTEREOVOL
01176 END_RAMPMIX_STFLT_INTERFACE()
01177 
01178 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitSplineRampMix)
01179         SNDMIX_BEGINSAMPLELOOP8
01180         SNDMIX_GETSTEREOVOL8SPLINE
01181         SNDMIX_PROCESSSTEREOFILTER
01182         SNDMIX_RAMPSTEREOVOL
01183 END_RAMPMIX_STFLT_INTERFACE()
01184 
01185 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitSplineRampMix)
01186         SNDMIX_BEGINSAMPLELOOP16
01187         SNDMIX_GETSTEREOVOL16SPLINE
01188         SNDMIX_PROCESSSTEREOFILTER
01189         SNDMIX_RAMPSTEREOVOL
01190 END_RAMPMIX_STFLT_INTERFACE()
01191 
01192 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix)
01193         SNDMIX_BEGINSAMPLELOOP8
01194         SNDMIX_GETSTEREOVOL8FIRFILTER
01195         SNDMIX_PROCESSSTEREOFILTER
01196         SNDMIX_RAMPSTEREOVOL
01197 END_RAMPMIX_STFLT_INTERFACE()
01198 
01199 BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix)
01200         SNDMIX_BEGINSAMPLELOOP16
01201         SNDMIX_GETSTEREOVOL16FIRFILTER
01202         SNDMIX_PROCESSSTEREOFILTER
01203         SNDMIX_RAMPSTEREOVOL
01204 END_RAMPMIX_STFLT_INTERFACE()
01205 
01206 
01207 #else
01208 // Mono
01209 #define FilterMono8BitMix                                       Mono8BitMix
01210 #define FilterMono16BitMix                                      Mono16BitMix
01211 #define FilterMono8BitLinearMix                         Mono8BitLinearMix
01212 #define FilterMono16BitLinearMix                        Mono16BitLinearMix
01213 #define FilterMono8BitSplineMix                         Mono8BitSplineMix
01214 #define FilterMono16BitSplineMix                        Mono16BitSplineMix
01215 #define FilterMono8BitFirFilterMix                      Mono8BitFirFilterMix
01216 #define FilterMono16BitFirFilterMix                     Mono16BitFirFilterMix
01217 #define FilterMono8BitRampMix                           Mono8BitRampMix
01218 #define FilterMono16BitRampMix                          Mono16BitRampMix
01219 #define FilterMono8BitLinearRampMix                     Mono8BitLinearRampMix
01220 #define FilterMono16BitLinearRampMix            Mono16BitLinearRampMix
01221 #define FilterMono8BitSplineRampMix                     Mono8BitSplineRampMix
01222 #define FilterMono16BitSplineRampMix            Mono16BitSplineRampMix
01223 #define FilterMono8BitFirFilterRampMix          Mono8BitFirFilterRampMix
01224 #define FilterMono16BitFirFilterRampMix         Mono16BitFirFilterRampMix
01225 // Stereo
01226 #define FilterStereo8BitMix                                     Stereo8BitMix
01227 #define FilterStereo16BitMix                            Stereo16BitMix
01228 #define FilterStereo8BitLinearMix                       Stereo8BitLinearMix
01229 #define FilterStereo16BitLinearMix                      Stereo16BitLinearMix
01230 #define FilterStereo8BitSplineMix                       Stereo8BitSplineMix
01231 #define FilterStereo16BitSplineMix                      Stereo16BitSplineMix
01232 #define FilterStereo8BitFirFilterMix            Stereo8BitFirFilterMix
01233 #define FilterStereo16BitFirFilterMix           Stereo16BitFirFilterMix
01234 #define FilterStereo8BitRampMix                         Stereo8BitRampMix
01235 #define FilterStereo16BitRampMix                        Stereo16BitRampMix
01236 #define FilterStereo8BitLinearRampMix           Stereo8BitLinearRampMix
01237 #define FilterStereo16BitLinearRampMix          Stereo16BitLinearRampMix
01238 #define FilterStereo8BitSplineRampMix           Stereo8BitSplineRampMix
01239 #define FilterStereo16BitSplineRampMix          Stereo16BitSplineRampMix
01240 #define FilterStereo8BitFirFilterRampMix        Stereo8BitFirFilterRampMix
01241 #define FilterStereo16BitFirFilterRampMix       Stereo16BitFirFilterRampMix
01242 
01243 #endif
01244 
01246 //
01247 // Mix function tables
01248 //
01249 //
01250 // Index is as follow:
01251 //      [b1-b0] format (8-bit-mono, 16-bit-mono, 8-bit-stereo, 16-bit-stereo)
01252 //      [b2]    ramp
01253 //      [b3]    filter
01254 //      [b5-b4] src type
01255 //
01256 
01257 #define MIXNDX_16BIT            0x01
01258 #define MIXNDX_STEREO           0x02
01259 #define MIXNDX_RAMP                     0x04
01260 #define MIXNDX_FILTER           0x08
01261 #define MIXNDX_LINEARSRC        0x10
01262 #define MIXNDX_SPLINESRC    0x20
01263 #define MIXNDX_FIRSRC           0x30
01264 
01265 const LPMIXINTERFACE gpMixFunctionTable[2*2*16] =
01266 {
01267         // No SRC
01268         Mono8BitMix,                            Mono16BitMix,                           Stereo8BitMix,                  Stereo16BitMix,
01269         Mono8BitRampMix,                        Mono16BitRampMix,                       Stereo8BitRampMix,              Stereo16BitRampMix,
01270         // No SRC, Filter
01271         FilterMono8BitMix,                      FilterMono16BitMix,                     FilterStereo8BitMix,    FilterStereo16BitMix,
01272         FilterMono8BitRampMix,          FilterMono16BitRampMix,         FilterStereo8BitRampMix,FilterStereo16BitRampMix,
01273         // Linear SRC
01274         Mono8BitLinearMix,                      Mono16BitLinearMix,                     Stereo8BitLinearMix,    Stereo16BitLinearMix,
01275         Mono8BitLinearRampMix,          Mono16BitLinearRampMix,         Stereo8BitLinearRampMix,Stereo16BitLinearRampMix,
01276         // Linear SRC, Filter
01277         FilterMono8BitLinearMix,        FilterMono16BitLinearMix,       FilterStereo8BitLinearMix,      FilterStereo16BitLinearMix,
01278         FilterMono8BitLinearRampMix,FilterMono16BitLinearRampMix,FilterStereo8BitLinearRampMix,FilterStereo16BitLinearRampMix,
01279 
01280         // FirFilter SRC
01281         Mono8BitSplineMix,                      Mono16BitSplineMix,                     Stereo8BitSplineMix,    Stereo16BitSplineMix,
01282         Mono8BitSplineRampMix,          Mono16BitSplineRampMix,         Stereo8BitSplineRampMix,Stereo16BitSplineRampMix,
01283         // Spline SRC, Filter
01284         FilterMono8BitSplineMix,        FilterMono16BitSplineMix,       FilterStereo8BitSplineMix,      FilterStereo16BitSplineMix,
01285         FilterMono8BitSplineRampMix,FilterMono16BitSplineRampMix,FilterStereo8BitSplineRampMix,FilterStereo16BitSplineRampMix,
01286         
01287         // FirFilter  SRC
01288         Mono8BitFirFilterMix,                   Mono16BitFirFilterMix,                  Stereo8BitFirFilterMix, Stereo16BitFirFilterMix,
01289         Mono8BitFirFilterRampMix,               Mono16BitFirFilterRampMix,              Stereo8BitFirFilterRampMix,Stereo16BitFirFilterRampMix,
01290         // FirFilter  SRC, Filter
01291         FilterMono8BitFirFilterMix,     FilterMono16BitFirFilterMix,    FilterStereo8BitFirFilterMix,   FilterStereo16BitFirFilterMix,
01292         FilterMono8BitFirFilterRampMix,FilterMono16BitFirFilterRampMix,FilterStereo8BitFirFilterRampMix,FilterStereo16BitFirFilterRampMix
01293 };
01294 
01295 const LPMIXINTERFACE gpFastMixFunctionTable[2*2*16] =
01296 {
01297         // No SRC
01298         FastMono8BitMix,                        FastMono16BitMix,                       Stereo8BitMix,                  Stereo16BitMix,
01299         FastMono8BitRampMix,            FastMono16BitRampMix,           Stereo8BitRampMix,              Stereo16BitRampMix,
01300         // No SRC, Filter
01301         FilterMono8BitMix,                      FilterMono16BitMix,                     FilterStereo8BitMix,    FilterStereo16BitMix,
01302         FilterMono8BitRampMix,          FilterMono16BitRampMix,         FilterStereo8BitRampMix,FilterStereo16BitRampMix,
01303         // Linear SRC
01304         FastMono8BitLinearMix,          FastMono16BitLinearMix,         Stereo8BitLinearMix,    Stereo16BitLinearMix,
01305         FastMono8BitLinearRampMix,      FastMono16BitLinearRampMix,     Stereo8BitLinearRampMix,Stereo16BitLinearRampMix,
01306         // Linear SRC, Filter
01307         FilterMono8BitLinearMix,        FilterMono16BitLinearMix,       FilterStereo8BitLinearMix,      FilterStereo16BitLinearMix,
01308         FilterMono8BitLinearRampMix,FilterMono16BitLinearRampMix,FilterStereo8BitLinearRampMix,FilterStereo16BitLinearRampMix,
01309         
01310         // Spline SRC
01311         Mono8BitSplineMix,              Mono16BitSplineMix,             Stereo8BitSplineMix,    Stereo16BitSplineMix,
01312         Mono8BitSplineRampMix,  Mono16BitSplineRampMix, Stereo8BitSplineRampMix,Stereo16BitSplineRampMix,
01313         // Spline SRC, Filter
01314         FilterMono8BitSplineMix,        FilterMono16BitSplineMix,       FilterStereo8BitSplineMix,      FilterStereo16BitSplineMix,
01315         FilterMono8BitSplineRampMix,FilterMono16BitSplineRampMix,FilterStereo8BitSplineRampMix,FilterStereo16BitSplineRampMix,
01316         
01317         // FirFilter SRC
01318         Mono8BitFirFilterMix,           Mono16BitFirFilterMix,          Stereo8BitFirFilterMix, Stereo16BitFirFilterMix,
01319         Mono8BitFirFilterRampMix,       Mono16BitFirFilterRampMix,      Stereo8BitFirFilterRampMix,Stereo16BitFirFilterRampMix,
01320         // FirFilter SRC, Filter
01321         FilterMono8BitFirFilterMix,     FilterMono16BitFirFilterMix,    FilterStereo8BitFirFilterMix,   FilterStereo16BitFirFilterMix,
01322         FilterMono8BitFirFilterRampMix,FilterMono16BitFirFilterRampMix,FilterStereo8BitFirFilterRampMix,FilterStereo16BitFirFilterRampMix,
01323 };
01324 
01325 
01327 
01328 static LONG MPPFASTCALL GetSampleCount(MODCHANNEL *pChn, LONG nSamples)
01329 //---------------------------------------------------------------------
01330 {
01331         LONG nLoopStart = (pChn->dwFlags & CHN_LOOP) ? pChn->nLoopStart : 0;
01332         LONG nInc = pChn->nInc;
01333 
01334         if ((nSamples <= 0) || (!nInc) || (!pChn->nLength)) return 0;
01335         // Under zero ?
01336         if ((LONG)pChn->nPos < nLoopStart)
01337         {
01338                 if (nInc < 0)
01339                 {
01340                         // Invert loop for bidi loops
01341                         LONG nDelta = ((nLoopStart - pChn->nPos) << 16) - (pChn->nPosLo & 0xffff);
01342                         pChn->nPos = nLoopStart | (nDelta>>16);
01343                         pChn->nPosLo = nDelta & 0xffff;
01344                         if (((LONG)pChn->nPos < nLoopStart) || (pChn->nPos >= (nLoopStart+pChn->nLength)/2))
01345                         {
01346                                 pChn->nPos = nLoopStart; pChn->nPosLo = 0;
01347                         }
01348                         nInc = -nInc;
01349                         pChn->nInc = nInc;
01350                         pChn->dwFlags &= ~(CHN_PINGPONGFLAG); // go forward
01351                         if ((!(pChn->dwFlags & CHN_LOOP)) || (pChn->nPos >= pChn->nLength))
01352                         {
01353                                 pChn->nPos = pChn->nLength;
01354                                 pChn->nPosLo = 0;
01355                                 return 0;
01356                         }
01357                 } else
01358                 {
01359                         // We probably didn't hit the loop end yet (first loop), so we do nothing
01360                         if ((LONG)pChn->nPos < 0) pChn->nPos = 0;
01361                 }
01362         } else
01363         // Past the end
01364         if (pChn->nPos >= pChn->nLength)
01365         {
01366                 if (!(pChn->dwFlags & CHN_LOOP)) return 0; // not looping -> stop this channel
01367                 if (pChn->dwFlags & CHN_PINGPONGLOOP)
01368                 {
01369                         // Invert loop
01370                         if (nInc > 0)
01371                         {
01372                                 nInc = -nInc;
01373                                 pChn->nInc = nInc;
01374                         }
01375                         pChn->dwFlags |= CHN_PINGPONGFLAG;
01376                         // adjust loop position
01377                         LONG nDeltaHi = (pChn->nPos - pChn->nLength);
01378                         LONG nDeltaLo = 0x10000 - (pChn->nPosLo & 0xffff);
01379                         pChn->nPos = pChn->nLength - nDeltaHi - (nDeltaLo>>16);
01380                         pChn->nPosLo = nDeltaLo & 0xffff;
01381                         if ((pChn->nPos <= pChn->nLoopStart) || (pChn->nPos >= pChn->nLength)) pChn->nPos = pChn->nLength-1;
01382                 } else
01383                 {
01384                         if (nInc < 0) // This is a bug
01385                         {
01386                                 nInc = -nInc;
01387                                 pChn->nInc = nInc;
01388                         }
01389                         // Restart at loop start
01390                         pChn->nPos += nLoopStart - pChn->nLength;
01391                         if ((LONG)pChn->nPos < nLoopStart) pChn->nPos = pChn->nLoopStart;
01392                 }
01393         }
01394         LONG nPos = pChn->nPos;
01395         // too big increment, and/or too small loop length
01396         if (nPos < nLoopStart)
01397         {
01398                 if ((nPos < 0) || (nInc < 0)) return 0;
01399         }
01400         if ((nPos < 0) || (nPos >= (LONG)pChn->nLength)) return 0;
01401         LONG nPosLo = (USHORT)pChn->nPosLo, nSmpCount = nSamples;
01402         if (nInc < 0)
01403         {
01404                 LONG nInv = -nInc;
01405                 LONG maxsamples = 16384 / ((nInv>>16)+1);
01406                 if (maxsamples < 2) maxsamples = 2;
01407                 if (nSamples > maxsamples) nSamples = maxsamples;
01408                 LONG nDeltaHi = (nInv>>16) * (nSamples - 1);
01409                 LONG nDeltaLo = (nInv&0xffff) * (nSamples - 1);
01410                 LONG nPosDest = nPos - nDeltaHi + ((nPosLo - nDeltaLo) >> 16);
01411                 if (nPosDest < nLoopStart)
01412                 {
01413                         nSmpCount = (ULONG)(((((LONGLONG)nPos - nLoopStart) << 16) + nPosLo - 1) / nInv) + 1;
01414                 }
01415         } else
01416         {
01417                 LONG maxsamples = 16384 / ((nInc>>16)+1);
01418                 if (maxsamples < 2) maxsamples = 2;
01419                 if (nSamples > maxsamples) nSamples = maxsamples;
01420                 LONG nDeltaHi = (nInc>>16) * (nSamples - 1);
01421                 LONG nDeltaLo = (nInc&0xffff) * (nSamples - 1);
01422                 LONG nPosDest = nPos + nDeltaHi + ((nPosLo + nDeltaLo)>>16);
01423                 if (nPosDest >= (LONG)pChn->nLength)
01424                 {
01425                         nSmpCount = (ULONG)(((((LONGLONG)pChn->nLength - nPos) << 16) - nPosLo - 1) / nInc) + 1;
01426                 }
01427         }
01428         if (nSmpCount <= 1) return 1;
01429         if (nSmpCount > nSamples) return nSamples;
01430         return nSmpCount;
01431 }
01432 
01433 
01434 UINT CSoundFile::CreateStereoMix(int count)
01435 //-----------------------------------------
01436 {
01437         LPLONG pOfsL, pOfsR;
01438         DWORD nchused, nchmixed;
01439 
01440         if (!count) return 0;
01441 #ifndef FASTSOUNDLIB
01442         if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2);
01443 #endif
01444         nchused = nchmixed = 0;
01445         for (UINT nChn=0; nChn<m_nMixChannels; nChn++)
01446         {
01447                 const LPMIXINTERFACE *pMixFuncTable;
01448                 MODCHANNEL * const pChannel = &Chn[ChnMix[nChn]];
01449                 UINT nFlags, nMasterCh;
01450                 LONG nSmpCount;
01451                 int nsamples;
01452                 int *pbuffer;
01453 
01454                 if (!pChannel->pCurrentSample) continue;
01455                 nMasterCh = (ChnMix[nChn] < m_nChannels) ? ChnMix[nChn]+1 : pChannel->nMasterChn;
01456                 pOfsR = &gnDryROfsVol;
01457                 pOfsL = &gnDryLOfsVol;
01458                 nFlags = 0;
01459                 if (pChannel->dwFlags & CHN_16BIT) nFlags |= MIXNDX_16BIT;
01460                 if (pChannel->dwFlags & CHN_STEREO) nFlags |= MIXNDX_STEREO;
01461         #ifndef NO_FILTER
01462                 if (pChannel->dwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER;
01463         #endif
01464                 if (!(pChannel->dwFlags & CHN_NOIDO))
01465                 {
01466                         // use hq-fir mixer?
01467                         if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) )
01468                                 nFlags += MIXNDX_FIRSRC;
01469                         else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER )
01470                                 nFlags += MIXNDX_SPLINESRC;
01471                         else
01472                                 nFlags += MIXNDX_LINEARSRC; // use 
01473                 }
01474                 if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol)
01475                  && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp)))
01476                 {
01477                         pMixFuncTable = gpFastMixFunctionTable;
01478                 } else
01479                 {
01480                         pMixFuncTable = gpMixFunctionTable;
01481                 }
01482                 nsamples = count;
01483 #ifndef NO_REVERB
01484                 pbuffer = (gdwSoundSetup & SNDMIX_REVERB) ? MixReverbBuffer : MixSoundBuffer;
01485                 if (pChannel->dwFlags & CHN_NOREVERB) pbuffer = MixSoundBuffer;
01486                 if (pChannel->dwFlags & CHN_REVERB) pbuffer = MixReverbBuffer;
01487                 if (pbuffer == MixReverbBuffer)
01488                 {
01489                         if (!gnReverbSend) memset(MixReverbBuffer, 0, count * 8);
01490                         gnReverbSend += count;
01491                 }
01492 #else
01493                 pbuffer = MixSoundBuffer;
01494 #endif
01495                 nchused++;
01497         SampleLooping:
01498                 UINT nrampsamples = nsamples;
01499                 if (pChannel->nRampLength > 0)
01500                 {
01501                         if ((LONG)nrampsamples > pChannel->nRampLength) nrampsamples = pChannel->nRampLength;
01502                 }
01503                 if ((nSmpCount = GetSampleCount(pChannel, nrampsamples)) <= 0)
01504                 {
01505                         // Stopping the channel
01506                         pChannel->pCurrentSample = NULL;
01507                         pChannel->nLength = 0;
01508                         pChannel->nPos = 0;
01509                         pChannel->nPosLo = 0;
01510                         pChannel->nRampLength = 0;
01511                         X86_EndChannelOfs(pChannel, pbuffer, nsamples);
01512                         *pOfsR += pChannel->nROfs;
01513                         *pOfsL += pChannel->nLOfs;
01514                         pChannel->nROfs = pChannel->nLOfs = 0;
01515                         pChannel->dwFlags &= ~CHN_PINGPONGFLAG;
01516                         continue;
01517                 }
01518                 // Should we mix this channel ?
01519                 UINT naddmix;
01520                 if (((nchmixed >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)))
01521                  || ((!pChannel->nRampLength) && (!(pChannel->nLeftVol|pChannel->nRightVol))))
01522                 {
01523                         LONG delta = (pChannel->nInc * (LONG)nSmpCount) + (LONG)pChannel->nPosLo;
01524                         pChannel->nPosLo = delta & 0xFFFF;
01525                         pChannel->nPos += (delta >> 16);
01526                         pChannel->nROfs = pChannel->nLOfs = 0;
01527                         pbuffer += nSmpCount*2;
01528                         naddmix = 0;
01529                 } else
01530                 // Do mixing
01531                 {
01532                         // Choose function for mixing
01533                         LPMIXINTERFACE pMixFunc;
01534                         pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags];
01535                         int *pbufmax = pbuffer + (nSmpCount*2);
01536                         pChannel->nROfs = - *(pbufmax-2);
01537                         pChannel->nLOfs = - *(pbufmax-1);
01538                         pMixFunc(pChannel, pbuffer, pbufmax);
01539                         pChannel->nROfs += *(pbufmax-2);
01540                         pChannel->nLOfs += *(pbufmax-1);
01541                         pbuffer = pbufmax;
01542                         naddmix = 1;
01543 
01544                 }
01545                 nsamples -= nSmpCount;
01546                 if (pChannel->nRampLength)
01547                 {
01548                         pChannel->nRampLength -= nSmpCount;
01549                         if (pChannel->nRampLength <= 0)
01550                         {
01551                                 pChannel->nRampLength = 0;
01552                                 pChannel->nRightVol = pChannel->nNewRightVol;
01553                                 pChannel->nLeftVol = pChannel->nNewLeftVol;
01554                                 pChannel->nRightRamp = pChannel->nLeftRamp = 0;
01555                                 if ((pChannel->dwFlags & CHN_NOTEFADE) && (!(pChannel->nFadeOutVol)))
01556                                 {
01557                                         pChannel->nLength = 0;
01558                                         pChannel->pCurrentSample = NULL;
01559                                 }
01560                         }
01561                 }
01562                 if (nsamples > 0) goto SampleLooping;
01563                 nchmixed += naddmix;
01564         }
01565         return nchused;
01566 }
01567 
01568 
01569 #ifdef WIN32
01570 #pragma warning (disable:4100)
01571 #endif
01572 
01573 // Clip and convert to 8 bit
01574 #ifdef WIN32
01575 __declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01576 //----------------------------------------------------------------------------------------------------------------------------
01577 {
01578         _asm {
01579         push ebx
01580         push esi
01581         push edi
01582         mov ebx, 16[esp]                // ebx = 8-bit buffer
01583         mov esi, 20[esp]                // esi = pBuffer
01584         mov edi, 24[esp]                // edi = lSampleCount
01585         mov eax, 28[esp]
01586         mov ecx, dword ptr [eax]        // ecx = clipmin
01587         mov eax, 32[esp]
01588         mov edx, dword ptr [eax]        // edx = clipmax
01589 cliploop:
01590         mov eax, dword ptr [esi]
01591         inc ebx
01592         cdq
01593         and edx, (1 << (24-MIXING_ATTENUATION)) - 1
01594         add eax, edx
01595         cmp eax, MIXING_CLIPMIN
01596         jl cliplow
01597         cmp eax, MIXING_CLIPMAX
01598         jg cliphigh
01599         cmp eax, ecx
01600         jl updatemin
01601         cmp eax, edx
01602         jg updatemax
01603 cliprecover:
01604         add esi, 4
01605         sar eax, 24-MIXING_ATTENUATION
01606         xor eax, 0x80
01607         dec edi
01608         mov byte ptr [ebx-1], al
01609         jnz cliploop
01610         mov eax, 28[esp]
01611         mov dword ptr [eax], ecx
01612         mov eax, 32[esp]
01613         mov dword ptr [eax], edx
01614         mov eax, 24[esp]
01615         pop edi
01616         pop esi
01617         pop ebx
01618         ret
01619 updatemin:
01620         mov ecx, eax
01621         jmp cliprecover
01622 updatemax:
01623         mov edx, eax
01624         jmp cliprecover
01625 cliplow:
01626         mov ecx, MIXING_CLIPMIN
01627         mov edx, MIXING_CLIPMAX
01628         mov eax, MIXING_CLIPMIN
01629         jmp cliprecover
01630 cliphigh:
01631         mov ecx, MIXING_CLIPMIN
01632         mov edx, MIXING_CLIPMAX
01633         mov eax, MIXING_CLIPMAX
01634         jmp cliprecover
01635         }
01636 }
01637 #else //WIN32
01638 //---GCCFIX: Asm replaced with C function
01639 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
01640 __declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01641 {
01642         int vumin = *lpMin, vumax = *lpMax;
01643         unsigned char *p = (unsigned char *)lp8;
01644         for (UINT i=0; i<lSampleCount; i++)
01645         {
01646                 int n = pBuffer[i];
01647                 if (n < MIXING_CLIPMIN) 
01648                         n = MIXING_CLIPMIN;
01649                 else if (n > MIXING_CLIPMAX)
01650                         n = MIXING_CLIPMAX;
01651                 if (n < vumin)
01652                         vumin = n;
01653                 else if (n > vumax)
01654                         vumax = n;
01655                 p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80;   // 8-bit unsigned
01656         }
01657         *lpMin = vumin;
01658         *lpMax = vumax;
01659         return lSampleCount;
01660 }
01661 #endif //WIN32, else
01662 
01663 
01664 #ifdef WIN32
01665 // Clip and convert to 16 bit
01666 __declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01667 //-----------------------------------------------------------------------------------------------------------------------------
01668 {
01669         _asm {
01670         push ebx
01671         push esi
01672         push edi
01673         mov ebx, 16[esp]                // ebx = 16-bit buffer
01674         mov eax, 28[esp]
01675         mov esi, 20[esp]                // esi = pBuffer
01676         mov ecx, dword ptr [eax]        // ecx = clipmin
01677         mov edi, 24[esp]                // edi = lSampleCount
01678         mov eax, 32[esp]
01679         push ebp
01680         mov ebp, dword ptr [eax]        // edx = clipmax
01681 cliploop:
01682         mov eax, dword ptr [esi]
01683         add ebx, 2
01684         cdq
01685         and edx, (1 << (16-MIXING_ATTENUATION)) - 1
01686         add esi, 4
01687         add eax, edx
01688         cmp eax, MIXING_CLIPMIN
01689         jl cliplow
01690         cmp eax, MIXING_CLIPMAX
01691         jg cliphigh
01692         cmp eax, ecx
01693         jl updatemin
01694         cmp eax, ebp
01695         jg updatemax
01696 cliprecover:
01697         sar eax, 16-MIXING_ATTENUATION
01698         dec edi
01699         mov word ptr [ebx-2], ax
01700         jnz cliploop
01701         mov edx, ebp
01702         pop ebp
01703         mov eax, 28[esp]
01704         mov dword ptr [eax], ecx
01705         mov eax, 32[esp]
01706         mov dword ptr [eax], edx
01707         mov eax, 24[esp]
01708         pop edi
01709         shl eax, 1
01710         pop esi
01711         pop ebx
01712         ret
01713 updatemin:
01714         mov ecx, eax
01715         jmp cliprecover
01716 updatemax:
01717         mov ebp, eax
01718         jmp cliprecover
01719 cliplow:
01720         mov ecx, MIXING_CLIPMIN
01721         mov ebp, MIXING_CLIPMAX
01722         mov eax, MIXING_CLIPMIN
01723         jmp cliprecover
01724 cliphigh:
01725         mov ecx, MIXING_CLIPMIN
01726         mov ebp, MIXING_CLIPMAX
01727         mov eax, MIXING_CLIPMAX
01728         jmp cliprecover
01729         }
01730 }
01731 #else //WIN32
01732 //---GCCFIX: Asm replaced with C function
01733 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
01734 __declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01735 {
01736         int vumin = *lpMin, vumax = *lpMax;
01737         signed short *p = (signed short *)lp16;
01738         for (UINT i=0; i<lSampleCount; i++)
01739         {
01740                 int n = pBuffer[i];
01741                 if (n < MIXING_CLIPMIN)
01742                         n = MIXING_CLIPMIN;
01743                 else if (n > MIXING_CLIPMAX)
01744                         n = MIXING_CLIPMAX;
01745                 if (n < vumin)
01746                         vumin = n;
01747                 else if (n > vumax)
01748                         vumax = n;
01749                 p[i] = n >> (16-MIXING_ATTENUATION);    // 16-bit signed
01750         }
01751         *lpMin = vumin;
01752         *lpMax = vumax;
01753         return lSampleCount * 2;
01754 }
01755 #endif //WIN32, else
01756 
01757 #ifdef WIN32
01758 // Clip and convert to 24 bit
01759 __declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01760 //-----------------------------------------------------------------------------------------------------------------------------
01761 {
01762         _asm {
01763         push ebx
01764         push esi
01765         push edi
01766         mov ebx, 16[esp]                // ebx = 8-bit buffer
01767         mov esi, 20[esp]                // esi = pBuffer
01768         mov edi, 24[esp]                // edi = lSampleCount
01769         mov eax, 28[esp]
01770         mov ecx, dword ptr [eax]        // ecx = clipmin
01771         mov eax, 32[esp]
01772         push ebp
01773         mov edx, dword ptr [eax]        // edx = clipmax
01774 cliploop:
01775         mov eax, dword ptr [esi]
01776         mov ebp, eax
01777         sar ebp, 31
01778         and ebp, (1 << (8-MIXING_ATTENUATION)) - 1
01779         add eax, ebp
01780         cmp eax, MIXING_CLIPMIN
01781         jl cliplow
01782         cmp eax, MIXING_CLIPMAX
01783         jg cliphigh
01784         cmp eax, ecx
01785         jl updatemin
01786         cmp eax, edx
01787         jg updatemax
01788 cliprecover:
01789         add ebx, 3
01790         sar eax, 8-MIXING_ATTENUATION
01791         add esi, 4
01792         mov word ptr [ebx-3], ax
01793         shr eax, 16
01794         dec edi
01795         mov byte ptr [ebx-1], al
01796         jnz cliploop
01797         pop ebp
01798         mov eax, 28[esp]
01799         mov dword ptr [eax], ecx
01800         mov eax, 32[esp]
01801         mov dword ptr [eax], edx
01802         mov edx, 24[esp]
01803         mov eax, edx
01804         pop edi
01805         shl eax, 1
01806         pop esi
01807         add eax, edx
01808         pop ebx
01809         ret
01810 updatemin:
01811         mov ecx, eax
01812         jmp cliprecover
01813 updatemax:
01814         mov edx, eax
01815         jmp cliprecover
01816 cliplow:
01817         mov ecx, MIXING_CLIPMIN
01818         mov edx, MIXING_CLIPMAX
01819         mov eax, MIXING_CLIPMIN
01820         jmp cliprecover
01821 cliphigh:
01822         mov ecx, MIXING_CLIPMIN
01823         mov edx, MIXING_CLIPMAX
01824         mov eax, MIXING_CLIPMAX
01825         jmp cliprecover
01826         }
01827 }
01828 #else //WIN32
01829 //---GCCFIX: Asm replaced with C function
01830 // 24-bit audio not supported.
01831 __declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01832 {
01833         return 0;
01834 }
01835 #endif
01836 
01837 #ifdef WIN32
01838 // Clip and convert to 32 bit
01839 __declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01840 //-----------------------------------------------------------------------------------------------------------------------------
01841 {
01842         _asm {
01843         push ebx
01844         push esi
01845         push edi
01846         mov ebx, 16[esp]                        // ebx = 32-bit buffer
01847         mov esi, 20[esp]                        // esi = pBuffer
01848         mov edi, 24[esp]                        // edi = lSampleCount
01849         mov eax, 28[esp]
01850         mov ecx, dword ptr [eax]        // ecx = clipmin
01851         mov eax, 32[esp]
01852         mov edx, dword ptr [eax]        // edx = clipmax
01853 cliploop:
01854         mov eax, dword ptr [esi]
01855         add ebx, 4
01856         add esi, 4
01857         cmp eax, MIXING_CLIPMIN
01858         jl cliplow
01859         cmp eax, MIXING_CLIPMAX
01860         jg cliphigh
01861         cmp eax, ecx
01862         jl updatemin
01863         cmp eax, edx
01864         jg updatemax
01865 cliprecover:
01866         shl eax, MIXING_ATTENUATION
01867         dec edi
01868         mov dword ptr [ebx-4], eax
01869         jnz cliploop
01870         mov eax, 28[esp]
01871         mov dword ptr [eax], ecx
01872         mov eax, 32[esp]
01873         mov dword ptr [eax], edx
01874         mov edx, 24[esp]
01875         pop edi
01876         mov eax, edx
01877         pop esi
01878         shl eax, 2
01879         pop ebx
01880         ret
01881 updatemin:
01882         mov ecx, eax
01883         jmp cliprecover
01884 updatemax:
01885         mov edx, eax
01886         jmp cliprecover
01887 cliplow:
01888         mov ecx, MIXING_CLIPMIN
01889         mov edx, MIXING_CLIPMAX
01890         mov eax, MIXING_CLIPMIN
01891         jmp cliprecover
01892 cliphigh:
01893         mov ecx, MIXING_CLIPMIN
01894         mov edx, MIXING_CLIPMAX
01895         mov eax, MIXING_CLIPMAX
01896         jmp cliprecover
01897         }
01898 }
01899 #else
01900 //---GCCFIX: Asm replaced with C function
01901 // 32-bit audio not supported
01902 __declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
01903 {
01904         return 0;
01905 }
01906 #endif
01907 
01908 
01909 #ifdef WIN32
01910 void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
01911 //------------------------------------------------------------
01912 {
01913         _asm {
01914         mov ecx, nSamples
01915         mov esi, pBuffer
01916         xor eax, eax
01917         mov edx, ecx
01918         shr ecx, 2
01919         and edx, 3
01920         jz unroll4x
01921 loop1x:
01922         add esi, 4
01923         dec edx
01924         mov dword ptr [esi-4], eax
01925         jnz loop1x
01926 unroll4x:
01927         or ecx, ecx
01928         jnz loop4x
01929         jmp done
01930 loop4x:
01931         add esi, 16
01932         dec ecx
01933         mov dword ptr [esi-16], eax
01934         mov dword ptr [esi-12], eax
01935         mov dword ptr [esi-8], eax
01936         mov dword ptr [esi-4], eax
01937         jnz loop4x
01938 done:;
01939         }
01940 }
01941 #else
01942 //---GCCFIX: Asm replaced with C function
01943 // Will fill in later.
01944 void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
01945 {
01946         memset(pBuffer, 0, nSamples * sizeof(int));
01947 }
01948 #endif
01949 
01950 
01951 #ifdef WIN32
01952 __declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
01953 //------------------------------------------------------------------------------------------------------
01954 {
01955         _asm {
01956         push ebx
01957         push ebp
01958         push esi
01959         push edi
01960         mov ecx, 28[esp] // ecx = samplecount
01961         mov esi, 20[esp] // esi = front buffer
01962         mov edi, 24[esp] // edi = rear buffer
01963         lea esi, [esi+ecx*4]    // esi = &front[N]
01964         lea edi, [edi+ecx*4]    // edi = &rear[N]
01965         lea ebx, [esi+ecx*4]    // ebx = &front[N*2]
01966 interleaveloop:
01967         mov eax, dword ptr [esi-8]
01968         mov edx, dword ptr [esi-4]
01969         sub ebx, 16
01970         mov ebp, dword ptr [edi-8]
01971         mov dword ptr [ebx], eax
01972         mov dword ptr [ebx+4], edx
01973         mov eax, dword ptr [edi-4]
01974         sub esi, 8
01975         sub edi, 8
01976         dec ecx
01977         mov dword ptr [ebx+8], ebp
01978         mov dword ptr [ebx+12], eax
01979         jnz interleaveloop
01980         pop edi
01981         pop esi
01982         pop ebp
01983         pop ebx
01984         ret
01985         }
01986 }
01987 #else
01988 //---GCCFIX: Asm replaced with C function
01989 // Multichannel not supported.
01990 __declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
01991 {
01992 }
01993 #endif
01994 
01995 
01996 #ifdef WIN32
01997 VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
01998 //-------------------------------------------------------------
01999 {
02000         _asm {
02001         mov ecx, nSamples
02002         mov esi, pMixBuf
02003         mov edi, esi
02004 stloop:
02005         mov eax, dword ptr [esi]
02006         mov edx, dword ptr [esi+4]
02007         add edi, 4
02008         add esi, 8
02009         add eax, edx
02010         sar eax, 1
02011         dec ecx
02012         mov dword ptr [edi-4], eax
02013         jnz stloop
02014         }
02015 }
02016 #else
02017 //---GCCFIX: Asm replaced with C function
02018 VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
02019 {
02020         UINT j;
02021         for(UINT i = 0; i < nSamples; i++)
02022         {
02023                 j = i << 1;
02024                 pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1;
02025         }
02026 }
02027 #endif
02028 
02029 #define OFSDECAYSHIFT   8
02030 #define OFSDECAYMASK    0xFF
02031 
02032 
02033 #ifdef WIN32
02034 void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
02035 //---------------------------------------------------------------------------------------
02036 {
02037         _asm {
02038         mov edi, pBuffer
02039         mov ecx, nSamples
02040         mov eax, lpROfs
02041         mov edx, lpLOfs
02042         mov eax, [eax]
02043         mov edx, [edx]
02044         or ecx, ecx
02045         jz fill_loop
02046         mov ebx, eax
02047         or ebx, edx
02048         jz fill_loop
02049 ofsloop:
02050         mov ebx, eax
02051         mov esi, edx
02052         neg ebx
02053         neg esi
02054         sar ebx, 31
02055         sar esi, 31
02056         and ebx, OFSDECAYMASK
02057         and esi, OFSDECAYMASK
02058         add ebx, eax
02059         add esi, edx
02060         sar ebx, OFSDECAYSHIFT
02061         sar esi, OFSDECAYSHIFT
02062         sub eax, ebx
02063         sub edx, esi
02064         mov ebx, eax
02065         or ebx, edx
02066         jz fill_loop
02067         add edi, 8
02068         dec ecx
02069         mov [edi-8], eax
02070         mov [edi-4], edx
02071         jnz ofsloop
02072 fill_loop:
02073         mov ebx, ecx
02074         and ebx, 3
02075         jz fill4x
02076 fill1x:
02077         mov [edi], eax
02078         mov [edi+4], edx
02079         add edi, 8
02080         dec ebx
02081         jnz fill1x
02082 fill4x:
02083         shr ecx, 2
02084         or ecx, ecx
02085         jz done
02086 fill4xloop:
02087         mov [edi], eax
02088         mov [edi+4], edx
02089         mov [edi+8], eax
02090         mov [edi+12], edx
02091         add edi, 8*4
02092         dec ecx
02093         mov [edi-16], eax
02094         mov [edi-12], edx
02095         mov [edi-8], eax
02096         mov [edi-4], edx
02097         jnz fill4xloop
02098 done:
02099         mov esi, lpROfs
02100         mov edi, lpLOfs
02101         mov [esi], eax
02102         mov [edi], edx
02103         }
02104 }
02105 #else
02106 //---GCCFIX: Asm replaced with C function
02107 #define OFSDECAYSHIFT    8
02108 #define OFSDECAYMASK     0xFF
02109 __declspec(naked) void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
02110 //---------------------------------------------------------------------------------------------------------
02111 {
02112         int rofs = *lpROfs;
02113         int lofs = *lpLOfs;
02114         
02115         if ((!rofs) && (!lofs))
02116         {
02117                 X86_InitMixBuffer(pBuffer, nSamples*2);
02118                 return;
02119         }
02120         for (UINT i=0; i<nSamples; i++)
02121         {
02122                 int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
02123                 int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
02124                 rofs -= x_r;
02125                 lofs -= x_l;
02126                 pBuffer[i*2] = x_r;
02127                 pBuffer[i*2+1] = x_l;
02128         }
02129         *lpROfs = rofs;
02130         *lpLOfs = lofs;
02131 }
02132 #endif
02133 
02134 #ifdef WIN32
02135 void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
02136 //----------------------------------------------------------------------------------
02137 {
02138         _asm {
02139         mov esi, pChannel
02140         mov edi, pBuffer
02141         mov ecx, nSamples
02142         mov eax, dword ptr [esi+MODCHANNEL.nROfs]
02143         mov edx, dword ptr [esi+MODCHANNEL.nLOfs]
02144         or ecx, ecx
02145         jz brkloop
02146 ofsloop:
02147         mov ebx, eax
02148         mov esi, edx
02149         neg ebx
02150         neg esi
02151         sar ebx, 31
02152         sar esi, 31
02153         and ebx, OFSDECAYMASK
02154         and esi, OFSDECAYMASK
02155         add ebx, eax
02156         add esi, edx
02157         sar ebx, OFSDECAYSHIFT
02158         sar esi, OFSDECAYSHIFT
02159         sub eax, ebx
02160         sub edx, esi
02161         mov ebx, eax
02162         add dword ptr [edi], eax
02163         add dword ptr [edi+4], edx
02164         or ebx, edx
02165         jz brkloop
02166         add edi, 8
02167         dec ecx
02168         jnz ofsloop
02169 brkloop:
02170         mov esi, pChannel
02171         mov dword ptr [esi+MODCHANNEL.nROfs], eax
02172         mov dword ptr [esi+MODCHANNEL.nLOfs], edx
02173         }
02174 }
02175 #else
02176 //---GCCFIX: Asm replaced with C function
02177 // Will fill in later.
02178 void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
02179 {
02180         int rofs = pChannel->nROfs;
02181         int lofs = pChannel->nLOfs;
02182         
02183         if ((!rofs) && (!lofs)) return;
02184         for (UINT i=0; i<nSamples; i++)
02185         {
02186                 int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
02187                 int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
02188                 rofs -= x_r;
02189                 lofs -= x_l;
02190                 pBuffer[i*2] += x_r;
02191                 pBuffer[i*2+1] += x_l;
02192         }
02193         pChannel->nROfs = rofs;
02194         pChannel->nLOfs = lofs;
02195 }
02196 #endif
02197 
02198 
02200 // Automatic Gain Control
02201 
02202 #ifndef NO_AGC
02203 
02204 // Limiter
02205 #define MIXING_LIMITMAX         (0x08100000)
02206 #define MIXING_LIMITMIN         (-MIXING_LIMITMAX)
02207 
02208 __declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
02209 //-------------------------------------------------------------------------------
02210 {
02211         __asm {
02212         push ebx
02213         push ebp
02214         push esi
02215         push edi
02216         mov esi, 20[esp]        // esi = pBuffer+i
02217         mov ecx, 24[esp]        // ecx = i
02218         mov edi, 28[esp]        // edi = AGC (0..256)
02219 agcloop:
02220         mov eax, dword ptr [esi]
02221         imul edi
02222         shrd eax, edx, AGC_PRECISION
02223         add esi, 4
02224         cmp eax, MIXING_LIMITMIN
02225         jl agcupdate
02226         cmp eax, MIXING_LIMITMAX
02227         jg agcupdate
02228 agcrecover:
02229         dec ecx
02230         mov dword ptr [esi-4], eax
02231         jnz agcloop
02232         mov eax, edi
02233         pop edi
02234         pop esi
02235         pop ebp
02236         pop ebx
02237         ret
02238 agcupdate:
02239         dec edi
02240         jmp agcrecover
02241         }
02242 }
02243 
02244 #pragma warning (default:4100)
02245 
02246 void CSoundFile::ProcessAGC(int count)
02247 //------------------------------------
02248 {
02249         static DWORD gAGCRecoverCount = 0;
02250         UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC);
02251         // Some kind custom law, so that the AGC stays quite stable, but slowly
02252         // goes back up if the sound level stays below a level inversely proportional
02253         // to the AGC level. (J'me comprends)
02254         if ((agc >= gnAGC) && (gnAGC < AGC_UNITY) && (gnVUMeter < (0xFF - (gnAGC >> (AGC_PRECISION-7))) ))
02255         {
02256                 gAGCRecoverCount += count;
02257                 UINT agctimeout = gdwMixingFreq + gnAGC;
02258                 if (gnChannels >= 2) agctimeout <<= 1;
02259                 if (gAGCRecoverCount >= agctimeout)
02260                 {
02261                         gAGCRecoverCount = 0;
02262                         gnAGC++;
02263                 }
02264         } else
02265         {
02266                 gnAGC = agc;
02267                 gAGCRecoverCount = 0;
02268         }
02269 }
02270 
02271 
02272 
02273 void CSoundFile::ResetAGC()
02274 //-------------------------
02275 {
02276         gnAGC = AGC_UNITY;
02277 }
02278 
02279 #endif // NO_AGC
02280 

Generated on Sat Nov 5 16:15:38 2005 for OPIE by  doxygen 1.4.2