external/libmodplug-0.8.8.4/src/snd_dsp.cpp
author Sam Lantinga <slouken@libsdl.org>
Sun, 09 Jun 2013 16:22:42 -0700
changeset 639 f8901a7ff3f1
permissions -rw-r--r--
Switched from mikmod to libmodplug, which is now in the public domain.
This allows us to add MOD support for iOS and Android, yay!
slouken@639
     1
/*
slouken@639
     2
 * This source code is public domain.
slouken@639
     3
 *
slouken@639
     4
 * Authors: Olivier Lapicque <olivierl@jps.net>
slouken@639
     5
*/
slouken@639
     6
slouken@639
     7
#include "stdafx.h"
slouken@639
     8
#include "sndfile.h"
slouken@639
     9
slouken@639
    10
#ifdef MODPLUG_FASTSOUNDLIB
slouken@639
    11
#define MODPLUG_NO_REVERB
slouken@639
    12
#endif
slouken@639
    13
slouken@639
    14
slouken@639
    15
// Delayed Surround Filters
slouken@639
    16
#ifndef MODPLUG_FASTSOUNDLIB
slouken@639
    17
#define nDolbyHiFltAttn		6
slouken@639
    18
#define nDolbyHiFltMask		3
slouken@639
    19
#define DOLBYATTNROUNDUP	31
slouken@639
    20
#else
slouken@639
    21
#define nDolbyHiFltAttn		3
slouken@639
    22
#define nDolbyHiFltMask		3
slouken@639
    23
#define DOLBYATTNROUNDUP	3
slouken@639
    24
#endif
slouken@639
    25
slouken@639
    26
// Bass Expansion
slouken@639
    27
#define XBASS_DELAY			14	// 2.5 ms
slouken@639
    28
slouken@639
    29
// Buffer Sizes
slouken@639
    30
#define XBASSBUFFERSIZE		64		// 2 ms at 50KHz
slouken@639
    31
#define FILTERBUFFERSIZE	64		// 1.25 ms
slouken@639
    32
#define SURROUNDBUFFERSIZE	((MAX_SAMPLE_RATE * 50) / 1000)
slouken@639
    33
#define REVERBBUFFERSIZE	((MAX_SAMPLE_RATE * 200) / 1000)
slouken@639
    34
#define REVERBBUFFERSIZE2	((REVERBBUFFERSIZE*13) / 17)
slouken@639
    35
#define REVERBBUFFERSIZE3	((REVERBBUFFERSIZE*7) / 13)
slouken@639
    36
#define REVERBBUFFERSIZE4	((REVERBBUFFERSIZE*7) / 19)
slouken@639
    37
slouken@639
    38
slouken@639
    39
// DSP Effects: PUBLIC members
slouken@639
    40
UINT CSoundFile::m_nXBassDepth = 6;
slouken@639
    41
UINT CSoundFile::m_nXBassRange = XBASS_DELAY;
slouken@639
    42
UINT CSoundFile::m_nReverbDepth = 1;
slouken@639
    43
UINT CSoundFile::m_nReverbDelay = 100;
slouken@639
    44
UINT CSoundFile::m_nProLogicDepth = 12;
slouken@639
    45
UINT CSoundFile::m_nProLogicDelay = 20;
slouken@639
    46
slouken@639
    47
////////////////////////////////////////////////////////////////////
slouken@639
    48
// DSP Effects internal state
slouken@639
    49
slouken@639
    50
// Bass Expansion: low-pass filter
slouken@639
    51
static LONG nXBassSum = 0;
slouken@639
    52
static LONG nXBassBufferPos = 0;
slouken@639
    53
static LONG nXBassDlyPos = 0;
slouken@639
    54
static LONG nXBassMask = 0;
slouken@639
    55
slouken@639
    56
// Noise Reduction: simple low-pass filter
slouken@639
    57
static LONG nLeftNR = 0;
slouken@639
    58
static LONG nRightNR = 0;
slouken@639
    59
slouken@639
    60
// Surround Encoding: 1 delay line + low-pass filter + high-pass filter
slouken@639
    61
