2 * This source code is public domain.
4 * Authors: Olivier Lapicque <olivierl@jps.net>
14 #ifdef MODPLUG_TRACKER
15 #define ENABLE_STEREOVU
18 // Volume ramp length, in 1/10 ms
19 #define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz
22 #define VUMETER_DECAY 4
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;
47 typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG);
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);
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];
73 // Log tables for pre-amp
74 // We don't want the tracker to get too loud
75 const UINT PreAmpTable[16] =
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
83 const UINT PreAmpAGCTable[16] =
85 0x60, 0x60, 0x60, 0x60,
86 0x68, 0x70, 0x78, 0x80,
87 0x84, 0x88, 0x8C, 0x90,
88 0x94, 0x98, 0x9C, 0xA0,
92 // Return (a*b)/c - no divide error
93 int _muldiv(long a, long b, long c)
134 return ((unsigned long long) a * (unsigned long long) b ) / c;
139 // Return (a*b+c/2)/c - no divide error
140 int _muldivr(long a, long b, long c)
185 return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c;
190 BOOL CSoundFile::InitPlayer(BOOL bReset)
191 //--------------------------------------
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;
205 gbInitPlugins = (bReset) ? 3 : 1;
206 InitializeDSP(bReset);
211 BOOL CSoundFile::FadeSong(UINT msec)
212 //----------------------------------
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++)
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;
232 m_dwSongFlags |= SONG_FADINGSONG;
237 BOOL CSoundFile::GlobalFadeSong(UINT msec)
238 //----------------------------------------
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;
248 UINT CSoundFile::Read(LPVOID lpDestBuffer, UINT cbBuffer)
249 //-------------------------------------------------------
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;
258 nMaxPlugins = MAX_MIXPLUGINS;
259 while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--;
262 lSampleSize = gnChannels;
263 if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; }
265 else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; }
266 else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; }
268 lMax = cbBuffer / lSampleSize;
269 if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0;
271 if (m_dwSongFlags & SONG_ENDREACHED) goto MixDone;
274 // Update Channel Data
278 if (m_dwSongFlags & SONG_FADINGSONG)
280 m_dwSongFlags |= SONG_ENDREACHED;
281 m_nBufferCount = lRead;
287 if (!FadeSong(FADESONGDELAY))
290 m_dwSongFlags |= SONG_ENDREACHED;
291 if (lRead == lMax) goto MixDone;
292 m_nBufferCount = lRead;
296 lCount = m_nBufferCount;
297 if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE;
298 if (lCount > lRead) lCount = lRead;
300 lSampleCount = lCount;
304 // Resetting sound buffer
305 X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
309 m_nMixStat += CreateStereoMix(lCount);
310 ProcessStereoDSP(lCount);
313 m_nMixStat += CreateStereoMix(lCount);
314 if (nMaxPlugins) ProcessPlugins(lCount);
315 ProcessStereoDSP(lCount);
316 X86_MonoFromStereo(MixSoundBuffer, lCount);
320 // Automatic Gain Control
321 if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount);
323 UINT lTotalSampleCount = lSampleCount;
328 X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
329 lTotalSampleCount *= 2;
334 gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels);
337 // Perform clipping + VU-Meter
338 lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax);
341 m_nBufferCount -= lCount;
344 if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize);
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; }
356 /////////////////////////////////////////////////////////////////////////////
357 // Handles navigation/effects
359 BOOL CSoundFile::ProcessRow()
360 //---------------------------
362 if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay)
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))
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)
378 if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS))
380 //if (!m_nRepeatCount)
381 return FALSE; //never repeat entire song
384 m_nMusicSpeed = m_nDefaultSpeed;
385 m_nMusicTempo = m_nDefaultTempo;
386 m_nGlobalVolume = m_nDefaultGlobalVolume;
387 for (UINT i=0; i<MAX_CHANNELS; i++)
389 Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF;
390 Chn[i].nFadeOutVol = 0;
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;
403 Chn[i].dwFlags = ChnSettings[i].dwFlags;
404 Chn[i].nLoopStart = 0;
406 Chn[i].pHeader = NULL;
407 Chn[i].pSample = NULL;
408 Chn[i].pInstrument = NULL;
413 // if (m_nRepeatCount > 0) m_nRepeatCount--;
414 m_nCurrentPattern = m_nRestartPos;
416 if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE;
421 m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
422 if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
424 m_nNextPattern = m_nCurrentPattern;
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])
433 if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1;
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++)
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;
448 pChn->nLeftVol = pChn->nNewLeftVol;
449 pChn->nRightVol = pChn->nNewRightVol;
450 pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO);
454 // Should we process tick0 effects?
455 if (!m_nMusicSpeed) m_nMusicSpeed = 1;
456 m_dwSongFlags |= SONG_FIRSTTICK;
459 m_dwSongFlags &= ~SONG_FIRSTTICK;
460 if ((!(m_nType & MOD_TYPE_XM)) && (m_nTickCount < m_nMusicSpeed * (1 + m_nPatternDelay)))
462 if (!(m_nTickCount % m_nMusicSpeed)) m_dwSongFlags |= SONG_FIRSTTICK;
467 return ProcessEffects();
471 ////////////////////////////////////////////////////////////////////////////////////////////
472 // Handles envelopes & mixer setup
474 BOOL CSoundFile::ReadNote()
475 //-------------------------
477 if (!ProcessRow()) return FALSE;
478 ////////////////////////////////////////////////////////////////////////////////////
480 if (!m_nMusicTempo) return FALSE;
481 m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8);
482 // Master Volume + Pre-Amplification / Attenuation setup
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)
490 realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16;
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))
497 mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples);
499 nMasterVol = (mastervol << 7) / attenuation;
500 if (nMasterVol > 0x180) nMasterVol = 0x180;
502 ////////////////////////////////////////////////////////////////////////////////////
503 // Update channels data
505 MODCHANNEL *pChn = Chn;
506 for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++)
508 if ((pChn->dwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol)))
511 pChn->nROfs = pChn->nLOfs = 0;
513 // Check for unused channel
514 if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength)))
517 #ifdef ENABLE_STEREOVU
518 pChn->nLeftVU = pChn->nRightVU = 0;
522 // Reset channel data
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;
530 if ((pChn->nPeriod) && (pChn->nLength))
532 int vol = pChn->nVolume + pChn->nVolSwing;
534 if (vol < 0) vol = 0;
535 if (vol > 256) vol = 256;
537 if (pChn->dwFlags & CHN_TREMOLO)
539 UINT trempos = pChn->nTremoloPos & 0x3F;
542 int tremattn = (m_nType & MOD_TYPE_XM) ? 5 : 6;
543 switch (pChn->nTremoloType & 0x03)
546 vol += (ModRampDownTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
549 vol += (ModSquareTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
552 vol += (ModRandomTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
555 vol += (ModSinusTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
558 if ((m_nTickCount) || ((m_nType & (MOD_TYPE_STM|MOD_TYPE_S3M|MOD_TYPE_IT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
560 pChn->nTremoloPos = (trempos + pChn->nTremoloSpeed) & 0x3F;
564 if (pChn->nCommand == CMD_TREMOR)
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)))
573 if (tremcount >= ontime) vol = 0;
574 pChn->nTremorCount = (BYTE)(tremcount + 1);
576 pChn->dwFlags |= CHN_FASTVOLRAMP;
579 if (vol < 0) vol = 0;
580 if (vol > 0x100) vol = 0x100;
585 INSTRUMENTHEADER *penv = pChn->pHeader;
587 if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv))
589 int envpos = pChn->nVolEnvPosition;
590 UINT pt = penv->nVolEnv - 1;
591 for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++)
593 if (envpos <= penv->VolPoints[i])
599 int x2 = penv->VolPoints[pt];
603 envvol = penv->VolEnv[pt] << 2;
608 envvol = penv->VolEnv[pt-1] << 2;
609 x1 = penv->VolPoints[pt-1];
615 if (envpos > x2) envpos = x2;
616 if ((x2 > x1) && (envpos > x1))
618 envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1);
620 if (envvol < 0) envvol = 0;
621 if (envvol > 256) envvol = 256;
622 vol = (vol * envvol) >> 8;
625 if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv))
627 int envpos = pChn->nPanEnvPosition;
628 UINT pt = penv->nPanEnv - 1;
629 for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++)
631 if (envpos <= penv->PanPoints[i])
637 int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt];
646 envpan = penv->PanEnv[pt-1];
647 x1 = penv->PanPoints[pt-1];
653 if ((x2 > x1) && (envpos > x1))
655 envpan += ((envpos - x1) * (y2 - envpan)) / (x2 - x1);
657 if (envpan < 0) envpan = 0;
658 if (envpan > 64) envpan = 64;
659 int pan = pChn->nPan;
662 pan += ((envpan - 32) * (256 - pan)) / 32;
665 pan += ((envpan - 32) * (pan)) / 32;
667 if (pan < 0) pan = 0;
668 if (pan > 256) pan = 256;
669 pChn->nRealPan = pan;
672 if (pChn->dwFlags & CHN_NOTEFADE)
674 UINT fadeout = penv->nFadeOut;
677 pChn->nFadeOutVol -= fadeout << 1;
678 if (pChn->nFadeOutVol <= 0) pChn->nFadeOutVol = 0;
679 vol = (vol * pChn->nFadeOutVol) >> 16;
681 if (!pChn->nFadeOutVol)
686 // Pitch/Pan separation
687 if ((penv->nPPS) && (pChn->nRealPan) && (pChn->nNote))
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;
696 // No Envelope: key off => note cut
697 if (pChn->dwFlags & CHN_NOTEFADE) // 1.41-: CHN_KEYOFF|CHN_NOTEFADE
699 pChn->nFadeOutVol = 0;
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);
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))
714 period = GetPeriodFromNote(GetNoteFromPeriod(period), pChn->nFineTune, pChn->nC4Speed);
718 if (pChn->nCommand == CMD_ARPEGGIO)
720 switch(m_nTickCount % 3)
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;
727 if (m_dwSongFlags & SONG_AMIGALIMITS)
729 if (period < 113*4) period = 113*4;
730 if (period > 856*4) period = 856*4;
733 // Pitch/Filter Envelope
734 if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv))
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++)
741 if (envpos <= penv->PitchPoints[i])
747 int x2 = penv->PitchPoints[pt];
751 envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8;
756 envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8;
757 x1 = penv->PitchPoints[pt-1];
763 if (envpos > x2) envpos = x2;
764 if ((x2 > x1) && (envpos > x1))
766 int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8;
767 envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1);
769 if (envpitch < -256) envpitch = -256;
770 if (envpitch > 256) envpitch = 256;
771 // Filter Envelope: controls cutoff frequency
772 if (penv->dwFlags & ENV_FILTER)
775 SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
784 if (l > 255) l = 255;
785 period = _muldiv(period, LinearSlideUpTable[l], 0x10000);
788 if (l > 255) l = 255;
789 period = _muldiv(period, LinearSlideDownTable[l], 0x10000);
795 if (pChn->dwFlags & CHN_VIBRATO)
797 UINT vibpos = pChn->nVibratoPos;
799 switch (pChn->nVibratoType & 0x03)
802 vdelta = ModRampDownTable[vibpos];
805 vdelta = ModSquareTable[vibpos];
808 vdelta = ModRandomTable[vibpos];
811 vdelta = ModSinusTable[vibpos];
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))
821 vdelta = _muldiv(period, LinearSlideDownTable[l >> 2], 0x10000) - period;
822 if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideDownTable[l & 0x03], 0x10000) - period;
826 vdelta = _muldiv(period, LinearSlideUpTable[l >> 2], 0x10000) - period;
827 if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period;
832 if ((m_nTickCount) || ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
834 pChn->nVibratoPos = (vibpos + pChn->nVibratoSpeed) & 0x3F;
838 if (pChn->dwFlags & CHN_PANBRELLO)
840 UINT panpos = ((pChn->nPanbrelloPos+0x10) >> 2) & 0x3F;
842 switch (pChn->nPanbrelloType & 0x03)
845 pdelta = ModRampDownTable[panpos];
848 pdelta = ModSquareTable[panpos];
851 pdelta = ModRandomTable[panpos];
854 pdelta = ModSinusTable[panpos];
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;
864 // Instrument Auto-Vibrato
865 if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth))
867 MODINSTRUMENT *pins = pChn->pInstrument;
868 if (pins->nVibSweep == 0)
870 pChn->nAutoVibDepth = pins->nVibDepth << 8;
873 if (m_nType & MOD_TYPE_IT)
875 pChn->nAutoVibDepth += pins->nVibSweep << 3;
877 if (!(pChn->dwFlags & CHN_KEYOFF))
879 pChn->nAutoVibDepth += (pins->nVibDepth << 8) / pins->nVibSweep;
881 if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth)
882 pChn->nAutoVibDepth = pins->nVibDepth << 8;
884 pChn->nAutoVibPos += pins->nVibRate;
886 switch(pins->nVibType)
889 val = ModRandomTable[pChn->nAutoVibPos & 0x3F];
893 val = ((0x40 - (pChn->nAutoVibPos >> 1)) & 0x7F) - 0x40;
896 val = ((0x40 + (pChn->nAutoVibPos >> 1)) & 0x7f) - 0x40;
899 val = (pChn->nAutoVibPos & 128) ? +64 : -64;
902 val = ft2VibratoTable[pChn->nAutoVibPos & 255];
904 int n = ((val * pChn->nAutoVibDepth) >> 8);
905 if (m_nType & MOD_TYPE_IT)
912 df1 = LinearSlideUpTable[n1];
913 df2 = LinearSlideUpTable[n1+1];
917 df1 = LinearSlideDownTable[n1];
918 df2 = LinearSlideDownTable[n1+1];
921 period = _muldiv(period, df1 + ((df2-df1)*(n&0x3F)>>6), 256);
922 nPeriodFrac = period & 0xFF;
930 if (period <= m_nMinPeriod)
932 if (m_nType & MOD_TYPE_S3M) pChn->nLength = 0;
933 period = m_nMinPeriod;
935 if (period > m_nMaxPeriod)
937 if ((m_nType & MOD_TYPE_IT) || (period >= 0x100000))
939 pChn->nFadeOutVol = 0;
940 pChn->dwFlags |= CHN_NOTEFADE;
941 pChn->nRealVolume = 0;
943 period = m_nMaxPeriod;
946 UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac);
947 if ((m_nType & MOD_TYPE_IT) && (freq < 256))
949 pChn->nFadeOutVol = 0;
950 pChn->dwFlags |= CHN_NOTEFADE;
951 pChn->nRealVolume = 0;
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;
960 // Increment envelope position
963 INSTRUMENTHEADER *penv = pChn->pHeader;
965 if (pChn->dwFlags & CHN_VOLENV)
968 pChn->nVolEnvPosition++;
970 if (penv->dwFlags & ENV_VOLLOOP)
972 UINT volloopend = penv->VolPoints[penv->nVolLoopEnd];
973 if (m_nType != MOD_TYPE_XM) volloopend++;
974 if (pChn->nVolEnvPosition == volloopend)
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)))
980 pChn->dwFlags |= CHN_NOTEFADE;
981 pChn->nFadeOutVol = 0;
986 if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
988 if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1)
989 pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin];
992 if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1])
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)))
998 pChn->dwFlags |= CHN_NOTEFADE;
999 pChn->nFadeOutVol = 0;
1001 pChn->nRealVolume = 0;
1006 if (pChn->dwFlags & CHN_PANENV)
1008 pChn->nPanEnvPosition++;
1009 if (penv->dwFlags & ENV_PANLOOP)
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];
1016 // Panning Sustain ?
1017 if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1)
1018 && (!(pChn->dwFlags & CHN_KEYOFF)))
1020 // Panning sustained
1021 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin];
1024 if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1])
1025 pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1];
1029 if (pChn->dwFlags & CHN_PITCHENV)
1031 // Increase position
1032 pChn->nPitchEnvPosition++;
1034 if (penv->dwFlags & ENV_PITCHLOOP)
1036 if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd])
1037 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart];
1040 if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
1042 if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1)
1043 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin];
1046 if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1])
1047 pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1];
1051 #ifdef MODPLUG_PLAYER
1052 // Limit CPU -> > 80% -> don't ramp
1053 if ((gnCPUUsage >= 80) && (!pChn->nRealVolume))
1055 pChn->nLeftVol = pChn->nRightVol = 0;
1057 #endif // MODPLUG_PLAYER
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;
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)
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;
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;
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;
1094 if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur;
1096 #ifdef MODPLUG_TRACKER
1097 UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol;
1099 #define kChnMasterVol nMasterVol
1100 #endif // MODPLUG_TRACKER
1101 // Adjusting volumes
1102 if (gnChannels >= 2)
1104 int pan = ((int)pChn->nRealPan) - 128;
1105 pan *= (int)m_nStereoSeparation;
1109 if (pan < 0) pan = 0;
1110 if (pan > 256) pan = 256;
1111 #ifndef FASTSOUNDLIB
1112 if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan;
1114 LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1);
1115 if (gdwSoundSetup & SNDMIX_SOFTPANNING)
1119 pChn->nNewLeftVol = (realvol * pan) >> 8;
1120 pChn->nNewRightVol = (realvol * 128) >> 8;
1123 pChn->nNewLeftVol = (realvol * 128) >> 8;
1124 pChn->nNewRightVol = (realvol * (256 - pan)) >> 8;
1128 pChn->nNewLeftVol = (realvol * pan) >> 8;
1129 pChn->nNewRightVol = (realvol * (256 - pan)) >> 8;
1133 pChn->nNewRightVol = (pChn->nRealVolume * kChnMasterVol) >> 8;
1134 pChn->nNewLeftVol = pChn->nNewRightVol;
1137 if (pChn->nNewRightVol > 0xFFFF) pChn->nNewRightVol = 0xFFFF;
1138 if (pChn->nNewLeftVol > 0xFFFF) pChn->nNewLeftVol = 0xFFFF;
1140 if (gdwSoundSetup & SNDMIX_NORESAMPLING)
1142 pChn->dwFlags |= CHN_NOIDO;
1145 pChn->dwFlags &= ~(CHN_NOIDO|CHN_HQSRC);
1146 if( pChn->nInc == 0x10000 )
1147 { pChn->dwFlags |= CHN_NOIDO;
1150 { if( ((gdwSoundSetup & SNDMIX_HQRESAMPLER) == 0) && ((gdwSoundSetup & SNDMIX_ULTRAHQSRCMODE) == 0) )
1151 { if (pChn->nInc >= 0xFF00) pChn->dwFlags |= CHN_NOIDO;
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)))
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)))
1175 if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP)))
1177 nRampLength = m_nBufferCount;
1178 if (nRampLength > (1 << (VOLUMERAMPPRECISION-1))) nRampLength = (1 << (VOLUMERAMPPRECISION-1));
1179 if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples;
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)
1189 pChn->nRampLength = nRampLength;
1192 pChn->dwFlags &= ~CHN_VOLUMERAMP;
1193 pChn->nRightVol = pChn->nNewRightVol;
1194 pChn->nLeftVol = pChn->nNewLeftVol;
1198 pChn->dwFlags &= ~CHN_VOLUMERAMP;
1199 pChn->nRightVol = pChn->nNewRightVol;
1200 pChn->nLeftVol = pChn->nNewLeftVol;
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;
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;
1214 if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0;
1215 pChn->nLeftVol = pChn->nRightVol = 0;
1219 // Checking Max Mix Channels reached: ordering by volume
1220 if ((m_nMixChannels >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)))
1222 for (UINT i=0; i<m_nMixChannels; i++)
1225 while ((j+1<m_nMixChannels) && (Chn[ChnMix[j]].nRealVolume < Chn[ChnMix[j+1]].nRealVolume))
1228 ChnMix[j] = ChnMix[j+1];
1234 if (m_dwSongFlags & SONG_GLOBALFADE)
1236 if (!m_nGlobalFadeSamples)
1238 m_dwSongFlags |= SONG_ENDREACHED;
1241 if (m_nGlobalFadeSamples > m_nBufferCount)
1242 m_nGlobalFadeSamples -= m_nBufferCount;
1244 m_nGlobalFadeSamples = 0;