Mercurial > audlegacy-plugins
diff src/modplug/sndmix.cxx @ 2218:6907fc39b53f
That didn't merge properly. I'll try again at some other point.
author | William Pitcock <nenolod@atheme.org> |
---|---|
date | Fri, 07 Dec 2007 12:13:37 -0600 |
parents | 3673c7ec4ea2 |
children | 107c1fed3d92 |
line wrap: on
line diff
--- a/src/modplug/sndmix.cxx Fri Dec 07 12:09:16 2007 -0600 +++ b/src/modplug/sndmix.cxx Fri Dec 07 12:13:37 2007 -0600 @@ -7,14 +7,18 @@ #include "stdafx.h" #include "sndfile.h" +#ifdef MODPLUG_TRACKER +#define ENABLE_STEREOVU +#endif // Volume ramp length, in 1/10 ms #define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz // VU-Meter -#define VUMETER_DECAY 16 +#define VUMETER_DECAY 4 // SNDMIX: These are global flags for playback control +UINT CSoundFile::m_nStereoSeparation = 128; LONG CSoundFile::m_nStreamVolume = 0x8000; UINT CSoundFile::m_nMaxMixChannels = 32; // Mixing Configuration (SetWaveConfig) @@ -26,8 +30,7 @@ // Mixing data initialized in UINT CSoundFile::gnAGC = AGC_UNITY; UINT CSoundFile::gnVolumeRampSamples = 64; -UINT CSoundFile::gnVULeft = 0; -UINT CSoundFile::gnVURight = 0; +UINT CSoundFile::gnVUMeter = 0; UINT CSoundFile::gnCPUUsage = 0; LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL; PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL; @@ -39,15 +42,15 @@ typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG); -extern DWORD MPPASMCALL Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern DWORD MPPASMCALL Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern DWORD MPPASMCALL Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern DWORD MPPASMCALL Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]); -extern UINT MPPASMCALL AGC(int *pBuffer, UINT nSamples, UINT nAGC); -extern VOID MPPASMCALL Dither(int *pBuffer, UINT nSamples, UINT nBits); -extern VOID MPPASMCALL InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); -extern VOID MPPASMCALL StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); -extern VOID MPPASMCALL MonoFromStereo(int *pMixBuf, UINT nSamples); +extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG); +extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC); +extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits); +extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples); +extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs); +extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples); extern short int ModSinusTable[64]; extern short int ModRampDownTable[64]; @@ -82,6 +85,104 @@ }; +// Return (a*b)/c - no divide error +int _muldiv(long a, long b, long c) +{ +#ifdef MSC_VER + int sign, result; + _asm { + mov eax, a + mov ebx, b + or eax, eax + mov edx, eax + jge aneg + neg eax +aneg: + xor edx, ebx + or ebx, ebx + mov ecx, c + jge bneg + neg ebx +bneg: + xor edx, ecx + or ecx, ecx + mov sign, edx + jge cneg + neg ecx +cneg: + mul ebx + cmp edx, ecx + jae diverr + div ecx + jmp ok +diverr: + mov eax, 0x7fffffff +ok: + mov edx, sign + or edx, edx + jge rneg + neg eax +rneg: + mov result, eax + } + return result; +#else + return ((unsigned long long) a * (unsigned long long) b ) / c; +#endif +} + + +// Return (a*b+c/2)/c - no divide error +int _muldivr(long a, long b, long c) +{ +#ifdef MSC_VER + int sign, result; + _asm { + mov eax, a + mov ebx, b + or eax, eax + mov edx, eax + jge aneg + neg eax +aneg: + xor edx, ebx + or ebx, ebx + mov ecx, c + jge bneg + neg ebx +bneg: + xor edx, ecx + or ecx, ecx + mov sign, edx + jge cneg + neg ecx +cneg: + mul ebx + mov ebx, ecx + shr ebx, 1 + add eax, ebx + adc edx, 0 + cmp edx, ecx + jae diverr + div ecx + jmp ok +diverr: + mov eax, 0x7fffffff +ok: + mov edx, sign + or edx, edx + jge rneg + neg eax +rneg: + mov result, eax + } + return result; +#else + return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c; +#endif +} + + BOOL CSoundFile::InitPlayer(BOOL bReset) //-------------------------------------- { @@ -94,13 +195,11 @@ gnRvbROfsVol = gnRvbLOfsVol = 0; if (bReset) { - gnVULeft = 0; - gnVURight = 0; + gnVUMeter = 0; gnCPUUsage = 0; } gbInitPlugins = (bReset) ? 3 : 1; InitializeDSP(bReset); - InitializeEQ(bReset); return TRUE; } @@ -146,28 +245,22 @@ //------------------------------------------------------- { LPBYTE lpBuffer = (LPBYTE)lpDestBuffer; - LPCONVERTPROC pCvt = Convert32To8; - LONG vu_min[2]; - LONG vu_max[2]; + LPCONVERTPROC pCvt = X86_Convert32To8; UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0; -#if 0 + LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF; UINT nMaxPlugins; -#endif - vu_min[0] = vu_min[1] = 0x7FFFFFFF; - vu_max[0] = vu_max[1] = -0x7FFFFFFF; - -#if 0 { nMaxPlugins = MAX_MIXPLUGINS; while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--; } -#endif m_nMixStat = 0; lSampleSize = gnChannels; - if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = Convert32To16; } - else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = Convert32To24; } - else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = Convert32To32; } + if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; } +#ifndef MODPLUG_FASTSOUNDLIB + else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; } + else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; } +#endif lMax = cbBuffer / lSampleSize; if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0; lRead = lMax; @@ -175,19 +268,26 @@ while (lRead > 0) { // Update Channel Data - UINT lTotalSampleCount; if (!m_nBufferCount) { - if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)) - m_nBufferCount = lRead; - if (!ReadNote()) { +#ifndef MODPLUG_FASTSOUNDLIB + if (m_dwSongFlags & SONG_FADINGSONG) + { m_dwSongFlags |= SONG_ENDREACHED; - if (stop_at_order > -1) return 0; /* faster */ - if (lRead == lMax) goto MixDone; - if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)) + m_nBufferCount = lRead; + } else +#endif + if (!ReadNote()) + { +#ifndef MODPLUG_FASTSOUNDLIB + if (!FadeSong(FADESONGDELAY)) +#endif + { + m_dwSongFlags |= SONG_ENDREACHED; + if (lRead == lMax) goto MixDone; m_nBufferCount = lRead; + } } - if (!m_nBufferCount) goto MixDone; } lCount = m_nBufferCount; if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE; @@ -197,46 +297,30 @@ #ifndef MODPLUG_NO_REVERB gnReverbSend = 0; #endif - // Resetting sound buffer - StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); + X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol); if (gnChannels >= 2) { lSampleCount *= 2; m_nMixStat += CreateStereoMix(lCount); -#if 0 - if (nMaxPlugins) ProcessPlugins(lCount); -#endif ProcessStereoDSP(lCount); } else { m_nMixStat += CreateStereoMix(lCount); -#if 0 - if (nMaxPlugins) ProcessPlugins(lCount); -#endif - MonoFromStereo(MixSoundBuffer, lCount); - ProcessMonoDSP(lCount); + ProcessStereoDSP(lCount); + X86_MonoFromStereo(MixSoundBuffer, lCount); } - - if (gdwSoundSetup & SNDMIX_EQ) - { - if (gnChannels >= 2) - EQStereo(MixSoundBuffer, lCount); - else - EQMono(MixSoundBuffer, lCount); - } - - nStat++; #ifndef NO_AGC // Automatic Gain Control if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount); #endif - lTotalSampleCount = lSampleCount; + UINT lTotalSampleCount = lSampleCount; +#ifndef MODPLUG_FASTSOUNDLIB // Multichannel if (gnChannels > 2) { - InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); + X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount); lTotalSampleCount *= 2; } // Hook Function @@ -244,8 +328,9 @@ { gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels); } +#endif // Perform clipping + VU-Meter - lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, vu_min, vu_max); + lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax); // Buffer ready lRead -= lCount; m_nBufferCount -= lCount; @@ -253,16 +338,10 @@ MixDone: if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize); // VU-Meter - vu_min[0] >>= 18; - vu_min[1] >>= 18; - vu_max[0] >>= 18; - vu_max[1] >>= 18; - if (vu_max[0] < vu_min[0]) vu_max[0] = vu_min[0]; - if (vu_max[1] < vu_min[1]) vu_max[1] = vu_min[1]; - if ((gnVULeft = (UINT)(vu_max[0] - vu_min[0])) > 0xFF) - gnVULeft = 0xFF; - if ((gnVURight = (UINT)(vu_max[1] - vu_min[1])) > 0xFF) - gnVURight = 0xFF; + nVUMeterMin >>= (24-MIXING_ATTENUATION); + nVUMeterMax >>= (24-MIXING_ATTENUATION); + if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin; + if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF; if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; } return lMax - lRead; } @@ -276,75 +355,77 @@ //--------------------------- { if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay) - { + { m_nPatternDelay = 0; m_nFrameDelay = 0; m_nTickCount = 0; m_nRow = m_nNextRow; - // Reset Pattern Loop Effect - if (m_nCurrentPattern != m_nNextPattern) { - if (m_nLockedPattern < MAX_ORDERS) { - m_nCurrentPattern = m_nLockedPattern; - if (!(m_dwSongFlags & SONG_ORDERLOCKED)) - m_nLockedPattern = MAX_ORDERS; - } else { - m_nCurrentPattern = m_nNextPattern; - } - - // Check if pattern is valid - if (!(m_dwSongFlags & SONG_PATTERNLOOP)) + if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern; + // Check if pattern is valid + if (!(m_dwSongFlags & SONG_PATTERNLOOP)) + { + m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; + if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; + while (m_nPattern >= MAX_PATTERNS) { + // End of song ? + if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) + { + //if (!m_nRepeatCount) + return FALSE; //never repeat entire song + if (!m_nRestartPos) + { + m_nMusicSpeed = m_nDefaultSpeed; + m_nMusicTempo = m_nDefaultTempo; + m_nGlobalVolume = m_nDefaultGlobalVolume; + for (UINT i=0; i<MAX_CHANNELS; i++) + { + Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF; + Chn[i].nFadeOutVol = 0; + if (i < m_nChannels) + { + Chn[i].nGlobalVol = ChnSettings[i].nVolume; + Chn[i].nVolume = ChnSettings[i].nVolume; + Chn[i].nPan = ChnSettings[i].nPan; + Chn[i].nPanSwing = Chn[i].nVolSwing = 0; + Chn[i].nOldVolParam = 0; + Chn[i].nOldOffset = 0; + Chn[i].nOldHiOffset = 0; + Chn[i].nPortamentoDest = 0; + if (!Chn[i].nLength) + { + Chn[i].dwFlags = ChnSettings[i].dwFlags; + Chn[i].nLoopStart = 0; + Chn[i].nLoopEnd = 0; + Chn[i].pHeader = NULL; + Chn[i].pSample = NULL; + Chn[i].pInstrument = NULL; + } + } + } + } +// if (m_nRepeatCount > 0) m_nRepeatCount--; + m_nCurrentPattern = m_nRestartPos; + m_nRow = 0; + if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE; + } else + { + m_nCurrentPattern++; + } m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - while (m_nPattern >= MAX_PATTERNS) - { - // End of song ? - if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS)) - { - if (m_nRepeatCount > 0) m_nRepeatCount--; - if (!m_nRepeatCount) return FALSE; - m_nCurrentPattern = m_nRestartPos; - if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) - || (!Patterns[Order[m_nCurrentPattern]])) - return FALSE; - } else { - m_nCurrentPattern++; - } - m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF; - if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE; - } - m_nNextPattern = m_nCurrentPattern; - } else if (m_nCurrentPattern < 255) { - if (m_nRepeatCount > 0) m_nRepeatCount--; - if (!m_nRepeatCount) return FALSE; } - } -#ifdef MODPLUG_TRACKER - if (m_dwSongFlags & SONG_STEP) - { - m_dwSongFlags &= ~SONG_STEP; - m_dwSongFlags |= SONG_PAUSED; - } -#endif // MODPLUG_TRACKER - if (!PatternSize[m_nPattern] || !Patterns[m_nPattern]) { - /* okay, this is wrong. allocate the pattern _NOW_ */ - Patterns[m_nPattern] = AllocatePattern(64,64); - PatternSize[m_nPattern] = 64; - PatternAllocSize[m_nPattern] = 64; + m_nNextPattern = m_nCurrentPattern; } // Weird stuff? - if (m_nPattern >= MAX_PATTERNS) return FALSE; + if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE; // Should never happen - // ... sure it should: suppose there's a C70 effect before a 64-row pattern. - // It's in fact very easy to make this happen ;) - // - chisel if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0; - m_nNextRow = m_nRow + 1; + m_nNextRow = m_nRow + 1; if (m_nNextRow >= PatternSize[m_nPattern]) { if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1; - else if (m_nRepeatCount > 0) return FALSE; m_nNextRow = 0; } // Reset channel values @@ -352,18 +433,7 @@ MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++) { - /* skip realtime copyin */ - if (pChn->nRealtime) continue; - - // this is where we're going to spit out our midi - // commands... ALL WE DO is dump raw midi data to - // our super-secret "midi buffer" - // -mrsb - if (_midi_out_note) - _midi_out_note(nChn, m); - pChn->nRowNote = m->note; - if (m->instr) pChn->nLastInstr = m->instr; pChn->nRowInstr = m->instr; pChn->nRowVolCmd = m->volcmd; pChn->nRowVolume = m->vol; @@ -375,14 +445,6 @@ pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO); pChn->nCommand = 0; } - - } else if (_midi_out_note) { - MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels; - for (UINT nChn=0; nChn<m_nChannels; nChn++, m++) - { - /* m==NULL allows schism to receive notification of SDx and Scx commands */ - _midi_out_note(nChn, 0); - } } // Should we process tick0 effects? if (!m_nMusicSpeed) m_nMusicSpeed = 1; @@ -407,100 +469,33 @@ BOOL CSoundFile::ReadNote() //------------------------- { - // Checking end of row ? - if (m_dwSongFlags & SONG_PAUSED) - { - /*m_nTickCount = 0;*/ - if (!m_nMusicSpeed) m_nMusicSpeed = 6; - if (!m_nMusicTempo) m_nMusicTempo = 125; - m_nPatternDelay = 0; - m_nFrameDelay = 0; - - m_dwSongFlags |= SONG_FIRSTTICK; - if (m_nTickCount) { - m_dwSongFlags &= ~SONG_FIRSTTICK; - } - - ProcessEffects(); - m_nTickCount++; - if (m_nTickCount >= m_nMusicSpeed) { - m_nTickCount = 0; - } - if (!ProcessEffects()) return FALSE; - } else - { - if (!ProcessRow()) return FALSE; - } - - { /* handle realtime closures */ - MODCHANNEL *pChn = Chn; - for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++) { - /* reset end of "row" */ - if (pChn->nRealtime && pChn->nRowNote && (pChn->nTickStart % m_nMusicSpeed) == (m_nTickCount % m_nMusicSpeed)) { - pChn->nRealtime = 0; - pChn->nRowNote = 0; - pChn->nRowInstr = 0; - //pChn->nMaster - pChn->nRowVolCmd = 0; - pChn->nRowVolume = 0; - pChn->nRowCommand = 0; - pChn->nRowParam = 0; - pChn->nTickStart = 0; - } - } - }; - + if (!ProcessRow()) return FALSE; //////////////////////////////////////////////////////////////////////////////////// m_nTotalCount++; if (!m_nMusicTempo) return FALSE; m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); -#ifdef MODPLUG_TRACKER - if (m_dwSongFlags & SONG_PAUSED) - { - m_nBufferCount = gdwMixingFreq / 64; // 1/64 seconds - } -#endif - - // chaseback hoo hah - if (stop_at_order > -1 && stop_at_row > -1) { - if (stop_at_order <= (signed) m_nCurrentPattern && stop_at_row <= (signed) m_nRow) { - return FALSE; - } - } - // Master Volume + Pre-Amplification / Attenuation setup DWORD nMasterVol; { - int nchn32 = 0; - MODCHANNEL *pChn = Chn; - for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++) { - nchn32++; - } - if (nchn32 < 1) nchn32 = 1; - if (nchn32 > 31) nchn32 = 31; - + int nchn32 = (m_nChannels < 32) ? m_nChannels : 31; + if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6; int realmastervol = m_nMasterVolume; if (realmastervol > 0x80) { realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16; } - - DWORD mastervol = (realmastervol * (m_nSongPreAmp)) >> 6; -// if (mastervol > 0x200) mastervol = 0x200; + UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; + DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6; + if (mastervol > 0x200) mastervol = 0x200; if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples)) { mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples); } - - UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1]; - if (attenuation < 1) attenuation = 1; - nMasterVol = (mastervol << 7) / attenuation; if (nMasterVol > 0x180) nMasterVol = 0x180; } //////////////////////////////////////////////////////////////////////////////////// // Update channels data - if (CSoundFile::gdwSoundSetup & SNDMIX_NOMIXING) return TRUE; m_nMixChannels = 0; MODCHANNEL *pChn = Chn; for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++) @@ -511,9 +506,12 @@ pChn->nROfs = pChn->nLOfs = 0; } // Check for unused channel - if ((nChn >= m_nChannels) && (!pChn->nLength)) + if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength))) { + pChn->nVUMeter = 0; +#ifdef ENABLE_STEREOVU pChn->nLeftVU = pChn->nRightVU = 0; +#endif continue; } // Reset channel data @@ -577,33 +575,33 @@ if (vol > 0x100) vol = 0x100; vol <<= 6; // Process Envelopes - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) + if (pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; // Volume Envelope - if ((pChn->dwFlags & CHN_VOLENV) && (penv->VolEnv.nNodes)) + if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv)) { int envpos = pChn->nVolEnvPosition; - UINT pt = penv->VolEnv.nNodes - 1; - for (UINT i=0; i<(UINT)(penv->VolEnv.nNodes-1); i++) + UINT pt = penv->nVolEnv - 1; + for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++) { - if (envpos <= penv->VolEnv.Ticks[i]) + if (envpos <= penv->VolPoints[i]) { pt = i; break; } } - int x2 = penv->VolEnv.Ticks[pt]; + int x2 = penv->VolPoints[pt]; int x1, envvol; if (envpos >= x2) { - envvol = penv->VolEnv.Values[pt] << 2; + envvol = penv->VolEnv[pt] << 2; x1 = x2; } else if (pt) { - envvol = penv->VolEnv.Values[pt-1] << 2; - x1 = penv->VolEnv.Ticks[pt-1]; + envvol = penv->VolEnv[pt-1] << 2; + x1 = penv->VolPoints[pt-1]; } else { envvol = 0; @@ -612,26 +610,26 @@ if (envpos > x2) envpos = x2; if ((x2 > x1) && (envpos > x1)) { - envvol += ((envpos - x1) * (((int)penv->VolEnv.Values[pt]<<2) - envvol)) / (x2 - x1); + envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1); } if (envvol < 0) envvol = 0; if (envvol > 256) envvol = 256; vol = (vol * envvol) >> 8; } // Panning Envelope - if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes)) + if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv)) { int envpos = pChn->nPanEnvPosition; - UINT pt = penv->PanEnv.nNodes - 1; - for (UINT i=0; i<(UINT)(penv->PanEnv.nNodes-1); i++) + UINT pt = penv->nPanEnv - 1; + for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++) { - if (envpos <= penv->PanEnv.Ticks[i]) + if (envpos <= penv->PanPoints[i]) { pt = i; break; } } - int x2 = penv->PanEnv.Ticks[pt], y2 = penv->PanEnv.Values[pt]; + int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt]; int x1, envpan; if (envpos >= x2) { @@ -640,8 +638,8 @@ } else if (pt) { - envpan = penv->PanEnv.Values[pt-1]; - x1 = penv->PanEnv.Ticks[pt-1]; + envpan = penv->PanEnv[pt-1]; + x1 = penv->PanPoints[pt-1]; } else { envpan = 128; @@ -716,13 +714,8 @@ { switch(m_nTickCount % 3) { -#if 0 case 1: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; case 2: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; -#else - case 1: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break; - case 2: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break; -#endif } } @@ -733,32 +726,30 @@ } // Pitch/Filter Envelope - int envpitch = 0; - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) - && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->PitchEnv.nNodes)) + if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv)) { INSTRUMENTHEADER *penv = pChn->pHeader; int envpos = pChn->nPitchEnvPosition; - UINT pt = penv->PitchEnv.nNodes - 1; - for (UINT i=0; i<(UINT)(penv->PitchEnv.nNodes-1); i++) + UINT pt = penv->nPitchEnv - 1; + for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++) { - if (envpos <= penv->PitchEnv.Ticks[i]) + if (envpos <= penv->PitchPoints[i]) { pt = i; break; } } - int x2 = penv->PitchEnv.Ticks[pt]; - int x1; + int x2 = penv->PitchPoints[pt]; + int x1, envpitch; if (envpos >= x2) { - envpitch = (((int)penv->PitchEnv.Values[pt]) - 32) * 8; + envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8; x1 = x2; } else if (pt) { - envpitch = (((int)penv->PitchEnv.Values[pt-1]) - 32) * 8; - x1 = penv->PitchEnv.Ticks[pt-1]; + envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8; + x1 = penv->PitchPoints[pt-1]; } else { envpitch = 0; @@ -767,13 +758,19 @@ if (envpos > x2) envpos = x2; if ((x2 > x1) && (envpos > x1)) { - int envpitchdest = (((int)penv->PitchEnv.Values[pt]) - 32) * 8; + int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8; envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1); } if (envpitch < -256) envpitch = -256; if (envpitch > 256) envpitch = 256; + // Filter Envelope: controls cutoff frequency + if (penv->dwFlags & ENV_FILTER) + { +#ifndef NO_FILTER + SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); +#endif // NO_FILTER + } else // Pitch Envelope - if (!(penv->dwFlags & ENV_FILTER)) { int l = envpitch; if (l < 0) @@ -863,16 +860,6 @@ if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth)) { MODINSTRUMENT *pins = pChn->pInstrument; - /* this isn't correct, but its better... */ - - if (pins->nVibSweep == 0) { - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } else { - pChn->nAutoVibDepth += pins->nVibSweep; - if ((pChn->nAutoVibDepth >> 8) > (int)pins->nVibDepth) - pChn->nAutoVibDepth = pins->nVibDepth << 8; - } -#if 0 if (pins->nVibSweep == 0) { pChn->nAutoVibDepth = pins->nVibDepth << 8; @@ -880,7 +867,7 @@ { if (m_nType & MOD_TYPE_IT) { - pChn->nAutoVibDepth += pins->nVibSweep; + pChn->nAutoVibDepth += pins->nVibSweep << 3; } else if (!(pChn->dwFlags & CHN_KEYOFF)) { @@ -889,8 +876,7 @@ if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth) pChn->nAutoVibDepth = pins->nVibDepth << 8; } -#endif - pChn->nAutoVibPos += ((int)pins->nVibRate); + pChn->nAutoVibPos += pins->nVibRate; int val; switch(pins->nVibType) { @@ -911,10 +897,6 @@ val = ft2VibratoTable[pChn->nAutoVibPos & 255]; } int n = ((val * pChn->nAutoVibDepth) >> 8); - // is this right? -mrsb - if (!(m_dwSongFlags & SONG_ITOLDEFFECTS)) - n >>= 1; - if (m_nType & MOD_TYPE_IT) { int df1, df2; @@ -957,25 +939,12 @@ nPeriodFrac = 0; } UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac); - - // Filter Envelope: controls cutoff frequency - if (pChn && pChn->pHeader && pChn->pHeader->dwFlags & ENV_FILTER) - { -#ifndef NO_FILTER - SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch); -#endif // NO_FILTER - } - -#if 0 if ((m_nType & MOD_TYPE_IT) && (freq < 256)) { pChn->nFadeOutVol = 0; pChn->dwFlags |= CHN_NOTEFADE; pChn->nRealVolume = 0; } -#endif - pChn->sample_freq = freq; - UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq); if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000; if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7; @@ -984,7 +953,7 @@ } // Increment envelope position - if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader) + if (pChn->pHeader) { INSTRUMENTHEADER *penv = pChn->pHeader; // Volume Envelope @@ -995,13 +964,13 @@ // Volume Loop ? if (penv->dwFlags & ENV_VOLLOOP) { - int volloopend = penv->VolEnv.Ticks[penv->VolEnv.nLoopEnd]; + UINT volloopend = penv->VolPoints[penv->nVolLoopEnd]; if (m_nType != MOD_TYPE_XM) volloopend++; if (pChn->nVolEnvPosition == volloopend) { - pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nLoopStart]; - if ((penv->VolEnv.nLoopEnd == penv->VolEnv.nLoopStart) && (!penv->VolEnv.Values[penv->VolEnv.nLoopStart]) - && ((!(m_nType & MOD_TYPE_XM)) || (penv->VolEnv.nLoopEnd+1 == penv->VolEnv.nNodes))) + pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart]; + if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart]) + && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv))) { pChn->dwFlags |= CHN_NOTEFADE; pChn->nFadeOutVol = 0; @@ -1011,15 +980,15 @@ // Volume Sustain ? if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) { - if (pChn->nVolEnvPosition == (int)penv->VolEnv.Ticks[penv->VolEnv.nSustainEnd]+1) - pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nSustainStart]; + if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1) + pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin]; } else // End of Envelope ? - if (pChn->nVolEnvPosition > penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1]) + if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1]) { if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; - pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1]; - if ((!penv->VolEnv.Values[penv->VolEnv.nNodes-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) + pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1]; + if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT))) { pChn->dwFlags |= CHN_NOTEFADE; pChn->nFadeOutVol = 0; @@ -1034,21 +1003,21 @@ pChn->nPanEnvPosition++; if (penv->dwFlags & ENV_PANLOOP) { - int panloopend = penv->PanEnv.Ticks[penv->PanEnv.nLoopEnd]; + UINT panloopend = penv->PanPoints[penv->nPanLoopEnd]; if (m_nType != MOD_TYPE_XM) panloopend++; if (pChn->nPanEnvPosition == panloopend) - pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nLoopStart]; + pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart]; } // Panning Sustain ? - if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (int)penv->PanEnv.Ticks[penv->PanEnv.nSustainEnd]+1) + if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1) && (!(pChn->dwFlags & CHN_KEYOFF))) { // Panning sustained - pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nSustainStart]; + pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin]; } else { - if (pChn->nPanEnvPosition > penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]) - pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1]; + if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1]) + pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1]; } } // Pitch Envelope @@ -1059,22 +1028,22 @@ // Pitch Loop ? if (penv->dwFlags & ENV_PITCHLOOP) { - if (pChn->nPitchEnvPosition >= penv->PitchEnv.Ticks[penv->PitchEnv.nLoopEnd]) - pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nLoopStart]; + if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd]) + pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart]; } // Pitch Sustain ? if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) { - if (pChn->nPitchEnvPosition == (int)penv->PitchEnv.Ticks[penv->PitchEnv.nSustainEnd]+1) - pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nSustainStart]; + if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1) + pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin]; } else { - if (pChn->nPitchEnvPosition > penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]) - pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1]; + if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1]) + pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1]; } } } -#if 0 +#ifdef MODPLUG_PLAYER // Limit CPU -> > 80% -> don't ramp if ((gnCPUUsage >= 80) && (!pChn->nRealVolume)) { @@ -1085,10 +1054,14 @@ pChn->dwFlags &= ~CHN_VOLUMERAMP; if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol)) pChn->dwFlags |= CHN_VOLUMERAMP; +#ifdef MODPLUG_PLAYER // Decrease VU-Meter if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0; +#endif // MODPLUG_PLAYER +#ifdef ENABLE_STEREOVU if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0; if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0; +#endif // Check for too big nInc if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP; pChn->nNewRightVol = pChn->nNewLeftVol = 0; @@ -1096,11 +1069,14 @@ if (pChn->pCurrentSample) { // Update VU-Meter (nRealVolume is 14-bit) +#ifdef MODPLUG_PLAYER UINT vutmp = pChn->nRealVolume >> (14 - 8); if (vutmp > 0xFF) vutmp = 0xFF; if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp; vutmp >>= 1; if (pChn->nVUMeter < vutmp) pChn->nVUMeter = vutmp; +#endif // MODPLUG_PLAYER +#ifdef ENABLE_STEREOVU UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14; if (vul > 127) vul = 127; if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul; @@ -1111,6 +1087,7 @@ if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur; vur >>= 1; if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur; +#endif #ifdef MODPLUG_TRACKER UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol; #else @@ -1126,8 +1103,9 @@ if (pan < 0) pan = 0; if (pan > 256) pan = 256; +#ifndef MODPLUG_FASTSOUNDLIB if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan; - if (m_dwSongFlags & SONG_NOSTEREO) pan = 128; +#endif LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1); if (gdwSoundSetup & SNDMIX_SOFTPANNING) { @@ -1156,7 +1134,6 @@ // Check IDO if (gdwSoundSetup & SNDMIX_NORESAMPLING) { - pChn->dwFlags &= ~(CHN_HQSRC); pChn->dwFlags |= CHN_NOIDO; } else { @@ -1174,26 +1151,21 @@ pChn->nNewLeftVol >>= MIXING_ATTENUATION; pChn->nRightRamp = pChn->nLeftRamp = 0; // Dolby Pro-Logic Surround - if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2) && (gdwSoundSetup & SNDMIX_NOSURROUND) == 0) - pChn->nNewLeftVol = -pChn->nNewLeftVol; + if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol; // Checking Ping-Pong Loops if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc; // Setting up volume ramp - if (!(gdwSoundSetup & SNDMIX_NORAMPING) - && (pChn->dwFlags & CHN_VOLUMERAMP) + if ((pChn->dwFlags & CHN_VOLUMERAMP) && ((pChn->nRightVol != pChn->nNewRightVol) || (pChn->nLeftVol != pChn->nNewLeftVol))) { LONG nRampLength = gnVolumeRampSamples; LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION); LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION); -#if 0 +#ifndef MODPLUG_FASTSOUNDLIB if ((gdwSoundSetup & SNDMIX_DIRECTTODISK) || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU)) && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20))) -#else - if (gdwSoundSetup & SNDMIX_HQRESAMPLER) -#endif { if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP))) { @@ -1202,6 +1174,7 @@ if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples; } } +#endif pChn->nRightRamp = nRightDelta / nRampLength; pChn->nLeftRamp = nLeftDelta / nRampLength; pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION); @@ -1224,15 +1197,15 @@ pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION; pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION; // Adding the channel in the channel list - if (!(pChn->dwFlags & CHN_MUTE)) { - ChnMix[m_nMixChannels++] = nChn; - if (m_nMixChannels >= MAX_CHANNELS) break; - } + ChnMix[m_nMixChannels++] = nChn; + if (m_nMixChannels >= MAX_CHANNELS) break; } else { +#ifdef ENABLE_STEREOVU // Note change but no sample if (pChn->nLeftVU > 128) pChn->nLeftVU = 0; if (pChn->nRightVU > 128) pChn->nRightVU = 0; +#endif if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0; pChn->nLeftVol = pChn->nRightVol = 0; pChn->nLength = 0;