static LONG nSurroundSize = 0;
slouken@639
    62
static LONG nSurroundPos = 0;
slouken@639
    63
static LONG nDolbyDepth = 0;
slouken@639
    64
static LONG nDolbyLoDlyPos = 0;
slouken@639
    65
static LONG nDolbyLoFltPos = 0;
slouken@639
    66
static LONG nDolbyLoFltSum = 0;
slouken@639
    67
static LONG nDolbyHiFltPos = 0;
slouken@639
    68
static LONG nDolbyHiFltSum = 0;
slouken@639
    69
slouken@639
    70
// Reverb: 4 delay lines + high-pass filter + low-pass filter
slouken@639
    71
#ifndef MODPLUG_NO_REVERB
slouken@639
    72
static LONG nReverbSize = 0;
slouken@639
    73
static LONG nReverbBufferPos = 0;
slouken@639
    74
static LONG nReverbSize2 = 0;
slouken@639
    75
static LONG nReverbBufferPos2 = 0;
slouken@639
    76
static LONG nReverbSize3 = 0;
slouken@639
    77
static LONG nReverbBufferPos3 = 0;
slouken@639
    78
static LONG nReverbSize4 = 0;
slouken@639
    79
static LONG nReverbBufferPos4 = 0;
slouken@639
    80
static LONG nReverbLoFltSum = 0;
slouken@639
    81
static LONG nReverbLoFltPos = 0;
slouken@639
    82
static LONG nReverbLoDlyPos = 0;
slouken@639
    83
static LONG nFilterAttn = 0;
slouken@639
    84
static LONG gRvbLowPass[8];
slouken@639
    85
static LONG gRvbLPPos = 0;
slouken@639
    86
static LONG gRvbLPSum = 0;
slouken@639
    87
static LONG ReverbLoFilterBuffer[XBASSBUFFERSIZE];
slouken@639
    88
static LONG ReverbLoFilterDelay[XBASSBUFFERSIZE];
slouken@639
    89
static LONG ReverbBuffer[REVERBBUFFERSIZE];
slouken@639
    90
static LONG ReverbBuffer2[REVERBBUFFERSIZE2];
slouken@639
    91
static LONG ReverbBuffer3[REVERBBUFFERSIZE3];
slouken@639
    92
static LONG ReverbBuffer4[REVERBBUFFERSIZE4];
slouken@639
    93
#endif
slouken@639
    94
static LONG XBassBuffer[XBASSBUFFERSIZE];
slouken@639
    95
static LONG XBassDelay[XBASSBUFFERSIZE];
slouken@639
    96
static LONG DolbyLoFilterBuffer[XBASSBUFFERSIZE];
slouken@639
    97
static LONG DolbyLoFilterDelay[XBASSBUFFERSIZE];
slouken@639
    98
static LONG DolbyHiFilterBuffer[FILTERBUFFERSIZE];
slouken@639
    99
static LONG SurroundBuffer[SURROUNDBUFFERSIZE];
slouken@639
   100
slouken@639
   101
// Access the main temporary mix buffer directly: avoids an extra pointer
slouken@639
   102
extern int MixSoundBuffer[MIXBUFFERSIZE*2];
slouken@639
   103
//cextern int MixReverbBuffer[MIXBUFFERSIZE*2];
slouken@639
   104
extern int MixReverbBuffer[MIXBUFFERSIZE*2];
slouken@639
   105
slouken@639
   106
static UINT GetMaskFromSize(UINT len)
slouken@639
   107
//-----------------------------------
slouken@639
   108
{
slouken@639
   109
	UINT n = 2;
slouken@639
   110
	while (n <= len) n <<= 1;
slouken@639
   111
	return ((n >> 1) - 1);
slouken@639
   112
}
slouken@639
   113
slouken@639
   114
slouken@639
   115
void CSoundFile::InitializeDSP(BOOL bReset)
slouken@639
   116
//-----------------------------------------
slouken@639
   117
{
slouken@639
   118
	if (!m_nReverbDelay) m_nReverbDelay = 100;
slouken@639
   119
	if (!m_nXBassRange) m_nXBassRange = XBASS_DELAY;
slouken@639
   120
	if (!m_nProLogicDelay) m_nProLogicDelay = 20;
slouken@639
   121
	if (m_nXBassDepth > 8) m_nXBassDepth = 8;
slouken@639
   122
	if (m_nXBassDepth < 2) m_nXBassDepth = 2;
slouken@639
   123
	if (bReset)
slouken@639
   124
	{
slouken@639
   125
		// Noise Reduction
slouken@639
   126
		nLeftNR = nRightNR = 0;
slouken@639
   127
	}
slouken@639
   128
	// Pro-Logic Surround
slouken@639
   129
	nSurroundPos = nSurroundSize = 0;
slouken@639
   130
	nDolbyLoFltPos = nDolbyLoFltSum = nDolbyLoDlyPos = 0;
slouken@639
   131
	nDolbyHiFltPos = nDolbyHiFltSum = 0;
slouken@639
   132
	if (gdwSoundSetup & SNDMIX_SURROUND)
slouken@639
   133
	{
slouken@639
   134
		memset(DolbyLoFilterBuffer, 0, sizeof(DolbyLoFilterBuffer));
slouken@639
   135
		memset(DolbyHiFilterBuffer, 0, sizeof(DolbyHiFilterBuffer));
slouken@639
   136
		memset(DolbyLoFilterDelay, 0, sizeof(DolbyLoFilterDelay));
slouken@639
   137
		memset(SurroundBuffer, 0, sizeof(SurroundBuffer));
slouken@639
   138
		nSurroundSize = (gdwMixingFreq * m_nProLogicDelay) / 1000;
slouken@639
   139
		if (nSurroundSize > SURROUNDBUFFERSIZE) nSurroundSize = SURROUNDBUFFERSIZE;
slouken@639
   140
		if (m_nProLogicDepth < 8) nDolbyDepth = (32 >> m_nProLogicDepth) + 32;
slouken@639
   141
		else nDolbyDepth = (m_nProLogicDepth < 16) ? (8 + (m_nProLogicDepth - 8) * 7) : 64;
slouken@639
   142
		nDolbyDepth >>= 2;
slouken@639
   143
	}
slouken@639
   144
	// Reverb Setup
slouken@639
   145
#ifndef MODPLUG_NO_REVERB
slouken@639
   146
	if (gdwSoundSetup & SNDMIX_REVERB)
slouken@639
   147
	{
slouken@639
   148
		UINT nrs = (gdwMixingFreq * m_nReverbDelay) / 1000;
slouken@639
   149
		UINT nfa = m_nReverbDepth+1;
slouken@639
   150
		if (nrs > REVERBBUFFERSIZE) nrs = REVERBBUFFERSIZE;
slouken@639
   151
		if ((bReset) || (nrs != (UINT)nReverbSize) || (nfa != (UINT)nFilterAttn))
slouken@639
   152
		{
slouken@639
   153
			nFilterAttn = nfa;
slouken@639
   154
			nReverbSize = nrs;
slouken@639
   155
			nReverbBufferPos = nReverbBufferPos2 = nReverbBufferPos3 = nReverbBufferPos4 = 0;
slouken@639
   156
			nReverbLoFltSum = nReverbLoFltPos = nReverbLoDlyPos = 0;
slouken@639
   157
			gRvbLPSum = gRvbLPPos = 0;
slouken@639
   158
			nReverbSize2 = (nReverbSize * 13) / 17;
slouken@639
   159
			if (nReverbSize2 > REVERBBUFFERSIZE2) nReverbSize2 = REVERBBUFFERSIZE2;
slouken@639
   160
			nReverbSize3 = (nReverbSize * 7) / 13;
slouken@639
   161
			if (nReverbSize3 > REVERBBUFFERSIZE3) nReverbSize3 = REVERBBUFFERSIZE3;
slouken@639
   162
			nReverbSize4 = (nReverbSize * 7) / 19;
slouken@639
   163
			if (nReverbSize4 > REVERBBUFFERSIZE4) nReverbSize4 = REVERBBUFFERSIZE4;
slouken@639
   164
			memset(ReverbLoFilterBuffer, 0, sizeof(ReverbLoFilterBuffer));
slouken@639
   165
			memset(ReverbLoFilterDelay, 0, sizeof(ReverbLoFilterDelay));
slouken@639
   166
			memset(ReverbBuffer, 0, sizeof(ReverbBuffer));
slouken@639
   167
			memset(ReverbBuffer2, 0, sizeof(ReverbBuffer2));
slouken@639
   168
			memset(ReverbBuffer3, 0, sizeof(ReverbBuffer3));
slouken@639
   169
			memset(ReverbBuffer4, 0, sizeof(ReverbBuffer4));
slouken@639
   170
			memset(gRvbLowPass, 0, sizeof(gRvbLowPass));
slouken@639
   171
		}
slouken@639
   172
	} else nReverbSize = 0;
slouken@639
   173
#endif
slouken@639
   174
	BOOL bResetBass = FALSE;
slouken@639
   175
	// Bass Expansion Reset
slouken@639
   176
	if (gdwSoundSetup & SNDMIX_MEGABASS)
slouken@639
   177
	{
slouken@639
   178
		UINT nXBassSamples = (gdwMixingFreq * m_nXBassRange) / 10000;
slouken@639
   179
		if (nXBassSamples > XBASSBUFFERSIZE) nXBassSamples = XBASSBUFFERSIZE;
slouken@639
   180
		UINT mask = GetMaskFromSize(nXBassSamples);
slouken@639
   181
		if ((bReset) || (mask != (UINT)nXBassMask))
slouken@639
   182
		{
slouken@639
   183
			nXBassMask = mask;
slouken@639
   184
			bResetBass = TRUE;
slouken@639
   185
		}
slouken@639
   186
	} else
slouken@639
   187
	{
slouken@639
   188
		nXBassMask = 0;
slouken@639
   189
		bResetBass = TRUE;
slouken@639
   190
	}
slouken@639
   191
	if (bResetBass)
slouken@639
   192
	{
slouken@639
   193
		nXBassSum = nXBassBufferPos = nXBassDlyPos = 0;
slouken@639
   194
		memset(XBassBuffer, 0, sizeof(XBassBuffer));
slouken@639
   195
		memset(XBassDelay, 0, sizeof(XBassDelay));
slouken@639
   196
	}
slouken@639
   197
}
slouken@639
   198
slouken@639
   199
slouken@639
   200
void CSoundFile::ProcessStereoDSP(int count)
slouken@639
   201
//------------------------------------------
slouken@639
   202
{
slouken@639
   203
#ifndef MODPLUG_NO_REVERB
slouken@639
   204
	// Reverb
slouken@639
   205
	if (gdwSoundSetup & SNDMIX_REVERB)
slouken@639
   206
	{
slouken@639
   207
		int *pr = MixSoundBuffer, *pin = MixReverbBuffer, rvbcount = count;
slouken@639
   208
		do
slouken@639
   209
		{
slouken@639
   210
			int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2]
slouken@639
   211
					+ ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4];	// echo = reverb signal
slouken@639
   212
			// Delay line and remove Low Frequencies			// v = original signal
slouken@639
   213
			int echodly = ReverbLoFilterDelay[nReverbLoDlyPos];	// echodly = delayed signal
slouken@639
   214
			ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1;
slouken@639
   215
			nReverbLoDlyPos++;
slouken@639
   216
			nReverbLoDlyPos &= 0x1F;
slouken@639
   217
			int n = nReverbLoFltPos;
slouken@639
   218
			nReverbLoFltSum -= ReverbLoFilterBuffer[n];
slouken@639
   219
			int tmp = echo / 128;
slouken@639
   220
			ReverbLoFilterBuffer[n] = tmp;
slouken@639
   221
			nReverbLoFltSum += tmp;
slouken@639
   222
			echodly -= nReverbLoFltSum;
slouken@639
   223
			nReverbLoFltPos = (n + 1) & 0x3F;
slouken@639
   224
			// Reverb
slouken@639
   225
			int v = (pin[0]+pin[1]) >> nFilterAttn;
slouken@639
   226
			pr[0] += pin[0] + echodly;
slouken@639
   227
			pr[1] += pin[1] + echodly;
slouken@639
   228
			v += echodly >> 2;
slouken@639
   229
			ReverbBuffer3[nReverbBufferPos3] = v;
slouken@639
   230
			ReverbBuffer4[nReverbBufferPos4] = v;
slouken@639
   231
			v += echodly >> 4;
slouken@639
   232
			v >>= 1;
slouken@639
   233
			gRvbLPSum -= gRvbLowPass[gRvbLPPos];
slouken@639
   234
			gRvbLPSum += v;
slouken@639
   235
			gRvbLowPass[gRvbLPPos] = v;
slouken@639
   236
			gRvbLPPos++;
slouken@639
   237
			gRvbLPPos &= 7;
slouken@639
   238
			int vlp = gRvbLPSum >> 2;
slouken@639
   239
			ReverbBuffer[nReverbBufferPos] = vlp;
slouken@639
   240
			ReverbBuffer2[nReverbBufferPos2] = vlp;
slouken@639
   241
			if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0;
slouken@639
   242
			if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0;
slouken@639
   243
			if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0;
slouken@639
   244
			if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0;
slouken@639
   245
			pr += 2;
slouken@639
   246
			pin += 2;
slouken@639
   247
		} while (--rvbcount);
slouken@639
   248
	}
slouken@639
   249
#endif
slouken@639
   250
	// Dolby Pro-Logic Surround
slouken@639
   251
	if (gdwSoundSetup & SNDMIX_SURROUND)
slouken@639
   252
	{
slouken@639
   253
		int *pr = MixSoundBuffer, n = nDolbyLoFltPos;
slouken@639
   254
		for (int r=count; r; r--)
slouken@639
   255
		{
slouken@639
   256
			int v = (pr[0]+pr[1]+DOLBYATTNROUNDUP) >> (nDolbyHiFltAttn+1);
slouken@639
   257
#ifndef MODPLUG_FASTSOUNDLIB
slouken@639
   258
			v *= (int)nDolbyDepth;
slouken@639
   259
#endif
slouken@639
   260
			// Low-Pass Filter
slouken@639
   261
			nDolbyHiFltSum -= DolbyHiFilterBuffer[nDolbyHiFltPos];
slouken@639
   262
			DolbyHiFilterBuffer[nDolbyHiFltPos] = v;
slouken@639
   263
			nDolbyHiFltSum += v;
slouken@639
   264
			v = nDolbyHiFltSum;
slouken@639
   265
			nDolbyHiFltPos++;
slouken@639
   266
			nDolbyHiFltPos &= nDolbyHiFltMask;
slouken@639
   267
			// Surround
slouken@639
   268
			int secho = SurroundBuffer[nSurroundPos];
slouken@639
   269
			SurroundBuffer[nSurroundPos] = v;
slouken@639
   270
			// Delay line and remove low frequencies
slouken@639
   271
			v = DolbyLoFilterDelay[nDolbyLoDlyPos];		// v = delayed signal
slouken@639
   272
			DolbyLoFilterDelay[nDolbyLoDlyPos] = secho;	// secho = signal
slouken@639
   273
			nDolbyLoDlyPos++;
slouken@639
   274
			nDolbyLoDlyPos &= 0x1F;
slouken@639
   275
			nDolbyLoFltSum -= DolbyLoFilterBuffer[n];
slouken@639
   276
			int tmp = secho / 64;
slouken@639
   277
			DolbyLoFilterBuffer[n] = tmp;
slouken@639
   278
			nDolbyLoFltSum += tmp;
slouken@639
   279
			v -= nDolbyLoFltSum;
slouken@639
   280
			n++;
slouken@639
   281
			n &= 0x3F;
slouken@639
   282
			// Add echo
slouken@639
   283
			pr[0] += v;
slouken@639
   284
			pr[1] -= v;
slouken@639
   285
			if (++nSurroundPos >= nSurroundSize) nSurroundPos = 0;
slouken@639
   286
			pr += 2;
slouken@639
   287
		}
slouken@639
   288
		nDolbyLoFltPos = n;
slouken@639
   289
	}
