From: <sag...@us...> - 2012-02-26 00:31:54
|
Revision: 1197 http://modplug.svn.sourceforge.net/modplug/?rev=1197&view=rev Author: saga-games Date: 2012-02-26 00:31:46 +0000 (Sun, 26 Feb 2012) Log Message: ----------- [Fix] IT Compatibility: Envelope loop vs sustain loop checking priorities were wrong (http://schismtracker.org/scdev/res/1513.html). [Fix] IT Compatibility: Partly fixed envelope carry if an envelope ends with a looped point at volume 0 (test case Carry0Vol.it). [Ref] Unified envelope processing code. [Ref] Smaller related and unrelated changes. Modified Paths: -------------- trunk/OpenMPT/common/misc_util.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/soundlib/ModInstrument.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/common/misc_util.h =================================================================== --- trunk/OpenMPT/common/misc_util.h 2012-02-25 22:04:30 UTC (rev 1196) +++ trunk/OpenMPT/common/misc_util.h 2012-02-26 00:31:46 UTC (rev 1197) @@ -297,6 +297,7 @@ /// Returns value rounded to nearest integer. inline double Round(const double& val) {return std::floor(val + 0.5);} + inline float Round(const float& val) {return std::floor(val + 0.5f);} /// Rounds given double value to nearest integer value of type T. template <class T> inline T Round(const double& val) @@ -309,6 +310,15 @@ return intval; } + template <class T> inline T Round(const float& val) + { + static_assert(std::numeric_limits<T>::is_integer == true, "Type is a not an integer"); + static_assert(sizeof(T) <= 4, "Revise the implementation for integers > 32-bits."); + const float valRounded = Round(val); + ASSERT(valRounded >= (std::numeric_limits<T>::min)() && valRounded <= (std::numeric_limits<T>::max)()); + const T intval = static_cast<T>(valRounded); + return intval; + } }; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2012-02-25 22:04:30 UTC (rev 1196) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2012-02-26 00:31:46 UTC (rev 1197) @@ -1983,7 +1983,7 @@ if ((ch < GetChanFromCursor(m_findReplace.dwBeginSel)) || (ch > GetChanFromCursor(m_findReplace.dwEndSel))) bFound = false; if ((row < GetRowFromCursor(m_findReplace.dwBeginSel)) || (row > GetRowFromCursor(m_findReplace.dwEndSel))) bFound = false; } - if (((m_findReplace.dwFindFlags & PATSEARCH_NOTE) && ((m->note != m_findReplace.cmdFind.note) && ((m_findReplace.cmdFind.note != CFindReplaceTab::findAny) || (!m->note) || (m->note & 0x80)))) + if (((m_findReplace.dwFindFlags & PATSEARCH_NOTE) && ((m->note != m_findReplace.cmdFind.note) && ((m_findReplace.cmdFind.note != CFindReplaceTab::findAny) || !m->IsNote()))) || ((m_findReplace.dwFindFlags & PATSEARCH_INSTR) && (m->instr != m_findReplace.cmdFind.instr)) || ((m_findReplace.dwFindFlags & PATSEARCH_VOLCMD) && (m->volcmd != m_findReplace.cmdFind.volcmd)) || ((m_findReplace.dwFindFlags & PATSEARCH_VOLUME) && (m->vol != m_findReplace.cmdFind.vol)) Modified: trunk/OpenMPT/mptrack/Vstplug.cpp =================================================================== --- trunk/OpenMPT/mptrack/Vstplug.cpp 2012-02-25 22:04:30 UTC (rev 1196) +++ trunk/OpenMPT/mptrack/Vstplug.cpp 2012-02-26 00:31:46 UTC (rev 1197) @@ -2408,21 +2408,21 @@ // similarly, 16383 (0x7F 0x7F) is to "bend as high as possible." // The exact range of the pitch bend is specific to the synthesizer. - // pre: 0 <= value <= 16383 + ASSERT(0 <= value && value <= 16383); - BYTE byte1 = static_cast<BYTE>(value >> 7); // get last 7 bytes only - BYTE byte2 = static_cast<BYTE>(value & 0x7F); // get first 7 bytes only - short converted = byte1<<8 | byte2; // merge + BYTE byte1 = static_cast<BYTE>(value >> 7); // get last 7 bits only + BYTE byte2 = static_cast<BYTE>(value & 0x7F); // get first 7 bits only + short converted = (byte1 << 8) | byte2; // merge return converted; } -//Bend midi pitch for given midi channel using tracker param (0x00-0xFF) +// Bend midi pitch for given midi channel using tracker param (0x00-0xFF) void CVstPlugin::MidiPitchBend(UINT nMidiCh, int nParam, UINT /*trackChannel*/) //----------------------------------------------------------------------------- { - const int16 increment = static_cast<int16>(nParam * 0x2000/0xFF); + const int16 increment = static_cast<int16>(nParam * 0x2000 / 0xFF); int16 newPitchBendPos = m_nMidiPitchBendPos[nMidiCh] + increment; Limit(newPitchBendPos, int16(MIDI_PitchBend_Min), int16(MIDI_PitchBend_Max)); Modified: trunk/OpenMPT/soundlib/ModInstrument.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModInstrument.cpp 2012-02-25 22:04:30 UTC (rev 1196) +++ trunk/OpenMPT/soundlib/ModInstrument.cpp 2012-02-26 00:31:46 UTC (rev 1197) @@ -96,6 +96,7 @@ if (pt) { + // Get previous node's value and tick. value = static_cast<float>(Values[pt - 1]) / 64.0f; x1 = Ticks[pt - 1]; } @@ -107,7 +108,8 @@ value += ((position - x1) * (static_cast<float>(Values[pt]) / 64.0f - value)) / (x2 - x1); } } - return value; + + return Clamp(value, 0.0f, 1.0f); }; Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2012-02-25 22:04:30 UTC (rev 1196) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2012-02-26 00:31:46 UTC (rev 1197) @@ -703,7 +703,7 @@ || (IsCompatibleMode(TRK_IMPULSETRACKER) && instrumentChanged)) { pChn->dwFlags |= CHN_FASTVOLRAMP; - if ((GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT)) && (!instrumentChanged) && (pIns) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE)))) + if ((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && (!instrumentChanged) && (pIns) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE)))) { if (!(pIns->VolEnv.dwFlags & ENV_CARRY)) ResetChannelEnvelope(pChn->VolEnv); if (!(pIns->PanEnv.dwFlags & ENV_CARRY)) ResetChannelEnvelope(pChn->PanEnv); @@ -960,7 +960,7 @@ } } - if ((!bPorta) || ((!pChn->nLength) && (!(GetType() & MOD_TYPE_S3M)))) + if (!bPorta || (!pChn->nLength && !(GetType() & MOD_TYPE_S3M))) { pChn->pModSample = pSmp; pChn->pSample = pSmp->pSample; @@ -1057,9 +1057,11 @@ { // IT Compatiblity: NNA is reset on every note change, not every instrument change (fixes spx-farspacedance.it). if(IsCompatibleMode(TRK_IMPULSETRACKER)) pChn->nNNA = pIns->nNNA; - if (!(pIns->VolEnv.dwFlags & ENV_CARRY)) pChn->VolEnv.nEnvPosition = 0; - if (!(pIns->PanEnv.dwFlags & ENV_CARRY)) pChn->PanEnv.nEnvPosition = 0; - if (!(pIns->PitchEnv.dwFlags & ENV_CARRY)) pChn->PitchEnv.nEnvPosition = 0; + + if (!(pIns->VolEnv.dwFlags & ENV_CARRY)) ResetChannelEnvelope(pChn->VolEnv); + if (!(pIns->PanEnv.dwFlags & ENV_CARRY)) ResetChannelEnvelope(pChn->PanEnv); + if (!(pIns->PitchEnv.dwFlags & ENV_CARRY)) ResetChannelEnvelope(pChn->PitchEnv); + if (GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT)) { // Volume Swing @@ -1186,8 +1188,10 @@ ModChannel *pChn = &Chn[nChn]; ModInstrument* pHeader = 0; LPSTR pSample; - if (note > 0x80) note = NOTE_NONE; - if (note < 1) return; + if(!ModCommand::IsNote(note)) + { + return; + } // Always NNA cut - using if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT|MOD_TYPE_MT2))) || (!m_nInstruments) || (bForceCut)) { @@ -3946,7 +3950,7 @@ if (pSmp->uFlags & CHN_PINGPONGLOOP) pChn->dwFlags |= CHN_PINGPONGLOOP; else - pChn->dwFlags &= ~(CHN_PINGPONGLOOP|CHN_PINGPONGFLAG); + pChn->dwFlags &= ~(CHN_PINGPONGLOOP | CHN_PINGPONGFLAG); pChn->dwFlags |= CHN_LOOP; pChn->nLength = pSmp->nLength; pChn->nLoopStart = pSmp->nLoopStart; @@ -3959,7 +3963,7 @@ } } else { - pChn->dwFlags &= ~(CHN_LOOP|CHN_PINGPONGLOOP|CHN_PINGPONGFLAG); + pChn->dwFlags &= ~(CHN_LOOP | CHN_PINGPONGLOOP | CHN_PINGPONGFLAG); pChn->nLength = pSmp->nLength; } } @@ -3967,14 +3971,14 @@ if (pChn->pModInstrument) { const ModInstrument *pIns = pChn->pModInstrument; - if (((pIns->VolEnv.dwFlags & ENV_LOOP) || (GetType() & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (pIns->nFadeOut)) + if (((pIns->VolEnv.dwFlags & ENV_LOOP) || (GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2))) && (pIns->nFadeOut)) { pChn->dwFlags |= CHN_NOTEFADE; } if (pIns->VolEnv.nReleaseNode != ENV_RELEASE_NODE_UNSET) { - pChn->VolEnv.nEnvValueAtReleaseJump = GetVolEnvValueFromPosition(pChn->VolEnv.nEnvPosition, pIns->VolEnv); + pChn->VolEnv.nEnvValueAtReleaseJump = Util::Round<LONG>(pIns->VolEnv.GetValueFromPosition(pChn->VolEnv.nEnvPosition) * 256.0f); pChn->VolEnv.nEnvPosition = pIns->VolEnv.Ticks[pIns->VolEnv.nReleaseNode]; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2012-02-25 22:04:30 UTC (rev 1196) +++ trunk/OpenMPT/soundlib/Sndfile.h 2012-02-26 00:31:46 UTC (rev 1197) @@ -523,9 +523,8 @@ void ProcessPanningEnvelope(ModChannel *pChn); void ProcessPitchFilterEnvelope(ModChannel *pChn, int &period); - void IncrementVolumeEnvelopePosition(ModChannel *pChn); - void IncrementPanningEnvelopePosition(ModChannel *pChn); - void IncrementPitchFilterEnvelopePosition(ModChannel *pChn); + void IncrementEnvelopePosition(ModChannel *pChn, enmEnvelopeTypes envType); + void IncrementEnvelopePositions(ModChannel *pChn); void ProcessInstrumentFade(ModChannel *pChn, int &vol); @@ -708,7 +707,6 @@ bool ReadFixedLineLengthMessage(const BYTE *data, const size_t length, const size_t lineLength, const size_t lineEndingLength, void (*pTextConverter)(char &) = nullptr); public: - int GetVolEnvValueFromPosition(int position, const InstrumentEnvelope &env) const; void ResetChannelEnvelopes(ModChannel *pChn) const; void ResetChannelEnvelope(ModChannelEnvInfo &env) const; Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2012-02-25 22:04:30 UTC (rev 1196) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2012-02-26 00:31:46 UTC (rev 1197) @@ -1091,7 +1091,8 @@ return; } const int envpos = pChn->VolEnv.nEnvPosition - (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); - int envvol = GetVolEnvValueFromPosition(envpos, pIns->VolEnv); + // Get values in [0, 256] + int envval = Util::Round<int>(pIns->VolEnv.GetValueFromPosition(envpos) * 256.0f); // if we are in the release portion of the envelope, // rescale envelope factor so that it is proportional to the release point @@ -1101,18 +1102,18 @@ && pChn->VolEnv.nEnvValueAtReleaseJump != NOT_YET_RELEASED) { int envValueAtReleaseJump = pChn->VolEnv.nEnvValueAtReleaseJump; - int envValueAtReleaseNode = pIns->VolEnv.Values[pIns->VolEnv.nReleaseNode] << 2; + int envValueAtReleaseNode = pIns->VolEnv.Values[pIns->VolEnv.nReleaseNode] * 4; //If we have just hit the release node, force the current env value //to be that of the release node. This works around the case where // we have another node at the same position as the release node. if (envpos == pIns->VolEnv.Ticks[pIns->VolEnv.nReleaseNode]) - envvol = envValueAtReleaseNode; + envval = envValueAtReleaseNode; - int relativeVolumeChange = (envvol - envValueAtReleaseNode) * 2; - envvol = envValueAtReleaseJump + relativeVolumeChange; + int relativeVolumeChange = (envval - envValueAtReleaseNode) * 2; + envval = envValueAtReleaseJump + relativeVolumeChange; } - vol = (vol * Clamp(envvol, 0, 512)) >> 8; + vol = (vol * Clamp(envval, 0, 512)) >> 8; } } @@ -1130,48 +1131,21 @@ // If the envelope is disabled at the very same moment as it is triggered, we do not process anything. return; } + const int envpos = pChn->PanEnv.nEnvPosition - (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); + // Get values in [-32, 32] + const int envval = Util::Round<int>((pIns->PanEnv.GetValueFromPosition(envpos) - 0.5f) * 64.0f); - UINT pt = pIns->PanEnv.nNodes - 1; - for (UINT i = 0; i < (UINT)(pIns->PanEnv.nNodes - 1); i++) - { - if (envpos <= pIns->PanEnv.Ticks[i]) - { - pt = i; - break; - } - } - int x2 = pIns->PanEnv.Ticks[pt], y2 = pIns->PanEnv.Values[pt]; - int x1, envpan; - if (envpos >= x2) - { - envpan = y2; - x1 = x2; - } else if (pt) - { - envpan = pIns->PanEnv.Values[pt - 1]; - x1 = pIns->PanEnv.Ticks[pt - 1]; - } else - { - envpan = 128; - x1 = 0; - } - if ((x2 > x1) && (envpos > x1)) - { - envpan += ((envpos - x1) * (y2 - envpan)) / (x2 - x1); - } - - envpan = Clamp(envpan, 0, 64); int pan = pChn->nPan; - if (pan >= 128) + if(pan >= 128) { - pan += ((envpan - 32) * (256 - pan)) / 32; + pan += (envval * (256 - pan)) / 32; } else { - pan += ((envpan - 32) * (pan)) / 32; + pan += (envval * (pan)) / 32; } - pChn->nRealPan = Clamp(pan, 0, 256); + } } @@ -1188,55 +1162,25 @@ // If the envelope is disabled at the very same moment as it is triggered, we do not process anything. return; } - int envpos = pChn->PitchEnv.nEnvPosition - (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); - UINT pt = pIns->PitchEnv.nNodes - 1; - for (UINT i=0; i<(UINT)(pIns->PitchEnv.nNodes-1); i++) - { - if (envpos <= pIns->PitchEnv.Ticks[i]) - { - pt = i; - break; - } - } - int x2 = pIns->PitchEnv.Ticks[pt]; - int x1, envpitch; - if (envpos >= x2) - { - envpitch = (((int)pIns->PitchEnv.Values[pt]) - ENVELOPE_MID) * 8; - x1 = x2; - } else if (pt) - { - envpitch = (((int)pIns->PitchEnv.Values[pt-1]) - ENVELOPE_MID) * 8; - x1 = pIns->PitchEnv.Ticks[pt-1]; - } else - { - envpitch = 0; - x1 = 0; - } - if (envpos > x2) envpos = x2; - if ((x2 > x1) && (envpos > x1)) - { - int envpitchdest = (((int)pIns->PitchEnv.Values[pt]) - 32) * 8; - envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1); - } - Limit(envpitch, -256, 256); + const int envpos = pChn->PitchEnv.nEnvPosition - (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); + // Get values in [-256, 256] + const int envval = Util::Round<int>((pIns->PitchEnv.GetValueFromPosition(envpos) - 0.5f) * 512.0f); - //if (pIns->PitchEnv.dwFlags & ENV_FILTER) - if (pChn->PitchEnv.flags & ENV_FILTER) + if(pChn->PitchEnv.flags & ENV_FILTER) { // Filter Envelope: controls cutoff frequency #ifndef NO_FILTER - SetupChannelFilter(pChn, !(pChn->dwFlags & CHN_FILTER), envpitch); + SetupChannelFilter(pChn, !(pChn->dwFlags & CHN_FILTER), envval); #endif // NO_FILTER } else { // Pitch Envelope - if(m_nType == MOD_TYPE_MPT && pChn->pModInstrument && pChn->pModInstrument->pTuning) + if(GetType() == MOD_TYPE_MPT && pChn->pModInstrument && pChn->pModInstrument->pTuning) { - if(pChn->nFineTune != envpitch) + if(pChn->nFineTune != envval) { - pChn->nFineTune = envpitch; + pChn->nFineTune = envval; pChn->m_CalculateFreq = true; //Preliminary tests indicated that this behavior //is very close to original(with 12TET) when finestep count @@ -1245,15 +1189,15 @@ } else //Original behavior { - int l = envpitch; - if (l < 0) + int l = envval; + if(l < 0) { l = -l; - if (l > 255) l = 255; + LimitMax(l, 255); period = _muldiv(period, LinearSlideUpTable[l], 0x10000); } else { - if (l > 255) l = 255; + LimitMax(l, 255); period = _muldiv(period, LinearSlideDownTable[l], 0x10000); } } //End: Original behavior. @@ -1262,127 +1206,125 @@ } -void CSoundFile::IncrementVolumeEnvelopePosition(ModChannel *pChn) -//---------------------------------------------------------------- +void CSoundFile::IncrementEnvelopePosition(ModChannel *pChn, enmEnvelopeTypes envType) +//------------------------------------------------------------------------------------ { - const ModInstrument *pIns = pChn->pModInstrument; + ModChannelEnvInfo &chnEnv = pChn->GetEnvelope(envType); - if (pChn->VolEnv.flags & ENV_ENABLED) + if(pChn->pModInstrument == nullptr || !(chnEnv.flags & ENV_ENABLED)) { - // Increase position - UINT position = pChn->VolEnv.nEnvPosition + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 0 : 1); - // Volume Loop ? - if (pIns->VolEnv.dwFlags & ENV_LOOP) + return; + } + + // Increase position + UINT position = chnEnv.nEnvPosition + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 0 : 1); + + const InstrumentEnvelope &insEnv = pChn->pModInstrument->GetEnvelope(envType); + + bool endReached = false; + + if(!IsCompatibleMode(TRK_IMPULSETRACKER)) + { + // FT2-style envelope processing. + if(insEnv.dwFlags & ENV_LOOP) { - UINT volloopend = pIns->VolEnv.Ticks[pIns->VolEnv.nLoopEnd]; - if (GetType() != MOD_TYPE_XM) volloopend++; - if (position == volloopend) + // Normal loop active + UINT end = insEnv.Ticks[insEnv.nLoopEnd]; + if(GetType() != MOD_TYPE_XM) end++; + if(position == end) { - position = pIns->VolEnv.Ticks[pIns->VolEnv.nLoopStart]; - if ((pIns->VolEnv.nLoopEnd == pIns->VolEnv.nLoopStart) && (!pIns->VolEnv.Values[pIns->VolEnv.nLoopStart]) - && ((!(GetType() & MOD_TYPE_XM)) || (pIns->VolEnv.nLoopEnd+1 == (int)pIns->VolEnv.nNodes))) + position = insEnv.Ticks[insEnv.nLoopStart]; + + if(envType == ENV_VOLUME && insEnv.nLoopStart == insEnv.nLoopEnd && insEnv.Values[insEnv.nLoopEnd] == 0 + && (!(GetType() & MOD_TYPE_XM) || (insEnv.nLoopEnd + 1u == insEnv.nNodes))) { pChn->dwFlags |= CHN_NOTEFADE; pChn->nFadeOutVol = 0; } } } - // Volume Sustain ? - if ((pIns->VolEnv.dwFlags & ENV_SUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) + + if((insEnv.dwFlags & ENV_SUSTAIN) && !(pChn->dwFlags & CHN_KEYOFF)) { - if (position == (UINT)pIns->VolEnv.Ticks[pIns->VolEnv.nSustainEnd] + 1) - position = pIns->VolEnv.Ticks[pIns->VolEnv.nSustainStart]; + // Envelope sustained + if(position == insEnv.Ticks[insEnv.nSustainEnd] + 1u) + { + position = insEnv.Ticks[insEnv.nSustainStart]; + } } else { - // End of Envelope ? - if (position > pIns->VolEnv.Ticks[pIns->VolEnv.nNodes - 1]) + // Limit to last envelope point + if(position > insEnv.Ticks[insEnv.nNodes - 1]) { - if ((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE; - position = pIns->VolEnv.Ticks[pIns->VolEnv.nNodes - 1]; - if ((!pIns->VolEnv.Values[pIns->VolEnv.nNodes - 1]) && ((pChn->nMasterChn > 0) || (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)))) - { - pChn->dwFlags |= CHN_NOTEFADE; - pChn->nFadeOutVol = 0; - pChn->nRealVolume = 0; - pChn->nCalcVolume = 0; - } + // Env of envelope + position = insEnv.Ticks[insEnv.nNodes - 1]; + endReached = true; } } - - pChn->VolEnv.nEnvPosition = position + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); - } -} - - -void CSoundFile::IncrementPanningEnvelopePosition(ModChannel *pChn) -//----------------------------------------------------------------- -{ - const ModInstrument *pIns = pChn->pModInstrument; - - if (pChn->PanEnv.flags & ENV_ENABLED) + } else { - // Increase position - UINT position = pChn->PanEnv.nEnvPosition + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 0 : 1); + // IT envelope processing. + // Test case: EnvLoops.it + UINT start, end; - if (pIns->PanEnv.dwFlags & ENV_LOOP) + if((insEnv.dwFlags & ENV_SUSTAIN) && !(pChn->dwFlags & CHN_KEYOFF)) { - UINT panloopend = pIns->PanEnv.Ticks[pIns->PanEnv.nLoopEnd]; - if (GetType() != MOD_TYPE_XM) panloopend++; - if (position == panloopend) - position = pIns->PanEnv.Ticks[pIns->PanEnv.nLoopStart]; - } - - // Panning Sustain ? - if ((pIns->PanEnv.dwFlags & ENV_SUSTAIN) && (position == (UINT)pIns->PanEnv.Ticks[pIns->PanEnv.nSustainEnd] + 1) - && (!(pChn->dwFlags & CHN_KEYOFF))) + // Envelope sustained + start = insEnv.Ticks[insEnv.nSustainStart]; + end = insEnv.Ticks[insEnv.nSustainEnd] + 1; + } else if((insEnv.dwFlags & ENV_LOOP)) { - // Panning sustained - position = pIns->PanEnv.Ticks[pIns->PanEnv.nSustainStart]; + // Normal loop active + start = insEnv.Ticks[insEnv.nLoopStart]; + end = insEnv.Ticks[insEnv.nLoopEnd] + 1; } else { - if (position > pIns->PanEnv.Ticks[pIns->PanEnv.nNodes - 1]) - position = pIns->PanEnv.Ticks[pIns->PanEnv.nNodes - 1]; + // Limit to last envelope point + start = end = insEnv.Ticks[insEnv.nNodes - 1]; + if (position > end) + { + // Env of envelope + endReached = true; + } } - pChn->PanEnv.nEnvPosition = position + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); + if(position >= end) + { + position = start; + } } -} - -void CSoundFile::IncrementPitchFilterEnvelopePosition(ModChannel *pChn) -//--------------------------------------------------------------------- -{ - const ModInstrument *pIns = pChn->pModInstrument; - - if (pChn->PitchEnv.flags & ENV_ENABLED) + if(envType == ENV_VOLUME && endReached) { - // Increase position - UINT position = pChn->PitchEnv.nEnvPosition + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 0 : 1); - - // Pitch Loop ? - if (pIns->PitchEnv.dwFlags & ENV_LOOP) + // Special handling for volume envelopes at end of envelope + if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) || (pChn->dwFlags & CHN_KEYOFF)) { - UINT pitchloopend = pIns->PitchEnv.Ticks[pIns->PitchEnv.nLoopEnd]; - if (GetType() != MOD_TYPE_XM) pitchloopend++; - if (position >= pitchloopend) - position = pIns->PitchEnv.Ticks[pIns->PitchEnv.nLoopStart]; + pChn->dwFlags |= CHN_NOTEFADE; } - // Pitch Sustain ? - if ((pIns->PitchEnv.dwFlags & ENV_SUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF))) + + if(insEnv.Values[insEnv.nNodes - 1] == 0 && (pChn->nMasterChn > 0 || (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)))) { - if (position == (UINT)pIns->PitchEnv.Ticks[pIns->PitchEnv.nSustainEnd]+1) - position = pIns->PitchEnv.Ticks[pIns->PitchEnv.nSustainStart]; - } else - { - if (position > pIns->PitchEnv.Ticks[pIns->PitchEnv.nNodes - 1]) - position = pIns->PitchEnv.Ticks[pIns->PitchEnv.nNodes - 1]; + pChn->dwFlags |= CHN_NOTEFADE; + pChn->nFadeOutVol = 0; + pChn->nRealVolume = 0; + pChn->nCalcVolume = 0; } - - pChn->PitchEnv.nEnvPosition = position + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); } + + chnEnv.nEnvPosition = position + (IsCompatibleMode(TRK_IMPULSETRACKER) ? 1 : 0); + } +void CSoundFile::IncrementEnvelopePositions(ModChannel *pChn) +//----------------------------------------------------------- +{ + IncrementEnvelopePosition(pChn, ENV_VOLUME); + IncrementEnvelopePosition(pChn, ENV_PANNING); + IncrementEnvelopePosition(pChn, ENV_PITCH); +} + + void CSoundFile::ProcessInstrumentFade(ModChannel *pChn, int &vol) //---------------------------------------------------------------- { @@ -2035,9 +1977,7 @@ // When using MPT behaviour, we get the envelope position for the next tick while we are still calculating the current tick, // which then results in wrong position information when the envelope is paused on the next row. // Test case: s77.it - IncrementVolumeEnvelopePosition(pChn); - IncrementPanningEnvelopePosition(pChn); - IncrementPitchFilterEnvelopePosition(pChn); + IncrementEnvelopePositions(pChn); } ProcessVolumeEnvelope(pChn, vol); ProcessInstrumentFade(pChn, vol); @@ -2188,9 +2128,7 @@ { // In IT compatible mode, envelope positions are updated above. // Test case: s77.it - IncrementVolumeEnvelopePosition(pChn); - IncrementPanningEnvelopePosition(pChn); - IncrementPitchFilterEnvelopePosition(pChn); + IncrementEnvelopePositions(pChn); } #ifdef MODPLUG_PLAYER @@ -2533,53 +2471,9 @@ } } +#endif // MODPLUG_TRACKER -int CSoundFile::GetVolEnvValueFromPosition(int position, const InstrumentEnvelope &env) const -//------------------------------------------------------------------------------------------- -{ - UINT pt = env.nNodes - 1; - // Checking where current 'tick' is relative to the - // envelope points. - for (UINT i = 0; i < (UINT)(env.nNodes-1); i++) - { - if (position <= env.Ticks[i]) - { - pt = i; - break; - } - } - - int x2 = env.Ticks[pt]; - int x1, envvol; - if (position >= x2) // Case: current 'tick' is on a envelope point. - { - envvol = env.Values[pt] * 4; - } else // Case: current 'tick' is between two envelope points. - { - if (pt) - { - envvol = env.Values[pt - 1] * 4; - x1 = env.Ticks[pt - 1]; - } else - { - envvol = 0; - x1 = 0; - } - - if(x2 > x1 && position > x1) - { - // Linear approximation between the points; - // f(x+d) ~ f(x) + f'(x)*d, where f'(x) = (y2-y1)/(x2-x1) - envvol += ((position - x1) * (((int)env.Values[pt] * 4) - envvol)) / (x2 - x1); - } - } - return envvol; -} - -#endif - - void CSoundFile::ApplyGlobalVolume(int SoundBuffer[], int RearBuffer[], long lTotalSampleCount) //--------------------------------------------------------------------------------------------- { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |