00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "stdafx.h"
00011 #include "sndfile.h"
00012
00013 #ifdef FASTSOUNDLIB
00014 #define NO_REVERB
00015 #endif
00016
00017
00018
00019 #ifndef FASTSOUNDLIB
00020 #define nDolbyHiFltAttn 6
00021 #define nDolbyHiFltMask 3
00022 #define DOLBYATTNROUNDUP 31
00023 #else
00024 #define nDolbyHiFltAttn 3
00025 #define nDolbyHiFltMask 3
00026 #define DOLBYATTNROUNDUP 3
00027 #endif
00028
00029
00030 #define XBASS_DELAY 14 // 2.5 ms
00031
00032
00033 #define XBASSBUFFERSIZE 64 // 2 ms at 50KHz
00034 #define FILTERBUFFERSIZE 64 // 1.25 ms
00035 #define SURROUNDBUFFERSIZE ((MAX_SAMPLE_RATE * 50) / 1000)
00036 #define REVERBBUFFERSIZE ((MAX_SAMPLE_RATE * 200) / 1000)
00037 #define REVERBBUFFERSIZE2 ((REVERBBUFFERSIZE*13) / 17)
00038 #define REVERBBUFFERSIZE3 ((REVERBBUFFERSIZE*7) / 13)
00039 #define REVERBBUFFERSIZE4 ((REVERBBUFFERSIZE*7) / 19)
00040
00041
00042
00043 UINT CSoundFile::m_nXBassDepth = 6;
00044 UINT CSoundFile::m_nXBassRange = XBASS_DELAY;
00045 UINT CSoundFile::m_nReverbDepth = 1;
00046 UINT CSoundFile::m_nReverbDelay = 100;
00047 UINT CSoundFile::m_nProLogicDepth = 12;
00048 UINT CSoundFile::m_nProLogicDelay = 20;
00049
00051
00052
00053
00054 static LONG nXBassSum = 0;
00055 static LONG nXBassBufferPos = 0;
00056 static LONG nXBassDlyPos = 0;
00057 static LONG nXBassMask = 0;
00058
00059
00060 static LONG nLeftNR = 0;
00061 static LONG nRightNR = 0;
00062
00063
00064 static LONG nSurroundSize = 0;
00065 static LONG nSurroundPos = 0;
00066 static LONG nDolbyDepth = 0;
00067 static LONG nDolbyLoDlyPos = 0;
00068 static LONG nDolbyLoFltPos = 0;
00069 static LONG nDolbyLoFltSum = 0;
00070 static LONG nDolbyHiFltPos = 0;
00071 static LONG nDolbyHiFltSum = 0;
00072
00073
00074 #ifndef NO_REVERB
00075 static LONG nReverbSize = 0;
00076 static LONG nReverbBufferPos = 0;
00077 static LONG nReverbSize2 = 0;
00078 static LONG nReverbBufferPos2 = 0;
00079 static LONG nReverbSize3 = 0;
00080 static LONG nReverbBufferPos3 = 0;
00081 static LONG nReverbSize4 = 0;
00082 static LONG nReverbBufferPos4 = 0;
00083 static LONG nReverbLoFltSum = 0;
00084 static LONG nReverbLoFltPos = 0;
00085 static LONG nReverbLoDlyPos = 0;
00086 static LONG nFilterAttn = 0;
00087 static LONG gRvbLowPass[8];
00088 static LONG gRvbLPPos = 0;
00089 static LONG gRvbLPSum = 0;
00090 static LONG ReverbLoFilterBuffer[XBASSBUFFERSIZE];
00091 static LONG ReverbLoFilterDelay[XBASSBUFFERSIZE];
00092 static LONG ReverbBuffer[REVERBBUFFERSIZE];
00093 static LONG ReverbBuffer2[REVERBBUFFERSIZE2];
00094 static LONG ReverbBuffer3[REVERBBUFFERSIZE3];
00095 static LONG ReverbBuffer4[REVERBBUFFERSIZE4];
00096 #endif
00097 static LONG XBassBuffer[XBASSBUFFERSIZE];
00098 static LONG XBassDelay[XBASSBUFFERSIZE];
00099 static LONG DolbyLoFilterBuffer[XBASSBUFFERSIZE];
00100 static LONG DolbyLoFilterDelay[XBASSBUFFERSIZE];
00101 static LONG DolbyHiFilterBuffer[FILTERBUFFERSIZE];
00102 static LONG SurroundBuffer[SURROUNDBUFFERSIZE];
00103
00104
00105 extern int MixSoundBuffer[MIXBUFFERSIZE*2];
00106
00107 extern int MixReverbBuffer[MIXBUFFERSIZE*2];
00108
00109 static UINT GetMaskFromSize(UINT len)
00110
00111 {
00112 UINT n = 2;
00113 while (n <= len) n <<= 1;
00114 return ((n >> 1) - 1);
00115 }
00116
00117
00118 void CSoundFile::InitializeDSP(BOOL bReset)
00119
00120 {
00121 if (!m_nReverbDelay) m_nReverbDelay = 100;
00122 if (!m_nXBassRange) m_nXBassRange = XBASS_DELAY;
00123 if (!m_nProLogicDelay) m_nProLogicDelay = 20;
00124 if (m_nXBassDepth > 8) m_nXBassDepth = 8;
00125 if (m_nXBassDepth < 2) m_nXBassDepth = 2;
00126 if (bReset)
00127 {
00128
00129 nLeftNR = nRightNR = 0;
00130 }
00131
00132 nSurroundPos = nSurroundSize = 0;
00133 nDolbyLoFltPos = nDolbyLoFltSum = nDolbyLoDlyPos = 0;
00134 nDolbyHiFltPos = nDolbyHiFltSum = 0;
00135 if (gdwSoundSetup & SNDMIX_SURROUND)
00136 {
00137 memset(DolbyLoFilterBuffer, 0, sizeof(DolbyLoFilterBuffer));
00138 memset(DolbyHiFilterBuffer, 0, sizeof(DolbyHiFilterBuffer));
00139 memset(DolbyLoFilterDelay, 0, sizeof(DolbyLoFilterDelay));
00140 memset(SurroundBuffer, 0, sizeof(SurroundBuffer));
00141 nSurroundSize = (gdwMixingFreq * m_nProLogicDelay) / 1000;
00142 if (nSurroundSize > SURROUNDBUFFERSIZE) nSurroundSize = SURROUNDBUFFERSIZE;
00143 if (m_nProLogicDepth < 8) nDolbyDepth = (32 >> m_nProLogicDepth) + 32;
00144 else nDolbyDepth = (m_nProLogicDepth < 16) ? (8 + (m_nProLogicDepth - 8) * 7) : 64;
00145 nDolbyDepth >>= 2;
00146 }
00147
00148 #ifndef NO_REVERB
00149 if (gdwSoundSetup & SNDMIX_REVERB)
00150 {
00151 UINT nrs = (gdwMixingFreq * m_nReverbDelay) / 1000;
00152 UINT nfa = m_nReverbDepth+1;
00153 if (nrs > REVERBBUFFERSIZE) nrs = REVERBBUFFERSIZE;
00154 if ((bReset) || (nrs != (UINT)nReverbSize) || (nfa != (UINT)nFilterAttn))
00155 {
00156 nFilterAttn = nfa;
00157 nReverbSize = nrs;
00158 nReverbBufferPos = nReverbBufferPos2 = nReverbBufferPos3 = nReverbBufferPos4 = 0;
00159 nReverbLoFltSum = nReverbLoFltPos = nReverbLoDlyPos = 0;
00160 gRvbLPSum = gRvbLPPos = 0;
00161 nReverbSize2 = (nReverbSize * 13) / 17;
00162 if (nReverbSize2 > REVERBBUFFERSIZE2) nReverbSize2 = REVERBBUFFERSIZE2;
00163 nReverbSize3 = (nReverbSize * 7) / 13;
00164 if (nReverbSize3 > REVERBBUFFERSIZE3) nReverbSize3 = REVERBBUFFERSIZE3;
00165 nReverbSize4 = (nReverbSize * 7) / 19;
00166 if (nReverbSize4 > REVERBBUFFERSIZE4) nReverbSize4 = REVERBBUFFERSIZE4;
00167 memset(ReverbLoFilterBuffer, 0, sizeof(ReverbLoFilterBuffer));
00168 memset(ReverbLoFilterDelay, 0, sizeof(ReverbLoFilterDelay));
00169 memset(ReverbBuffer, 0, sizeof(ReverbBuffer));
00170 memset(ReverbBuffer2, 0, sizeof(ReverbBuffer2));
00171 memset(ReverbBuffer3, 0, sizeof(ReverbBuffer3));
00172 memset(ReverbBuffer4, 0, sizeof(ReverbBuffer4));
00173 memset(gRvbLowPass, 0, sizeof(gRvbLowPass));
00174 }
00175 } else nReverbSize = 0;
00176 #endif
00177 BOOL bResetBass = FALSE;
00178
00179 if (gdwSoundSetup & SNDMIX_MEGABASS)
00180 {
00181 UINT nXBassSamples = (gdwMixingFreq * m_nXBassRange) / 10000;
00182 if (nXBassSamples > XBASSBUFFERSIZE) nXBassSamples = XBASSBUFFERSIZE;
00183 UINT mask = GetMaskFromSize(nXBassSamples);
00184 if ((bReset) || (mask != (UINT)nXBassMask))
00185 {
00186 nXBassMask = mask;
00187 bResetBass = TRUE;
00188 }
00189 } else
00190 {
00191 nXBassMask = 0;
00192 bResetBass = TRUE;
00193 }
00194 if (bResetBass)
00195 {
00196 nXBassSum = nXBassBufferPos = nXBassDlyPos = 0;
00197 memset(XBassBuffer, 0, sizeof(XBassBuffer));
00198 memset(XBassDelay, 0, sizeof(XBassDelay));
00199 }
00200 }
00201
00202
00203 void CSoundFile::ProcessStereoDSP(int count)
00204
00205 {
00206 #ifndef NO_REVERB
00207
00208 if (gdwSoundSetup & SNDMIX_REVERB)
00209 {
00210 int *pr = MixSoundBuffer, *pin = MixReverbBuffer, rvbcount = count;
00211 do
00212 {
00213 int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2]
00214 + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4];
00215
00216 int echodly = ReverbLoFilterDelay[nReverbLoDlyPos];
00217 ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1;
00218 nReverbLoDlyPos++;
00219 nReverbLoDlyPos &= 0x1F;
00220 int n = nReverbLoFltPos;
00221 nReverbLoFltSum -= ReverbLoFilterBuffer[n];
00222 int tmp = echo / 128;
00223 ReverbLoFilterBuffer[n] = tmp;
00224 nReverbLoFltSum += tmp;
00225 echodly -= nReverbLoFltSum;
00226 nReverbLoFltPos = (n + 1) & 0x3F;
00227
00228 int v = (pin[0]+pin[1]) >> nFilterAttn;
00229 pr[0] += pin[0] + echodly;
00230 pr[1] += pin[1] + echodly;
00231 v += echodly >> 2;
00232 ReverbBuffer3[nReverbBufferPos3] = v;
00233 ReverbBuffer4[nReverbBufferPos4] = v;
00234 v += echodly >> 4;
00235 v >>= 1;
00236 gRvbLPSum -= gRvbLowPass[gRvbLPPos];
00237 gRvbLPSum += v;
00238 gRvbLowPass[gRvbLPPos] = v;
00239 gRvbLPPos++;
00240 gRvbLPPos &= 7;
00241 int vlp = gRvbLPSum >> 2;
00242 ReverbBuffer[nReverbBufferPos] = vlp;
00243 ReverbBuffer2[nReverbBufferPos2] = vlp;
00244 if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0;
00245 if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0;
00246 if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0;
00247 if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0;
00248 pr += 2;
00249 pin += 2;
00250 } while (--rvbcount);
00251 }
00252 #endif
00253
00254 if (gdwSoundSetup & SNDMIX_SURROUND)
00255 {
00256 int *pr = MixSoundBuffer, n = nDolbyLoFltPos;
00257 for (int r=count; r; r--)
00258 {
00259 int v = (pr[0]+pr[1]+DOLBYATTNROUNDUP) >> (nDolbyHiFltAttn+1);
00260 #ifndef FASTSOUNDLIB
00261 v *= (int)nDolbyDepth;
00262 #endif
00263
00264 nDolbyHiFltSum -= DolbyHiFilterBuffer[nDolbyHiFltPos];
00265 DolbyHiFilterBuffer[nDolbyHiFltPos] = v;
00266 nDolbyHiFltSum += v;
00267 v = nDolbyHiFltSum;
00268 nDolbyHiFltPos++;
00269 nDolbyHiFltPos &= nDolbyHiFltMask;
00270
00271 int secho = SurroundBuffer[nSurroundPos];
00272 SurroundBuffer[nSurroundPos] = v;
00273
00274 v = DolbyLoFilterDelay[nDolbyLoDlyPos];
00275 DolbyLoFilterDelay[nDolbyLoDlyPos] = secho;
00276 nDolbyLoDlyPos++;
00277 nDolbyLoDlyPos &= 0x1F;
00278 nDolbyLoFltSum -= DolbyLoFilterBuffer[n];
00279 int tmp = secho / 64;
00280 DolbyLoFilterBuffer[n] = tmp;
00281 nDolbyLoFltSum += tmp;
00282 v -= nDolbyLoFltSum;
00283 n++;
00284 n &= 0x3F;
00285
00286 pr[0] += v;
00287 pr[1] -= v;
00288 if (++nSurroundPos >= nSurroundSize) nSurroundPos = 0;
00289 pr += 2;
00290 }
00291 nDolbyLoFltPos = n;
00292 }
00293
00294 if (gdwSoundSetup & SNDMIX_MEGABASS)
00295 {
00296 int *px = MixSoundBuffer;
00297 int xba = m_nXBassDepth+1, xbamask = (1 << xba) - 1;
00298 int n = nXBassBufferPos;
00299 for (int x=count; x; x--)
00300 {
00301 nXBassSum -= XBassBuffer[n];
00302 int tmp0 = px[0] + px[1];
00303 int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba;
00304 XBassBuffer[n] = tmp;
00305 nXBassSum += tmp;
00306 int v = XBassDelay[nXBassDlyPos];
00307 XBassDelay[nXBassDlyPos] = px[0];
00308 px[0] = v + nXBassSum;
00309 v = XBassDelay[nXBassDlyPos+1];
00310 XBassDelay[nXBassDlyPos+1] = px[1];
00311 px[1] = v + nXBassSum;
00312 nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask;
00313 px += 2;
00314 n++;
00315 n &= nXBassMask;
00316 }
00317 nXBassBufferPos = n;
00318 }
00319
00320 if (gdwSoundSetup & SNDMIX_NOISEREDUCTION)
00321 {
00322 int n1 = nLeftNR, n2 = nRightNR;
00323 int *pnr = MixSoundBuffer;
00324 for (int nr=count; nr; nr--)
00325 {
00326 int vnr = pnr[0] >> 1;
00327 pnr[0] = vnr + n1;
00328 n1 = vnr;
00329 vnr = pnr[1] >> 1;
00330 pnr[1] = vnr + n2;
00331 n2 = vnr;
00332 pnr += 2;
00333 }
00334 nLeftNR = n1;
00335 nRightNR = n2;
00336 }
00337 }
00338
00339
00340 void CSoundFile::ProcessMonoDSP(int count)
00341
00342 {
00343 #ifndef NO_REVERB
00344
00345 if (gdwSoundSetup & SNDMIX_REVERB)
00346 {
00347 int *pr = MixSoundBuffer, rvbcount = count, *pin = MixReverbBuffer;
00348 do
00349 {
00350 int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2]
00351 + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4];
00352
00353 int echodly = ReverbLoFilterDelay[nReverbLoDlyPos];
00354 ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1;
00355 nReverbLoDlyPos++;
00356 nReverbLoDlyPos &= 0x1F;
00357 int n = nReverbLoFltPos;
00358 nReverbLoFltSum -= ReverbLoFilterBuffer[n];
00359 int tmp = echo / 128;
00360 ReverbLoFilterBuffer[n] = tmp;
00361 nReverbLoFltSum += tmp;
00362 echodly -= nReverbLoFltSum;
00363 nReverbLoFltPos = (n + 1) & 0x3F;
00364
00365 int v = pin[0] >> (nFilterAttn-1);
00366 *pr++ += pin[0] + echodly;
00367 pin++;
00368 v += echodly >> 2;
00369 ReverbBuffer3[nReverbBufferPos3] = v;
00370 ReverbBuffer4[nReverbBufferPos4] = v;
00371 v += echodly >> 4;
00372 v >>= 1;
00373 gRvbLPSum -= gRvbLowPass[gRvbLPPos];
00374 gRvbLPSum += v;
00375 gRvbLowPass[gRvbLPPos] = v;
00376 gRvbLPPos++;
00377 gRvbLPPos &= 7;
00378 int vlp = gRvbLPSum >> 2;
00379 ReverbBuffer[nReverbBufferPos] = vlp;
00380 ReverbBuffer2[nReverbBufferPos2] = vlp;
00381 if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0;
00382 if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0;
00383 if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0;
00384 if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0;
00385 } while (--rvbcount);
00386 }
00387 #endif
00388
00389 if (gdwSoundSetup & SNDMIX_MEGABASS)
00390 {
00391 int *px = MixSoundBuffer;
00392 int xba = m_nXBassDepth, xbamask = (1 << xba)-1;
00393 int n = nXBassBufferPos;
00394 for (int x=count; x; x--)
00395 {
00396 nXBassSum -= XBassBuffer[n];
00397 int tmp0 = *px;
00398 int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba;
00399 XBassBuffer[n] = tmp;
00400 nXBassSum += tmp;
00401 int v = XBassDelay[nXBassDlyPos];
00402 XBassDelay[nXBassDlyPos] = *px;
00403 *px++ = v + nXBassSum;
00404 nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask;
00405 n++;
00406 n &= nXBassMask;
00407 }
00408 nXBassBufferPos = n;
00409 }
00410
00411 if (gdwSoundSetup & SNDMIX_NOISEREDUCTION)
00412 {
00413 int n = nLeftNR;
00414 int *pnr = MixSoundBuffer;
00415 for (int nr=count; nr; pnr++, nr--)
00416 {
00417 int vnr = *pnr >> 1;
00418 *pnr = vnr + n;
00419 n = vnr;
00420 }
00421 nLeftNR = n;
00422 }
00423 }
00424
00425
00427
00428
00429
00430 BOOL CSoundFile::SetReverbParameters(UINT nDepth, UINT nDelay)
00431
00432 {
00433 if (nDepth > 100) nDepth = 100;
00434 UINT gain = nDepth / 20;
00435 if (gain > 4) gain = 4;
00436 m_nReverbDepth = 4 - gain;
00437 if (nDelay < 40) nDelay = 40;
00438 if (nDelay > 250) nDelay = 250;
00439 m_nReverbDelay = nDelay;
00440 return TRUE;
00441 }
00442
00443
00444
00445 BOOL CSoundFile::SetXBassParameters(UINT nDepth, UINT nRange)
00446
00447 {
00448 if (nDepth > 100) nDepth = 100;
00449 UINT gain = nDepth / 20;
00450 if (gain > 4) gain = 4;
00451 m_nXBassDepth = 8 - gain;
00452 UINT range = nRange / 5;
00453 if (range > 5) range -= 5; else range = 0;
00454 if (nRange > 16) nRange = 16;
00455 m_nXBassRange = 21 - range;
00456 return TRUE;
00457 }
00458
00459
00460
00461 BOOL CSoundFile::SetSurroundParameters(UINT nDepth, UINT nDelay)
00462
00463 {
00464 UINT gain = (nDepth * 16) / 100;
00465 if (gain > 16) gain = 16;
00466 if (gain < 1) gain = 1;
00467 m_nProLogicDepth = gain;
00468 if (nDelay < 4) nDelay = 4;
00469 if (nDelay > 50) nDelay = 50;
00470 m_nProLogicDelay = nDelay;
00471 return TRUE;
00472 }
00473
00474 BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ)
00475
00476 {
00477 DWORD d = gdwSoundSetup & ~(SNDMIX_SURROUND | SNDMIX_NORESAMPLING | SNDMIX_REVERB | SNDMIX_HQRESAMPLER | SNDMIX_MEGABASS | SNDMIX_NOISEREDUCTION | SNDMIX_EQ);
00478 if (bSurround) d |= SNDMIX_SURROUND;
00479 if (bNoOverSampling) d |= SNDMIX_NORESAMPLING;
00480 if (bReverb) d |= SNDMIX_REVERB;
00481 if (hqido) d |= SNDMIX_HQRESAMPLER;
00482 if (bMegaBass) d |= SNDMIX_MEGABASS;
00483 if (bNR) d |= SNDMIX_NOISEREDUCTION;
00484 if (bEQ) d |= SNDMIX_EQ;
00485 gdwSoundSetup = d;
00486 InitPlayer(FALSE);
00487 return TRUE;
00488 }