slouken@639
   290
	// Bass Expansion
slouken@639
   291
	if (gdwSoundSetup & SNDMIX_MEGABASS)
slouken@639
   292
	{
slouken@639
   293
		int *px = MixSoundBuffer;
slouken@639
   294
		int xba = m_nXBassDepth+1, xbamask = (1 << xba) - 1;
slouken@639
   295
		int n = nXBassBufferPos;
slouken@639
   296
		for (int x=count; x; x--)
slouken@639
   297
		{
slouken@639
   298
			nXBassSum -= XBassBuffer[n];
slouken@639
   299
			int tmp0 = px[0] + px[1];
slouken@639
   300
			int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba;
slouken@639
   301
			XBassBuffer[n] = tmp;
slouken@639
   302
			nXBassSum += tmp;
slouken@639
   303
			int v = XBassDelay[nXBassDlyPos];
slouken@639
   304
			XBassDelay[nXBassDlyPos] = px[0];
slouken@639
   305
			px[0] = v + nXBassSum;
slouken@639
   306
			v = XBassDelay[nXBassDlyPos+1];
slouken@639
   307
			XBassDelay[nXBassDlyPos+1] = px[1];
slouken@639
   308
			px[1] = v + nXBassSum;
slouken@639
   309
			nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask;
slouken@639
   310
			px += 2;
slouken@639
   311
			n++;
slouken@639
   312
			n &= nXBassMask;
slouken@639
   313
		}
slouken@639
   314
		nXBassBufferPos = n;
slouken@639
   315
	}
slouken@639
   316
	// Noise Reduction
slouken@639
   317
	if (gdwSoundSetup & SNDMIX_NOISEREDUCTION)
slouken@639
   318
	{
slouken@639
   319
		int n1 = nLeftNR, n2 = nRightNR;
slouken@639
   320
		int *pnr = MixSoundBuffer;
slouken@639
   321
		for (int nr=count; nr; nr--)
slouken@639
   322
		{
slouken@639
   323
			int vnr = pnr[0] >> 1;
slouken@639
   324
			pnr[0] = vnr + n1;
slouken@639
   325
			n1 = vnr;
slouken@639
   326
			vnr = pnr[1] >> 1;
slouken@639
   327
			pnr[1] = vnr + n2;
slouken@639
   328
			n2 = vnr;
slouken@639
   329
			pnr += 2;
slouken@639
   330
		}
slouken@639
   331
		nLeftNR = n1;
slouken@639
   332
		nRightNR = n2;
slouken@639
   333
	}
slouken@639
   334
}
slouken@639
   335
slouken@639
   336
slouken@639
   337
void CSoundFile::ProcessMonoDSP(int count)
slouken@639
   338
