summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/sndmix.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/modplug/sndmix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/sndmix.cpp1248
1 files changed, 1248 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/sndmix.cpp b/core/multimedia/opieplayer/modplug/sndmix.cpp
new file mode 100644
index 0000000..bfc5f4a
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/sndmix.cpp
@@ -0,0 +1,1248 @@
1/*
2 * This program is free software; you can redistribute it and modify it
3 * under the terms of the GNU General Public License as published by the
4 * Free Software Foundation; either version 2 of the license or (at your
5 * option) any later version.
6 *
7 * Authors: Olivier Lapicque <olivierl@jps.net>
8*/
9
10#include "stdafx.h"
11#include "sndfile.h"
12
13#ifdef MODPLUG_TRACKER
14#define ENABLE_STEREOVU
15#endif
16
17// Volume ramp length, in 1/10 ms
18 #define VOLUMERAMPLEN 146// 1.46ms = 64 samples at 44.1kHz
19
20// VU-Meter
21 #define VUMETER_DECAY 4
22
23// SNDMIX: These are global flags for playback control
24UINT CSoundFile::m_nStereoSeparation = 128;
25LONG CSoundFile::m_nStreamVolume = 0x8000;
26UINT CSoundFile::m_nMaxMixChannels = 32;
27// Mixing Configuration (SetWaveConfig)
28DWORD CSoundFile::gdwSysInfo = 0;
29DWORD CSoundFile::gnChannels = 1;
30DWORD CSoundFile::gdwSoundSetup = 0;
31DWORD CSoundFile::gdwMixingFreq = 44100;
32DWORD CSoundFile::gnBitsPerSample = 16;
33// Mixing data initialized in
34UINT CSoundFile::gnAGC = AGC_UNITY;
35UINT CSoundFile::gnVolumeRampSamples = 64;
36UINT CSoundFile::gnVUMeter = 0;
37UINT CSoundFile::gnCPUUsage = 0;
38LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL;
39PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL;
40LONG gnDryROfsVol = 0;
41LONG gnDryLOfsVol = 0;
42LONG gnRvbROfsVol = 0;
43LONG gnRvbLOfsVol = 0;
44int gbInitPlugins = 0;
45
46typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG);
47
48extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
49extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
50extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
51extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
52extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC);
53extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits);
54extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples);
55extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
56extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples);
57
58extern const short int ModSinusTable[64];
59extern const short int ModRampDownTable[64];
60extern const short int ModSquareTable[64];
61extern const short int ModRandomTable[64];
62extern const DWORD LinearSlideUpTable[256];
63extern const DWORD LinearSlideDownTable[256];
64extern const DWORD FineLinearSlideUpTable[16];
65extern const DWORD FineLinearSlideDownTable[16];
66 extern const signed char ft2VibratoTable[256];// -64 .. +64
67extern int MixSoundBuffer[MIXBUFFERSIZE*4];
68extern int MixRearBuffer[MIXBUFFERSIZE*2];
69UINT gnReverbSend;
70
71
72// Log tables for pre-amp
73// We don't want the tracker to get too loud
74const UINT PreAmpTable[16] =
75{
76 0x60, 0x60, 0x60, 0x70,// 0-7
77 0x80, 0x88, 0x90, 0x98,// 8-15
78 0xA0, 0xA4, 0xA8, 0xB0,// 16-23
79 0xB4, 0xB8, 0xBC, 0xC0,// 24-31
80};
81
82const UINT PreAmpAGCTable[16] =
83{
84 0x60, 0x60, 0x60, 0x60,
85 0x68, 0x70, 0x78, 0x80,
86 0x84, 0x88, 0x8C, 0x90,
87 0x94, 0x98, 0x9C, 0xA0,
88};
89
90
91// Return (a*b)/c - no divide error
92int _muldiv(long a, long b, long c)
93{
94#ifdef WIN32
95 int sign, result;
96 _asm {
97 mov eax, a
98 mov ebx, b
99 or eax, eax
100 mov edx, eax
101 jge aneg
102 neg eax
103aneg:
104 xor edx, ebx
105 or ebx, ebx
106 mov ecx, c
107 jge bneg
108 neg ebx
109bneg:
110 xor edx, ecx
111 or ecx, ecx
112 mov sign, edx
113 jge cneg
114 neg ecx
115cneg:
116 mul ebx
117 cmp edx, ecx
118 jae diverr
119 div ecx
120 jmp ok
121diverr:
122 mov eax, 0x7fffffff
123ok:
124 mov edx, sign
125 or edx, edx
126 jge rneg
127 neg eax
128rneg:
129 mov result, eax
130 }
131 return result;
132#else
133 return ((unsigned long long) a * (unsigned long long) b ) / c;
134#endif
135}
136
137
138// Return (a*b+c/2)/c - no divide error
139int _muldivr(long a, long b, long c)
140{
141#ifdef WIN32
142 int sign, result;
143 _asm {
144 mov eax, a
145 mov ebx, b
146 or eax, eax
147 mov edx, eax
148 jge aneg
149 neg eax
150aneg:
151 xor edx, ebx
152 or ebx, ebx
153 mov ecx, c
154 jge bneg
155 neg ebx
156bneg:
157 xor edx, ecx
158 or ecx, ecx
159 mov sign, edx
160 jge cneg
161 neg ecx
162cneg:
163 mul ebx
164 mov ebx, ecx
165 shr ebx, 1
166 add eax, ebx
167 adc edx, 0
168 cmp edx, ecx
169 jae diverr
170 div ecx
171 jmp ok
172diverr:
173 mov eax, 0x7fffffff
174ok:
175 mov edx, sign
176 or edx, edx
177 jge rneg
178 neg eax
179rneg:
180 mov result, eax
181 }
182 return result;
183#else
184 return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c;
185#endif
186}
187
188
189BOOL CSoundFile::InitPlayer(BOOL bReset)
190//--------------------------------------
191{
192 if (m_nMaxMixChannels > MAX_CHANNELS) m_nMaxMixChannels = MAX_CHANNELS;
193 if (gdwMixingFreq < 4000) gdwMixingFreq = 4000;
194 if (gdwMixingFreq > MAX_SAMPLE_RATE) gdwMixingFreq = MAX_SAMPLE_RATE;
195 gnVolumeRampSamples = (gdwMixingFreq * VOLUMERAMPLEN) / 100000;
196 if (gnVolumeRampSamples < 8) gnVolumeRampSamples = 8;
197 gnDryROfsVol = gnDryLOfsVol = 0;
198 gnRvbROfsVol = gnRvbLOfsVol = 0;
199 if (bReset)
200 {
201 gnVUMeter = 0;
202 gnCPUUsage = 0;
203 }
204 gbInitPlugins = (bReset) ? 3 : 1;
205 InitializeDSP(bReset);
206 return TRUE;
207}
208
209
210BOOL CSoundFile::FadeSong(UINT msec)
211//----------------------------------
212{
213 LONG nsamples = _muldiv(msec, gdwMixingFreq, 1000);
214 if (nsamples <= 0) return FALSE;
215 if (nsamples > 0x100000) nsamples = 0x100000;
216 m_nBufferCount = nsamples;
217 LONG nRampLength = m_nBufferCount;
218 // Ramp everything down
219 for (UINT noff=0; noff < m_nMixChannels; noff++)
220 {
221 MODCHANNEL *pramp = &Chn[ChnMix[noff]];
222 if (!pramp) continue;
223 pramp->nNewLeftVol = pramp->nNewRightVol = 0;
224 pramp->nRightRamp = (-pramp->nRightVol << VOLUMERAMPPRECISION) / nRampLength;
225 pramp->nLeftRamp = (-pramp->nLeftVol << VOLUMERAMPPRECISION) / nRampLength;
226 pramp->nRampRightVol = pramp->nRightVol << VOLUMERAMPPRECISION;
227 pramp->nRampLeftVol = pramp->nLeftVol << VOLUMERAMPPRECISION;
228 pramp->nRampLength = nRampLength;
229 pramp->dwFlags |= CHN_VOLUMERAMP;
230 }
231 m_dwSongFlags |= SONG_FADINGSONG;
232 return TRUE;
233}
234
235
236BOOL CSoundFile::GlobalFadeSong(UINT msec)
237//----------------------------------------
238{
239 if (m_dwSongFlags & SONG_GLOBALFADE) return FALSE;
240 m_nGlobalFadeMaxSamples = _muldiv(msec, gdwMixingFreq, 1000);
241 m_nGlobalFadeSamples = m_nGlobalFadeMaxSamples;
242 m_dwSongFlags |= SONG_GLOBALFADE;
243 return TRUE;
244}
245
246
247UINT CSoundFile::Read(LPVOID lpDestBuffer, UINT cbBuffer)
248//-------------------------------------------------------
249{
250 LPBYTE lpBuffer = (LPBYTE)lpDestBuffer;
251 LPCONVERTPROC pCvt = X86_Convert32To8;
252 UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0;
253 LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF;
254 UINT nMaxPlugins;
255
256 {
257 nMaxPlugins = MAX_MIXPLUGINS;
258 while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--;
259 }
260 m_nMixStat = 0;
261 lSampleSize = gnChannels;
262 if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; }
263#ifndef FASTSOUNDLIB
264 else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; }
265 else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; }
266#endif
267 lMax = cbBuffer / lSampleSize;
268 if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0;
269 lRead = lMax;
270 if (m_dwSongFlags & SONG_ENDREACHED) goto MixDone;
271 while (lRead > 0)
272 {
273 // Update Channel Data
274 if (!m_nBufferCount)
275 {
276#ifndef FASTSOUNDLIB
277 if (m_dwSongFlags & SONG_FADINGSONG)
278 {
279 m_dwSongFlags |= SONG_ENDREACHED;
280 m_nBufferCount = lRead;
281 } else
282#endif
283 if (!ReadNote())
284 {
285#ifndef FASTSOUNDLIB
286 if (!FadeSong(FADESONGDELAY))
287#endif
288 {
289 m_dwSongFlags |= SONG_ENDREACHED;
290 if (lRead == lMax) goto MixDone;
291 m_nBufferCount = lRead;
292 }
293 }
294 }
295 lCount = m_nBufferCount;
296 if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE;
297 if (lCount > lRead) lCount = lRead;
298 if (!lCount) break;
299 lSampleCount = lCount;
300#ifndef NO_REVERB
301 gnReverbSend = 0;
302#endif
303 // Resetting sound buffer
304 X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
305 if (gnChannels >= 2)
306 {
307 lSampleCount *= 2;
308 m_nMixStat += CreateStereoMix(lCount);
309 ProcessStereoDSP(lCount);
310 } else
311 {
312 m_nMixStat += CreateStereoMix(lCount);
313 if (nMaxPlugins) ProcessPlugins(lCount);
314 ProcessStereoDSP(lCount);
315 X86_MonoFromStereo(MixSoundBuffer, lCount);
316 }
317 nStat++;
318#ifndef NO_AGC
319 // Automatic Gain Control
320 if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount);
321#endif
322 UINT lTotalSampleCount = lSampleCount;
323#ifndef FASTSOUNDLIB
324 // Multichannel
325 if (gnChannels > 2)
326 {
327 X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
328 lTotalSampleCount *= 2;
329 }
330 // Hook Function
331 if (gpSndMixHook)
332 {
333 gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels);
334 }
335#endif
336 // Perform clipping + VU-Meter
337 lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax);
338 // Buffer ready
339 lRead -= lCount;
340 m_nBufferCount -= lCount;
341 }
342MixDone:
343 if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize);
344 // VU-Meter
345 nVUMeterMin >>= (24-MIXING_ATTENUATION);
346 nVUMeterMax >>= (24-MIXING_ATTENUATION);
347 if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin;
348 if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF;
349 if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; }
350 return lMax - lRead;
351}
352
353
354
355/////////////////////////////////////////////////////////////////////////////
356// Handles navigation/effects
357
358BOOL CSoundFile::ProcessRow()
359//---------------------------
360{
361 if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay)
362 {
363 m_nPatternDelay = 0;
364 m_nFrameDelay = 0;
365 m_nTickCount = 0;
366 m_nRow = m_nNextRow;
367 // Reset Pattern Loop Effect
368 if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern;
369 // Check if pattern is valid
370 if (!(m_dwSongFlags & SONG_PATTERNLOOP))
371 {
372 m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
373 if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
374 while (m_nPattern >= MAX_PATTERNS)
375 {
376 // End of song ?
377 if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS))
378 {
379 //if (!m_nRepeatCount)
380 return FALSE; //never repeat entire song
381 if (!m_nRestartPos)
382 {
383 m_nMusicSpeed = m_nDefaultSpeed;
384 m_nMusicTempo = m_nDefaultTempo;
385 m_nGlobalVolume = m_nDefaultGlobalVolume;
386 for (UINT i=0; i<MAX_CHANNELS; i++)
387 {
388 Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF;
389 Chn[i].nFadeOutVol = 0;
390 if (i < m_nChannels)
391 {
392 Chn[i].nGlobalVol = ChnSettings[i].nVolume;
393 Chn[i].nVolume = ChnSettings[i].nVolume;
394 Chn[i].nPan = ChnSettings[i].nPan;
395 Chn[i].nPanSwing = Chn[i].nVolSwing = 0;
396 Chn[i].nOldVolParam = 0;
397 Chn[i].nOldOffset = 0;
398 Chn[i].nOldHiOffset = 0;
399 Chn[i].nPortamentoDest = 0;
400 if (!Chn[i].nLength)
401 {
402 Chn[i].dwFlags = ChnSettings[i].dwFlags;
403 Chn[i].nLoopStart = 0;
404 Chn[i].nLoopEnd = 0;
405 Chn[i].pHeader = NULL;
406 Chn[i].pSample = NULL;
407 Chn[i].pInstrument = NULL;
408 }
409 }
410 }
411 }
412 // if (m_nRepeatCount > 0) m_nRepeatCount--;
413 m_nCurrentPattern = m_nRestartPos;
414 m_nRow = 0;
415 if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE;
416 } else
417 {
418 m_nCurrentPattern++;
419 }
420 m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
421 if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
422 }
423 m_nNextPattern = m_nCurrentPattern;
424 }
425 // Weird stuff?
426 if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE;
427 // Should never happen
428 if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0;
429 m_nNextRow = m_nRow + 1;
430 if (m_nNextRow >= PatternSize[m_nPattern])
431 {
432 if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1;
433 m_nNextRow = 0;
434 }
435 // Reset channel values
436 MODCHANNEL *pChn = Chn;
437 MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels;
438 for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++)
439 {
440 pChn->nRowNote = m->note;
441 pChn->nRowInstr = m->instr;
442 pChn->nRowVolCmd = m->volcmd;
443 pChn->nRowVolume = m->vol;
444 pChn->nRowCommand = m->command;
445 pChn->nRowParam = m->param;
446
447 pChn->nLeftVol = pChn->nNewLeftVol;
448 pChn->nRightVol = pChn->nNewRightVol;
449 pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO);
450 pChn->nCommand = 0;
451 }
452 }
453 // Should we process tick0 effects?
454 if (!m_nMusicSpeed) m_nMusicSpeed = 1;
455 m_dwSongFlags |= SONG_FIRSTTICK;
456 if (m_nTickCount)
457 {
458 m_dwSongFlags &= ~SONG_FIRSTTICK;
459 if ((!(m_nType & MOD_TYPE_XM)) && (m_nTickCount < m_nMusicSpeed * (1 + m_nPatternDelay)))
460 {
461 if (!(m_nTickCount % m_nMusicSpeed)) m_dwSongFlags |= SONG_FIRSTTICK;
462 }
463
464 }
465 // Update Effects
466 return ProcessEffects();
467}
468
469
470////////////////////////////////////////////////////////////////////////////////////////////
471// Handles envelopes & mixer setup
472
473BOOL CSoundFile::ReadNote()
474//-------------------------
475{
476 if (!ProcessRow()) return FALSE;
477 ////////////////////////////////////////////////////////////////////////////////////
478 m_nTotalCount++;
479 if (!m_nMusicTempo) return FALSE;
480 m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8);
481 // Master Volume + Pre-Amplification / Attenuation setup
482 DWORD nMasterVol;
483 {
484 int nchn32 = (m_nChannels < 32) ? m_nChannels : 31;
485 if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6;
486 int realmastervol = m_nMasterVolume;
487 if (realmastervol > 0x80)
488 {
489 realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16;
490 }
491 UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1];
492 DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6;
493 if (mastervol > 0x200) mastervol = 0x200;
494 if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples))
495 {
496 mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples);
497 }
498 nMasterVol = (mastervol << 7) / attenuation;
499 if (nMasterVol > 0x180) nMasterVol = 0x180;
500 }
501 ////////////////////////////////////////////////////////////////////////////////////
502 // Update channels data
503 m_nMixChannels = 0;
504 MODCHANNEL *pChn = Chn;
505 for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++)
506 {
507 if ((pChn->dwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol)))
508 {
509 pChn->nLength = 0;
510 pChn->nROfs = pChn->nLOfs = 0;
511 }
512 // Check for unused channel
513 if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength)))
514 {
515 pChn->nVUMeter = 0;
516#ifdef ENABLE_STEREOVU
517 pChn->nLeftVU = pChn->nRightVU = 0;
518#endif
519 continue;
520 }
521 // Reset channel data
522 pChn->nInc = 0;
523 pChn->nRealVolume = 0;
524 pChn->nRealPan = pChn->nPan + pChn->nPanSwing;
525 if (pChn->nRealPan < 0) pChn->nRealPan = 0;
526 if (pChn->nRealPan > 256) pChn->nRealPan = 256;
527 pChn->nRampLength = 0;
528 // Calc Frequency
529 if ((pChn->nPeriod)&& (pChn->nLength))
530 {
531 int vol = pChn->nVolume + pChn->nVolSwing;
532
533 if (vol < 0) vol = 0;
534 if (vol > 256) vol = 256;
535 // Tremolo
536 if (pChn->dwFlags & CHN_TREMOLO)
537 {
538 UINT trempos = pChn->nTremoloPos & 0x3F;
539 if (vol > 0)
540 {
541 int tremattn = (m_nType & MOD_TYPE_XM) ? 5 : 6;
542 switch (pChn->nTremoloType & 0x03)
543 {
544 case 1:
545 vol += (ModRampDownTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
546 break;
547 case 2:
548 vol += (ModSquareTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
549 break;
550 case 3:
551 vol += (ModRandomTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
552 break;
553 default:
554 vol += (ModSinusTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
555 }
556 }
557 if ((m_nTickCount) || ((m_nType & (MOD_TYPE_STM|MOD_TYPE_S3M|MOD_TYPE_IT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
558 {
559 pChn->nTremoloPos = (trempos + pChn->nTremoloSpeed) & 0x3F;
560 }
561 }
562 // Tremor
563 if (pChn->nCommand == CMD_TREMOR)
564 {
565 UINT n = (pChn->nTremorParam >> 4) + (pChn->nTremorParam & 0x0F);
566 UINT ontime = pChn->nTremorParam >> 4;
567 if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) { n += 2; ontime++; }
568 UINT tremcount = (UINT)pChn->nTremorCount;
569 if (tremcount >= n) tremcount = 0;
570 if ((m_nTickCount) || (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))
571 {
572 if (tremcount >= ontime) vol = 0;
573 pChn->nTremorCount = (BYTE)(tremcount + 1);
574 }
575 pChn->dwFlags |= CHN_FASTVOLRAMP;
576 }
577 // Clip volume
578 if (vol < 0) vol = 0;
579 if (vol > 0x100) vol = 0x100;
580 vol <<= 6;
581 // Process Envelopes
582 if (pChn->pHeader)
583 {
584 INSTRUMENTHEADER *penv = pChn->pHeader;
585 // Volume Envelope
586 if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv))
587 {
588 int envpos = pChn->nVolEnvPosition;
589 UINT pt = penv->nVolEnv - 1;
590 for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++)
591 {
592 if (envpos <= penv->VolPoints[i])
593 {
594 pt = i;
595 break;
596 }
597 }
598 int x2 = penv->VolPoints[pt];
599 int x1, envvol;
600 if (envpos >= x2)
601 {
602 envvol = penv->VolEnv[pt] << 2;
603 x1 = x2;
604 } else
605 if (pt)
606 {
607 envvol = penv->VolEnv[pt-1] << 2;
608 x1 = penv->VolPoints[pt-1];
609 } else
610 {
611 envvol = 0;
612 x1 = 0;
613 }
614 if (envpos > x2) envpos = x2;
615 if ((x2 > x1) && (envpos > x1))
616 {
617 envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1);
618 }
619 if (envvol < 0) envvol = 0;
620 if (envvol > 256) envvol = 256;
621 vol = (vol * envvol) >> 8;
622 }
623 // Panning Envelope
624 if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv))
625 {
626 int envpos = pChn->nPanEnvPosition;
627 UINT pt = penv->nPanEnv - 1;
628 for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++)
629 {
630 if (envpos <= penv->PanPoints[i])
631 {
632 pt = i;
633 break;
634 }
635 }
636 int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt];
637 int x1, envpan;
638 if (envpos >= x2)
639 {
640 envpan = y2;
641 x1 = x2;
642 } else
643 if (pt)
644 {
645 envpan = penv->PanEnv[pt-1];
646 x1 = penv->PanPoints[pt-1];
647 } else
648 {
649 envpan = 128;
650 x1 = 0;
651 }
652 if ((x2 > x1) && (envpos > x1))
653 {
654 envpan += ((envpos - x1) * (y2 - envpan)) / (x2 - x1);
655 }
656 if (envpan < 0) envpan = 0;
657 if (envpan > 64) envpan = 64;
658 int pan = pChn->nPan;
659 if (pan >= 128)
660 {
661 pan += ((envpan - 32) * (256 - pan)) / 32;
662 } else
663 {
664 pan += ((envpan - 32) * (pan)) / 32;
665 }
666 if (pan < 0) pan = 0;
667 if (pan > 256) pan = 256;
668 pChn->nRealPan = pan;
669 }
670 // FadeOut volume
671 if (pChn->dwFlags & CHN_NOTEFADE)
672 {
673 UINT fadeout = penv->nFadeOut;
674 if (fadeout)
675 {
676 pChn->nFadeOutVol -= fadeout << 1;
677 if (pChn->nFadeOutVol <= 0) pChn->nFadeOutVol = 0;
678 vol = (vol * pChn->nFadeOutVol) >> 16;
679 } else
680 if (!pChn->nFadeOutVol)
681 {
682 vol = 0;
683 }
684 }
685 // Pitch/Pan separation
686 if ((penv->nPPS) && (pChn->nRealPan) && (pChn->nNote))
687 {
688 int pandelta = (int)pChn->nRealPan + (int)((int)(pChn->nNote - penv->nPPC - 1) * (int)penv->nPPS) / (int)8;
689 if (pandelta < 0) pandelta = 0;
690 if (pandelta > 256) pandelta = 256;
691 pChn->nRealPan = pandelta;
692 }
693 } else
694 {
695 // No Envelope: key off => note cut
696 if (pChn->dwFlags & CHN_NOTEFADE) // 1.41-: CHN_KEYOFF|CHN_NOTEFADE
697 {
698 pChn->nFadeOutVol = 0;
699 vol = 0;
700 }
701 }
702 // vol is 14-bits
703 if (vol)
704 {
705 // IMPORTANT: pChn->nRealVolume is 14 bits !!!
706 // -> _muldiv( 14+8, 6+6, 18); => RealVolume: 14-bit result (22+12-20)
707 pChn->nRealVolume = _muldiv(vol * m_nGlobalVolume, pChn->nGlobalVol * pChn->nInsVol, 1 << 20);
708 }
709 if (pChn->nPeriod < m_nMinPeriod) pChn->nPeriod = m_nMinPeriod;
710 int period = pChn->nPeriod;
711 if ((pChn->dwFlags & (CHN_GLISSANDO|CHN_PORTAMENTO)) ==(CHN_GLISSANDO|CHN_PORTAMENTO))
712 {
713 period = GetPeriodFromNote(GetNoteFromPeriod(period), pChn->nFineTune, pChn->nC4Speed);
714 }
715
716 // Arpeggio ?
717 if (pChn->nCommand == CMD_ARPEGGIO)
718 {
719 switch(m_nTickCount % 3)
720 {
721 case 1:period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break;
722 case 2:period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break;
723 }
724 }
725
726 if (m_dwSongFlags & SONG_AMIGALIMITS)
727 {
728 if (period < 113*4) period = 113*4;
729 if (period > 856*4) period = 856*4;
730 }
731
732 // Pitch/Filter Envelope
733 if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv))
734 {
735 INSTRUMENTHEADER *penv = pChn->pHeader;
736 int envpos = pChn->nPitchEnvPosition;
737 UINT pt = penv->nPitchEnv - 1;
738 for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++)
739 {
740 if (envpos <= penv->PitchPoints[i])
741 {
742 pt = i;
743 break;
744 }
745 }
746 int x2 = penv->PitchPoints[pt];
747 int x1, envpitch;
748 if (envpos >= x2)
749 {
750 envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8;
751 x1 = x2;
752 } else
753 if (pt)
754 {
755 envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8;
756 x1 = penv->PitchPoints[pt-1];
757 } else
758 {
759 envpitch = 0;
760 x1 = 0;
761 }
762 if (envpos > x2) envpos = x2;
763 if ((x2 > x1) && (envpos > x1))
764 {
765 int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8;
766 envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1);
767 }
768 if (envpitch < -256) envpitch = -256;
769 if (envpitch > 256) envpitch = 256;
770 // Filter Envelope: controls cutoff frequency
771 if (penv->dwFlags & ENV_FILTER)
772 {
773#ifndef NO_FILTER
774 SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
775#endif // NO_FILTER
776 } else
777 // Pitch Envelope
778 {
779 int l = envpitch;
780 if (l < 0)
781 {
782 l = -l;
783 if (l > 255) l = 255;
784 period = _muldiv(period, LinearSlideUpTable[l], 0x10000);
785 } else
786 {
787 if (l > 255) l = 255;
788 period = _muldiv(period, LinearSlideDownTable[l], 0x10000);
789 }
790 }
791 }
792
793 // Vibrato
794 if (pChn->dwFlags & CHN_VIBRATO)
795 {
796 UINT vibpos = pChn->nVibratoPos;
797 LONG vdelta;
798 switch (pChn->nVibratoType & 0x03)
799 {
800 case 1:
801 vdelta = ModRampDownTable[vibpos];
802 break;
803 case 2:
804 vdelta = ModSquareTable[vibpos];
805 break;
806 case 3:
807 vdelta = ModRandomTable[vibpos];
808 break;
809 default:
810 vdelta = ModSinusTable[vibpos];
811 }
812 UINT vdepth = ((m_nType != MOD_TYPE_IT) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) ? 6 : 7;
813 vdelta = (vdelta * (int)pChn->nVibratoDepth) >> vdepth;
814 if ((m_dwSongFlags & SONG_LINEARSLIDES) && (m_nType & MOD_TYPE_IT))
815 {
816 LONG l = vdelta;
817 if (l < 0)
818 {
819 l = -l;
820 vdelta = _muldiv(period, LinearSlideDownTable[l >> 2], 0x10000) - period;
821 if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideDownTable[l & 0x03], 0x10000) - period;
822
823 } else
824 {
825 vdelta = _muldiv(period, LinearSlideUpTable[l >> 2], 0x10000) - period;
826 if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period;
827
828 }
829 }
830 period += vdelta;
831 if ((m_nTickCount) || ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
832 {
833 pChn->nVibratoPos = (vibpos + pChn->nVibratoSpeed) & 0x3F;
834 }
835 }
836 // Panbrello
837 if (pChn->dwFlags & CHN_PANBRELLO)
838 {
839 UINT panpos = ((pChn->nPanbrelloPos+0x10) >> 2) & 0x3F;
840 LONG pdelta;
841 switch (pChn->nPanbrelloType & 0x03)
842 {
843 case 1:
844 pdelta = ModRampDownTable[panpos];
845 break;
846 case 2:
847 pdelta = ModSquareTable[panpos];
848 break;
849 case 3:
850 pdelta = ModRandomTable[panpos];
851 break;
852 default:
853 pdelta = ModSinusTable[panpos];
854 }
855 pChn->nPanbrelloPos += pChn->nPanbrelloSpeed;
856 pdelta = ((pdelta * (int)pChn->nPanbrelloDepth) + 2) >> 3;
857 pdelta += pChn->nRealPan;
858 if (pdelta < 0) pdelta = 0;
859 if (pdelta > 256) pdelta = 256;
860 pChn->nRealPan = pdelta;
861 }
862 int nPeriodFrac = 0;
863 // Instrument Auto-Vibrato
864 if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth))
865 {
866 MODINSTRUMENT *pins = pChn->pInstrument;
867 if (pins->nVibSweep == 0)
868 {
869 pChn->nAutoVibDepth = pins->nVibDepth << 8;
870 } else
871 {
872 if (m_nType & MOD_TYPE_IT)
873 {
874 pChn->nAutoVibDepth += pins->nVibSweep << 3;
875 } else
876 if (!(pChn->dwFlags & CHN_KEYOFF))
877 {
878 pChn->nAutoVibDepth += (pins->nVibDepth << 8) /pins->nVibSweep;
879 }
880 if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth)
881 pChn->nAutoVibDepth = pins->nVibDepth << 8;
882 }
883 pChn->nAutoVibPos += pins->nVibRate;
884 int val;
885 switch(pins->nVibType)
886 {
887 case 4:// Random
888 val = ModRandomTable[pChn->nAutoVibPos & 0x3F];
889 pChn->nAutoVibPos++;
890 break;
891 case 3:// Ramp Down
892 val = ((0x40 - (pChn->nAutoVibPos >> 1)) & 0x7F) - 0x40;
893 break;
894 case 2:// Ramp Up
895 val = ((0x40 + (pChn->nAutoVibPos >> 1)) & 0x7f) - 0x40;
896 break;
897 case 1:// Square
898 val = (pChn->nAutoVibPos & 128) ? +64 : -64;
899 break;
900 default:// Sine
901 val = ft2VibratoTable[pChn->nAutoVibPos & 255];
902 }
903 int n =((val * pChn->nAutoVibDepth) >> 8);
904 if (m_nType & MOD_TYPE_IT)
905 {
906 int df1, df2;
907 if (n < 0)
908 {
909 n = -n;
910 UINT n1 = n >> 8;
911 df1 = LinearSlideUpTable[n1];
912 df2 = LinearSlideUpTable[n1+1];
913 } else
914 {
915 UINT n1 = n >> 8;
916 df1 = LinearSlideDownTable[n1];
917 df2 = LinearSlideDownTable[n1+1];
918 }
919 n >>= 2;
920 period = _muldiv(period, df1 + ((df2-df1)*(n&0x3F)>>6), 256);
921 nPeriodFrac = period & 0xFF;
922 period >>= 8;
923 } else
924 {
925 period += (n >> 6);
926 }
927 }
928 // Final Period
929 if (period <= m_nMinPeriod)
930 {
931 if (m_nType & MOD_TYPE_S3M) pChn->nLength = 0;
932 period = m_nMinPeriod;
933 }
934 if (period > m_nMaxPeriod)
935 {
936 if ((m_nType & MOD_TYPE_IT) || (period >= 0x100000))
937 {
938 pChn->nFadeOutVol = 0;
939 pChn->dwFlags |= CHN_NOTEFADE;
940 pChn->nRealVolume = 0;
941 }
942 period = m_nMaxPeriod;
943 nPeriodFrac = 0;
944 }
945 UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac);
946 if ((m_nType & MOD_TYPE_IT) && (freq < 256))
947 {
948 pChn->nFadeOutVol = 0;
949 pChn->dwFlags |= CHN_NOTEFADE;
950 pChn->nRealVolume = 0;
951 }
952 UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq);
953 if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000;
954 if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7;
955 if (ninc > 0xFF0000) ninc = 0xFF0000;
956 pChn->nInc = (ninc+1) & ~3;
957 }
958
959 // Increment envelope position
960 if (pChn->pHeader)
961 {
962 INSTRUMENTHEADER *penv = pChn->pHeader;
963 // Volume Envelope
964 if (pChn->dwFlags & CHN_VOLENV)
965 {
966 // Increase position
967 pChn->nVolEnvPosition++;
968 // Volume Loop ?
969 if (penv->dwFlags & ENV_VOLLOOP)
970 {
971 UINT volloopend = penv->VolPoints[penv->nVolLoopEnd];
972 if (m_nType != MOD_TYPE_XM) volloopend++;
973 if (pChn->nVolEnvPosition == volloopend)
974 {
975 pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart];
976 if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart])
977 && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv)))
978 {
979 pChn->dwFlags |= CHN_NOTEFADE;
980 pChn->nFadeOutVol = 0;
981 }
982 }
983 }
984 // Volume Sustain ?
985 if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
986 {
987 if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1)
988 pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin];
989 } else
990 // End of Envelope ?
991 if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1])
992 {
993 if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE;
994 pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1];
995 if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT)))
996 {
997 pChn->dwFlags |= CHN_NOTEFADE;
998 pChn->nFadeOutVol = 0;
999
1000 pChn->nRealVolume = 0;
1001 }
1002 }
1003 }
1004 // Panning Envelope
1005 if (pChn->dwFlags & CHN_PANENV)
1006 {
1007 pChn->nPanEnvPosition++;
1008 if (penv->dwFlags & ENV_PANLOOP)
1009 {
1010 UINT panloopend = penv->PanPoints[penv->nPanLoopEnd];
1011 if (m_nType != MOD_TYPE_XM) panloopend++;
1012 if (pChn->nPanEnvPosition == panloopend)
1013 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart];
1014 }
1015 // Panning Sustain ?
1016 if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1)
1017 && (!(pChn->dwFlags & CHN_KEYOFF)))
1018 {
1019 // Panning sustained
1020 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin];
1021 } else
1022 {
1023 if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1])
1024 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1];
1025 }
1026 }
1027 // Pitch Envelope
1028 if (pChn->dwFlags & CHN_PITCHENV)
1029 {
1030 // Increase position
1031 pChn->nPitchEnvPosition++;
1032 // Pitch Loop ?
1033 if (penv->dwFlags & ENV_PITCHLOOP)
1034 {
1035 if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd])
1036 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart];
1037 }
1038 // Pitch Sustain ?
1039 if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
1040 {
1041 if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1)
1042 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin];
1043 } else
1044 {
1045 if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1])
1046 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1];
1047 }
1048 }
1049 }
1050#ifdef MODPLUG_PLAYER
1051 // Limit CPU -> > 80% -> don't ramp
1052 if ((gnCPUUsage >= 80) && (!pChn->nRealVolume))
1053 {
1054 pChn->nLeftVol = pChn->nRightVol = 0;
1055 }
1056#endif // MODPLUG_PLAYER
1057 // Volume ramping
1058 pChn->dwFlags &= ~CHN_VOLUMERAMP;
1059 if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol))
1060 pChn->dwFlags |= CHN_VOLUMERAMP;
1061#ifdef MODPLUG_PLAYER
1062 // Decrease VU-Meter
1063 if (pChn->nVUMeter > VUMETER_DECAY)pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0;
1064#endif // MODPLUG_PLAYER
1065#ifdef ENABLE_STEREOVU
1066 if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0;
1067 if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0;
1068#endif
1069 // Check for too big nInc
1070 if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP;
1071 pChn->nNewRightVol = pChn->nNewLeftVol = 0;
1072 pChn->pCurrentSample = ((pChn->pSample) && (pChn->nLength) && (pChn->nInc)) ? pChn->pSample : NULL;
1073 if (pChn->pCurrentSample)
1074 {
1075 // Update VU-Meter (nRealVolume is 14-bit)
1076#ifdef MODPLUG_PLAYER
1077 UINT vutmp = pChn->nRealVolume >> (14 - 8);
1078 if (vutmp > 0xFF) vutmp = 0xFF;
1079 if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp;
1080 vutmp >>= 1;
1081 if (pChn->nVUMeter < vutmp)pChn->nVUMeter = vutmp;
1082#endif // MODPLUG_PLAYER
1083#ifdef ENABLE_STEREOVU
1084 UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14;
1085 if (vul > 127) vul = 127;
1086 if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul;
1087 vul >>= 1;
1088 if (pChn->nLeftVU < vul) pChn->nLeftVU = (BYTE)vul;
1089 UINT vur = (pChn->nRealVolume * (256-pChn->nRealPan)) >> 14;
1090 if (vur > 127) vur = 127;
1091 if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur;
1092 vur >>= 1;
1093 if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur;
1094#endif
1095#ifdef MODPLUG_TRACKER
1096 UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol;
1097#else
1098 #define kChnMasterVolnMasterVol
1099#endif // MODPLUG_TRACKER
1100 // Adjusting volumes
1101 if (gnChannels >= 2)
1102 {
1103 int pan = ((int)pChn->nRealPan) - 128;
1104 pan *= (int)m_nStereoSeparation;
1105 pan /= 128;
1106 pan += 128;
1107
1108 if (pan < 0) pan = 0;
1109 if (pan > 256) pan = 256;
1110#ifndef FASTSOUNDLIB
1111 if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan;
1112#endif
1113 LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1);
1114 if (gdwSoundSetup & SNDMIX_SOFTPANNING)
1115 {
1116 if (pan < 128)
1117 {
1118 pChn->nNewLeftVol = (realvol * pan) >> 8;
1119 pChn->nNewRightVol = (realvol * 128) >> 8;
1120 } else
1121 {
1122 pChn->nNewLeftVol = (realvol * 128) >> 8;
1123 pChn->nNewRightVol = (realvol * (256 - pan)) >> 8;
1124 }
1125 } else
1126 {
1127 pChn->nNewLeftVol = (realvol * pan) >> 8;
1128 pChn->nNewRightVol = (realvol * (256 - pan)) >> 8;
1129 }
1130 } else
1131 {
1132 pChn->nNewRightVol = (pChn->nRealVolume * kChnMasterVol) >> 8;
1133 pChn->nNewLeftVol = pChn->nNewRightVol;
1134 }
1135 // Clipping volumes
1136 if (pChn->nNewRightVol > 0xFFFF) pChn->nNewRightVol = 0xFFFF;
1137 if (pChn->nNewLeftVol > 0xFFFF) pChn->nNewLeftVol = 0xFFFF;
1138 // Check IDO
1139 if (gdwSoundSetup & SNDMIX_NORESAMPLING)
1140 {
1141 pChn->dwFlags |= CHN_NOIDO;
1142 } else
1143 {
1144 pChn->dwFlags &= ~(CHN_NOIDO|CHN_HQSRC);
1145 if( pChn->nInc == 0x10000 )
1146 {pChn->dwFlags |= CHN_NOIDO;
1147 }
1148 else
1149 {if( ((gdwSoundSetup & SNDMIX_HQRESAMPLER) == 0) && ((gdwSoundSetup & SNDMIX_ULTRAHQSRCMODE) == 0) )
1150 {if (pChn->nInc >= 0xFF00) pChn->dwFlags |= CHN_NOIDO;
1151 }
1152 }
1153 }
1154 pChn->nNewRightVol >>= MIXING_ATTENUATION;
1155 pChn->nNewLeftVol >>= MIXING_ATTENUATION;
1156 pChn->nRightRamp = pChn->nLeftRamp = 0;
1157 // Dolby Pro-Logic Surround
1158 if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol;
1159 // Checking Ping-Pong Loops
1160 if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc;
1161 // Setting up volume ramp
1162 if ((pChn->dwFlags & CHN_VOLUMERAMP)
1163 && ((pChn->nRightVol != pChn->nNewRightVol)
1164 || (pChn->nLeftVol != pChn->nNewLeftVol)))
1165 {
1166 LONG nRampLength = gnVolumeRampSamples;
1167 LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION);
1168 LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION);
1169#ifndef FASTSOUNDLIB
1170 if ((gdwSoundSetup & SNDMIX_DIRECTTODISK)
1171 || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU))
1172 && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20)))
1173 {
1174 if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP)))
1175 {
1176 nRampLength = m_nBufferCount;
1177 if (nRampLength > (1 << (VOLUMERAMPPRECISION-1))) nRampLength = (1 << (VOLUMERAMPPRECISION-1));
1178 if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples;
1179 }
1180 }
1181#endif
1182 pChn->nRightRamp = nRightDelta / nRampLength;
1183 pChn->nLeftRamp = nLeftDelta / nRampLength;
1184 pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION);
1185 pChn->nLeftVol = pChn->nNewLeftVol - ((pChn->nLeftRamp * nRampLength) >> VOLUMERAMPPRECISION);
1186 if (pChn->nRightRamp|pChn->nLeftRamp)
1187 {
1188 pChn->nRampLength = nRampLength;
1189 } else
1190 {
1191 pChn->dwFlags &= ~CHN_VOLUMERAMP;
1192 pChn->nRightVol = pChn->nNewRightVol;
1193 pChn->nLeftVol = pChn->nNewLeftVol;
1194 }
1195 } else
1196 {
1197 pChn->dwFlags &= ~CHN_VOLUMERAMP;
1198 pChn->nRightVol = pChn->nNewRightVol;
1199 pChn->nLeftVol = pChn->nNewLeftVol;
1200 }
1201 pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION;
1202 pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION;
1203 // Adding the channel in the channel list
1204 ChnMix[m_nMixChannels++] = nChn;
1205 if (m_nMixChannels >= MAX_CHANNELS) break;
1206 } else
1207 {
1208#ifdef ENABLE_STEREOVU
1209 // Note change but no sample
1210 if (pChn->nLeftVU > 128) pChn->nLeftVU = 0;
1211 if (pChn->nRightVU > 128) pChn->nRightVU = 0;
1212#endif
1213 if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0;
1214 pChn->nLeftVol = pChn->nRightVol = 0;
1215 pChn->nLength = 0;
1216 }
1217 }
1218 // Checking Max Mix Channels reached: ordering by volume
1219 if ((m_nMixChannels >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)))
1220 {
1221 for (UINT i=0; i<m_nMixChannels; i++)
1222 {
1223 UINT j=i;
1224 while ((j+1<m_nMixChannels) && (Chn[ChnMix[j]].nRealVolume < Chn[ChnMix[j+1]].nRealVolume))
1225 {
1226 UINT n = ChnMix[j];
1227 ChnMix[j] = ChnMix[j+1];
1228 ChnMix[j+1] = n;
1229 j++;
1230 }
1231 }
1232 }
1233 if (m_dwSongFlags & SONG_GLOBALFADE)
1234 {
1235 if (!m_nGlobalFadeSamples)
1236 {
1237 m_dwSongFlags |= SONG_ENDREACHED;
1238 return FALSE;
1239 }
1240 if (m_nGlobalFadeSamples > m_nBufferCount)
1241 m_nGlobalFadeSamples -= m_nBufferCount;
1242 else
1243 m_nGlobalFadeSamples = 0;
1244 }
1245 return TRUE;
1246}
1247
1248