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