//----------------------------------------
slouken@639
   339
{
slouken@639
   340
#ifndef MODPLUG_NO_REVERB
slouken@639
   341
	// Reverb
slouken@639
   342
	if (gdwSoundSetup & SNDMIX_REVERB)
slouken@639
   343
	{
slouken@639
   344
		int *pr = MixSoundBuffer, rvbcount = count, *pin = MixReverbBuffer;
slouken@639
   345
		do
slouken@639
   346
		{
slouken@639
   347
			int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2]
slouken@639
   348
					+ ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4];	// echo = reverb signal
slouken@639
   349
			// Delay line and remove Low Frequencies			// v = original signal
slouken@639
   350
			int echodly = ReverbLoFilterDelay[nReverbLoDlyPos];	// echodly = delayed signal
slouken@639
   351
			ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1;
slouken@639
   352
			nReverbLoDlyPos++;
slouken@639
   353
			nReverbLoDlyPos &= 0x1F;
slouken@639
   354
			int n = nReverbLoFltPos;
slouken@639
   355
			nReverbLoFltSum -= ReverbLoFilterBuffer[n];
slouken@639
   356
			int tmp = echo / 128;
slouken@639
   357
			ReverbLoFilterBuffer[n] = tmp;
slouken@639
   358
			nReverbLoFltSum += tmp;
slouken@639
   359
			echodly -= nReverbLoFltSum;
slouken@639
   360
			nReverbLoFltPos = (n + 1) & 0x3F;
slouken@639
   361
			// Reverb
slouken@639
   362
			int v = pin[0] >> (nFilterAttn-1);
slouken@639
   363
			*pr++ += pin[0] + echodly;
slouken@639
   364
			pin++;
slouken@639
   365
			v += echodly >> 2;
slouken@639
   366
			ReverbBuffer3[nReverbBufferPos3] = v;
slouken@639
   367
			ReverbBuffer4[nReverbBufferPos4] = v;
slouken@639
   368
			v += echodly >> 4;
slouken@639
   369
			v >>= 1;
slouken@639
   370
			gRvbLPSum -= gRvbLowPass[gRvbLPPos];
slouken@639
   371
			gRvbLPSum += v;
slouken@639
   372
			gRvbLowPass[gRvbLPPos] = v;
slouken@639
   373
			gRvbLPPos++;
slouken@639
   374
			gRvbLPPos &= 7;
slouken@639
   375
			int vlp = gRvbLPSum >> 2;
slouken@639
   376
			ReverbBuffer[nReverbBufferPos] = vlp;
slouken@639
   377
			ReverbBuffer2[nReverbBufferPos2] = vlp;
slouken@639
   378
			if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0;
slouken@639
   379
			if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0;
slouken@639
   380
			if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0;
slouken@639
   381
			if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0;
slouken@639
   382
		} while (--rvbcount);
slouken@639
   383
	}
slouken@639
   384
#endif
slouken@639
   385
	// Bass Expansion
slouken@639
   386
	if (gdwSoundSetup & SNDMIX_MEGABASS)
slouken@639
   387
	{
slouken@639
   388
		int *px = MixSoundBuffer;
slouken@639
   389
		int xba = m_nXBassDepth, xbamask = (1 << xba)-1;
slouken@639
   390
		int n = nXBassBufferPos;
slouken@639
   391
		for (int x=count; x; x--)
slouken@639
   392
		{
slouken@639
   393
			nXBassSum -= XBassBuffer[n];
slouken@639
   394
			int tmp0 = *px;
slouken@639
   395
			int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba;
slouken@639
   396
			XBassBuffer[n] = tmp;
slouken@639
   397
			nXBassSum += tmp;
slouken@639
   398
			int v = XBassDelay[nXBassDlyPos];
slouken@639
   399
			XBassDelay[nXBassDlyPos] = *px;
slouken@639
   400
			*px++ = v + nXBassSum;
slouken@639
   401
			nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask;
slouken@639
   402
			n++;
slouken@639
   403
			n &= nXBassMask;
slouken@639
   404
		}
slouken@639
   405
		nXBassBufferPos = n;
slouken@639
   406
	}
slouken@639
   407
	// Noise Reduction
slouken@639
   408
	if (gdwSoundSetup & SNDMIX_NOISEREDUCTION)
slouken@639
   409
	{
slouken@639
   410
		int n = nLeftNR;
slouken@639
   411
		int *pnr = MixSoundBuffer;
slouken@639
   412
		for (int nr=count; nr; pnr++, nr--)
slouken@639
   413
		{
slouken@639
   414
			int vnr = *pnr >> 1;
slouken@639
   415
			*pnr = vnr + n;
slouken@639
   416
			n = vnr;
slouken@639
   417
		}
slouken@639
   418
		nLeftNR = n;
slouken@639
   419
	}
slouken@639
   420
}
slouken@639
   421
slouken@639
   422
slouken@639
   423
/////////////////////////////////////////////////////////////////
slouken@639
   424
// Clean DSP Effects interface
slouken@639
   425
slouken@639
   426
// [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
slouken@639
   427
BOOL CSoundFile::SetReverbParameters(UINT nDepth, UINT nDelay)
slouken@639
   428
//------------------------------------------------------------
slouken@639
   429
{
slouken@639
   430
	if (nDepth > 100) nDepth = 100;
slouken@639
   431
	UINT gain = nDepth / 20;
slouken@639
   432
	if (gain > 4) gain = 4;
slouken@639
   433
	m_nReverbDepth = 4 - gain;
slouken@639
   434
	if (nDelay < 40) nDelay = 40;
slouken@639
   435
	if (nDelay > 250) nDelay = 250;
slouken@639
   436
	m_nReverbDelay = nDelay;
slouken@639
   437
	return TRUE;
slouken@639
   438
}
slouken@639
   439
slouken@639
   440
slouken@639
   441
// [XBass level 0(quiet)-100(loud)], [cutoff in Hz 20-100]
slouken@639
   442
BOOL CSoundFile::SetXBassParameters(UINT nDepth, UINT nRange)
slouken@639
   443
//-----------------------------------------------------------
slouken@639
   444
{
slouken@639
   445
	if (nDepth > 100) nDepth = 100;
slouken@639
   446
	UINT gain = nDepth / 20;
slouken@639
   447
	if (gain > 4) gain = 4;
slouken@639
   448
	m_nXBassDepth = 8 - gain;	// filter attenuation 1/256 .. 1/16
slouken@639
   449
	UINT range = nRange / 5;
slouken@639
   450
	if (range > 5) range -= 5; else range = 0;
slouken@639
   451
	if (nRange > 16) nRange = 16;
slouken@639
   452
	m_nXBassRange = 21 - range;	// filter average on 0.5-1.6ms
slouken@639
   453
	return TRUE;
slouken@639
   454
}
slouken@639
   455
slouken@639
   456
slouken@639
   457
// [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-50ms]
slouken@639
   458
BOOL CSoundFile::SetSurroundParameters(UINT nDepth, UINT nDelay)
slouken@639
   459
//--------------------------------------------------------------
slouken@639
   460
{
slouken@639
   461
	UINT gain = (nDepth * 16) / 100;
slouken@639
   462
	if (gain > 16) gain = 16;
slouken@639
   463
	if (gain < 1) gain = 1;
slouken@639
   464
	m_nProLogicDepth = gain;
slouken@639
   465
	if (nDelay < 4) nDelay = 4;
slouken@639
   466
	if (nDelay > 50) nDelay = 50;
slouken@639
   467
	m_nProLogicDelay = nDelay;
slouken@639
   468
	return TRUE;
slouken@639
   469
}
slouken@639
   470
slouken@639
   471
BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ)
slouken@639
   472
//----------------------------------------------------------------------------------------------------------------------------
slouken@639
   473
{
slouken@639
   474
	DWORD d = gdwSoundSetup & ~(SNDMIX_SURROUND | SNDMIX_NORESAMPLING | SNDMIX_REVERB | SNDMIX_HQRESAMPLER | SNDMIX_MEGABASS | SNDMIX_NOISEREDUCTION | SNDMIX_EQ);
slouken@639
   475
	if (bSurround) d |= SNDMIX_SURROUND;
slouken@639
   476
	if (bNoOverSampling) d |= SNDMIX_NORESAMPLING;
slouken@639
   477
	if (bReverb) d |= SNDMIX_REVERB;
slouken@639
   478
	if (hqido) d |= SNDMIX_HQRESAMPLER;
slouken@639
   479
	if (bMegaBass) d |= SNDMIX_MEGABASS;
slouken@639
   480
	if (bNR) d |= SNDMIX_NOISEREDUCTION;
slouken@639
   481
	if (bEQ) d |= SNDMIX_EQ;
slouken@639
   482
	gdwSoundSetup = d;
slouken@639
   483
	InitPlayer(FALSE);
slouken@639
   484
	return TRUE;
slouken@639
   485
}