From: <sag...@us...> - 2012-02-25 22:04:37
|
Revision: 1196 http://modplug.svn.sourceforge.net/modplug/?rev=1196&view=rev Author: saga-games Date: 2012-02-25 22:04:30 +0000 (Sat, 25 Feb 2012) Log Message: ----------- [Mod] IT Compatibility: Pitch envelope loop length is now identical in compatible and normal mode. To compensate for the missing tick in normal mode, pitch loops made with older versions of MPT are fixed upon loading. [Imp] Mod Conversion: Envelope loops are now fixed automatically when converting between XM and IT files. [Ref] Moved sample / instrument conversion code to ModInstrument.cpp / ModSample.cpp [Mod] OpenMPT: Version is now 1.20.00.71 Modified Paths: -------------- trunk/OpenMPT/mptrack/ModConvert.cpp trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/ModChannel.h trunk/OpenMPT/soundlib/ModInstrument.cpp trunk/OpenMPT/soundlib/ModInstrument.h trunk/OpenMPT/soundlib/ModSample.h trunk/OpenMPT/soundlib/Sampleio.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp Added Paths: ----------- trunk/OpenMPT/soundlib/ModSample.cpp Modified: trunk/OpenMPT/mptrack/ModConvert.cpp =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.cpp 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/mptrack/ModConvert.cpp 2012-02-25 22:04:30 UTC (rev 1196) @@ -296,7 +296,7 @@ CHANGEMODTYPE_WARNING(wMODSampleFrequency); } - m_SndFile.ConvertSample(nSmp, nOldType, nNewType); + sample.Convert(nOldType, nNewType); } for(INSTRUMENTINDEX nIns = 1; nIns <= m_SndFile.GetNumInstruments(); nIns++) @@ -344,7 +344,7 @@ } } - m_SndFile.ConvertInstrument(nIns, nOldType, nNewType); + pIns->Convert(nOldType, nNewType); } if(newTypeIsMOD) Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2012-02-25 22:04:30 UTC (rev 1196) @@ -316,6 +316,9 @@ RelativePath="..\soundlib\ModInstrument.cpp"> </File> <File + RelativePath="..\soundlib\ModSample.cpp"> + </File> + <File RelativePath=".\ModConvert.cpp"> </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2012-02-25 22:04:30 UTC (rev 1196) @@ -425,6 +425,10 @@ > </File> <File + RelativePath="..\soundlib\ModSample.cpp" + > + </File> + <File RelativePath=".\ModConvert.cpp" > </File> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2012-02-25 22:04:30 UTC (rev 1196) @@ -171,6 +171,7 @@ <ClCompile Include="..\common\Reporting.cpp" /> <ClCompile Include="..\soundlib\MIDIMacros.cpp" /> <ClCompile Include="..\soundlib\ModInstrument.cpp" /> + <ClCompile Include="..\soundlib\ModSample.cpp" /> <ClCompile Include="AbstractVstEditor.cpp" /> <ClCompile Include="ACMConvert.cpp" /> <ClCompile Include="ArrayUtils.cpp" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2012-02-25 22:04:30 UTC (rev 1196) @@ -433,6 +433,9 @@ <ClCompile Include="PSRatioCalc.cpp"> <Filter>Source Files\Dialogs</Filter> </ClCompile> + <ClCompile Include="..\soundlib\ModSample.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="AbstractVstEditor.h"> Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/mptrack/version.h 2012-02-25 22:04:30 UTC (rev 1196) @@ -19,7 +19,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 20 #define VER_MINOR 00 -#define VER_MINORMINOR 70 +#define VER_MINORMINOR 71 //Creates version number from version parts that appears in version string. //For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of Modified: trunk/OpenMPT/soundlib/ModChannel.h =================================================================== --- trunk/OpenMPT/soundlib/ModChannel.h 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/ModChannel.h 2012-02-25 22:04:30 UTC (rev 1196) @@ -102,7 +102,8 @@ void ClearRowCmd() { rowCommand = ModCommand::Empty(); } - ModChannelEnvInfo &GetEnvelope(enmEnvelopeTypes envType) + // Get a reference to a specific envelope of this channel + const ModChannelEnvInfo &GetEnvelope(enmEnvelopeTypes envType) const { switch(envType) { @@ -116,6 +117,11 @@ } } + ModChannelEnvInfo &GetEnvelope(enmEnvelopeTypes envType) + { + return const_cast<ModChannelEnvInfo &>(static_cast<const ModChannel &>(*this).GetEnvelope(envType)); + } + typedef UINT VOLUME; VOLUME GetVSTVolume() {return (pModInstrument) ? pModInstrument->nGlobalVol * 4 : nVolume;} Modified: trunk/OpenMPT/soundlib/ModInstrument.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModInstrument.cpp 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/ModInstrument.cpp 2012-02-25 22:04:30 UTC (rev 1196) @@ -13,6 +13,104 @@ #include "ModInstrument.h" +// Convert envelope data between various formats. +void InstrumentEnvelope::Convert(MODTYPE fromType, MODTYPE toType) +//---------------------------------------------------------------- +{ + if(!(fromType & MOD_TYPE_XM) && (toType & MOD_TYPE_XM)) + { + // IT / MPTM -> XM: Expand loop by one tick, convert sustain loops to sustain points, remove carry flag. + nSustainStart = nSustainEnd; + dwFlags &= ~ENV_CARRY; + + if(nLoopEnd > nLoopStart && (dwFlags & ENV_LOOP)) + { + for(UINT node = nLoopEnd; node < nNodes; node++) + { + Ticks[node]++; + } + } + } else if((fromType & MOD_TYPE_XM) && !(toType & MOD_TYPE_XM)) + { + // XM -> IT / MPTM: Shorten loop by one tick by inserting bogus point + if(nLoopEnd > nLoopStart && (dwFlags & ENV_LOOP)) + { + if(Ticks[nLoopEnd] - 1 > Ticks[nLoopEnd - 1]) + { + // Insert an interpolated point just before the loop point. + BYTE interpolatedValue = Util::Round<BYTE>(GetValueFromPosition(Ticks[nLoopEnd] - 1) * 64.0f); + + + if(nNodes + 1 < MAX_ENVPOINTS) + { + // Should always be possible, since XM only allows for 12 envelope points anyway. + for(UINT node = nNodes; node >= nLoopEnd; node--) + { + Ticks[node + 1] = Ticks[node]; + Values[node + 1] = Values[node]; + } + } + + Ticks[nLoopEnd]--; + Values[nLoopEnd] = (BYTE)interpolatedValue; + + nNodes++; + } else + { + // There is already a point before the loop point: Use it as loop end. + nLoopEnd--; + } + + } + } +}; + + +// Get envelope value at a given tick. Returns value in range [0.0, 1.0]. +float InstrumentEnvelope::GetValueFromPosition(int position) const +//---------------------------------------------------------------- +{ + UINT pt = nNodes - 1; + + // Checking where current 'tick' is relative to the envelope points. + for(UINT i = 0; i < nNodes - 1u; i++) + { + if (position <= Ticks[i]) + { + pt = i; + break; + } + } + + int x2 = Ticks[pt]; + float value = 0.0f; + + if(position >= x2) + { + // Case: current 'tick' is on a envelope point. + value = static_cast<float>(Values[pt]) / 64.0f; + } else + { + // Case: current 'tick' is between two envelope points. + int x1 = 0; + + if (pt) + { + value = static_cast<float>(Values[pt - 1]) / 64.0f; + x1 = Ticks[pt - 1]; + } + + 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) + value += ((position - x1) * (static_cast<float>(Values[pt]) / 64.0f - value)) / (x2 - x1); + } + } + return value; +}; + + ModInstrument::ModInstrument(SAMPLEINDEX sample) //---------------------------------------------- { @@ -56,3 +154,59 @@ MemsetZero(name); MemsetZero(filename); } + + +// Translate instrument properties between two given formats. +void ModInstrument::Convert(MODTYPE fromType, MODTYPE toType) +//----------------------------------------------------------- +{ + UNREFERENCED_PARAMETER(fromType); + + if(toType & MOD_TYPE_XM) + { + ResetNoteMap(); + + PitchEnv.dwFlags &= ~(ENV_ENABLED|ENV_FILTER); + + dwFlags &= ~INS_SETPANNING; + SetCutoff(GetCutoff(), false); + SetResonance(GetResonance(), false); + nFilterMode = FLTMODE_UNCHANGED; + + nCutSwing = nPanSwing = nResSwing = nVolSwing = 0; + + nPPC = NOTE_MIDDLEC - 1; + nPPS = 0; + + nNNA = NNA_NOTECUT; + nDCT = DCT_NONE; + nDNA = DNA_NOTECUT; + + if(nMidiChannel == MidiMappedChannel) + { + nMidiChannel = 1; + } + + nGlobalVol = 64; + nPan = 128; + + LimitMax(nFadeOut, 32767u); + } + + VolEnv.Convert(fromType, toType); + PanEnv.Convert(fromType, toType); + PitchEnv.Convert(fromType, toType); + + // Limit fadeout length for IT / MPT + if(toType & (MOD_TYPE_IT | MOD_TYPE_MPT)) + { + LimitMax(nFadeOut, 8192u); + } + + // MPT-specific features - remove instrument tunings, Pitch/Tempo Lock for other formats + if(!(toType & MOD_TYPE_MPT)) + { + SetTuning(nullptr); + wPitchToTempoLock = 0; + } +} Modified: trunk/OpenMPT/soundlib/ModInstrument.h =================================================================== --- trunk/OpenMPT/soundlib/ModInstrument.h 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/ModInstrument.h 2012-02-25 22:04:30 UTC (rev 1196) @@ -33,6 +33,13 @@ MemsetZero(Ticks); MemsetZero(Values); } + + // Convert envelope data between various formats. + void Convert(MODTYPE fromType, MODTYPE toType); + + // Get envelope value at a given tick. Returns value in range [0.0, 1.0]. + float GetValueFromPosition(int position) const; + }; // Instrument Struct @@ -120,7 +127,7 @@ bool HasValidMIDIChannel() const { return (nMidiChannel >= 1 && nMidiChannel <= 17); } // Get a reference to a specific envelope of this instrument - InstrumentEnvelope &GetEnvelope(enmEnvelopeTypes envType) + const InstrumentEnvelope &GetEnvelope(enmEnvelopeTypes envType) const { switch(envType) { @@ -134,6 +141,11 @@ } } + InstrumentEnvelope &GetEnvelope(enmEnvelopeTypes envType) + { + return const_cast<InstrumentEnvelope &>(static_cast<const ModInstrument &>(*this).GetEnvelope(envType)); + } + // Get a set of all samples referenced by this instrument std::set<SAMPLEINDEX> GetSamples() const { @@ -151,4 +163,7 @@ return referencedSamples; } + // Translate instrument properties between two given formats. + void Convert(MODTYPE fromType, MODTYPE toType); + }; Added: trunk/OpenMPT/soundlib/ModSample.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModSample.cpp (rev 0) +++ trunk/OpenMPT/soundlib/ModSample.cpp 2012-02-25 22:04:30 UTC (rev 1196) @@ -0,0 +1,90 @@ +/* + * ModSample.h + * ----------- + * Purpose: Module Sample header class and helpers + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "stdafx.h" +#include "Sndfile.h" +#include "ModSample.h" + + +// Translate sample properties between two given formats. +void ModSample::Convert(MODTYPE fromType, MODTYPE toType) +//------------------------------------------------------- +{ + // Convert between frequency and transpose values if necessary. + if ((!(toType & (MOD_TYPE_MOD | MOD_TYPE_XM))) && (fromType & (MOD_TYPE_MOD | MOD_TYPE_XM))) + { + nC5Speed = CSoundFile::TransposeToFrequency(RelativeTone, nFineTune); + RelativeTone = 0; + nFineTune = 0; + } else if((toType & (MOD_TYPE_MOD | MOD_TYPE_XM)) && (!(fromType & (MOD_TYPE_MOD | MOD_TYPE_XM)))) + { + CSoundFile::FrequencyToTranspose(this); + if(toType & MOD_TYPE_MOD) + { + RelativeTone = 0; + } + } + + // No ping-pong loop, panning and auto-vibrato for MOD / S3M samples + if(toType & (MOD_TYPE_MOD | MOD_TYPE_S3M)) + { + uFlags &= ~(CHN_PINGPONGLOOP | CHN_PANNING); + + nVibDepth = 0; + nVibRate = 0; + nVibSweep = 0; + nVibType = VIB_SINE; + } + + // No sustain loops for MOD/S3M/XM + if(toType & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_S3M)) + { + // Sustain loops - convert to normal loops + if((uFlags & CHN_SUSTAINLOOP) != 0) + { + // We probably overwrite a normal loop here, but since sustain loops are evaluated before normal loops, this is just correct. + nLoopStart = nSustainStart; + nLoopEnd = nSustainEnd; + uFlags |= CHN_LOOP; + if(uFlags & CHN_PINGPONGSUSTAIN) + { + uFlags |= CHN_PINGPONGLOOP; + } else + { + uFlags &= ~CHN_PINGPONGLOOP; + } + } + nSustainStart = nSustainEnd = 0; + uFlags &= ~(CHN_SUSTAINLOOP|CHN_PINGPONGSUSTAIN); + } + + // All XM samples have default panning, and XM's autovibrato settings are rather limited. + if(toType & MOD_TYPE_XM) + { + if(!(uFlags & CHN_PANNING)) + { + uFlags |= CHN_PANNING; + nPan = 128; + } + + LimitMax(nVibDepth, BYTE(15)); + LimitMax(nVibRate, BYTE(63)); + } + + + // Autovibrato sweep setting is inverse in XM (0 = "no sweep") and IT (0 = "no vibrato") + if(((fromType & MOD_TYPE_XM) && (toType & (MOD_TYPE_IT | MOD_TYPE_MPT))) || ((toType & MOD_TYPE_XM) && (fromType & (MOD_TYPE_IT | MOD_TYPE_MPT)))) + { + if(nVibRate != 0 && nVibDepth != 0) + { + nVibSweep = 255 - nVibSweep; + } + } +} Modified: trunk/OpenMPT/soundlib/ModSample.h =================================================================== --- trunk/OpenMPT/soundlib/ModSample.h 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/ModSample.h 2012-02-25 22:04:30 UTC (rev 1196) @@ -45,4 +45,7 @@ // Returns sample rate of the sample. The argument is needed because // the sample rate is obtained differently for different module types. uint32 GetSampleRate(const MODTYPE type) const; + + // Translate sample properties between two given formats. + void Convert(MODTYPE fromType, MODTYPE toType); }; Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2012-02-25 22:04:30 UTC (rev 1196) @@ -250,7 +250,7 @@ } } - ConvertInstrument(targetInstr, pSrcSong->GetType()); + pIns->Convert(pSrcSong->GetType(), GetType()); // Copy all referenced samples over for(size_t i = 0; i < targetSample.size(); i++) @@ -290,7 +290,7 @@ } } - ConvertSample(targetSample, pSrcSong->GetType()); + Samples[targetSample].Convert(pSrcSong->GetType(), GetType()); return true; } @@ -544,7 +544,7 @@ } } } - ConvertSample(nSample, MOD_TYPE_IT); + pSmp->Convert(MOD_TYPE_IT, GetType()); return true; } @@ -1036,7 +1036,7 @@ pSmp->RelativeTone = 0; pSmp->nFineTune = 0; - ConvertSample(nSample, MOD_TYPE_S3M); + pSmp->Convert(MOD_TYPE_S3M, GetType()); if (pss->flags & 0x01) pSmp->uFlags |= CHN_LOOP; flags = (pss->flags & 0x04) ? RS_PCM16U : RS_PCM8U; @@ -1262,7 +1262,7 @@ memcpy(pSmp->filename, psh->name, 22); pSmp->filename[21] = 0; - ConvertSample(samplemap[ismp], MOD_TYPE_XM); + pSmp->Convert(MOD_TYPE_XM, GetType()); } // Reading sample data for (UINT dsmp=0; dsmp<nsamples; dsmp++) @@ -1273,7 +1273,7 @@ dwMemPos += samplesize[dsmp]; } - ConvertInstrument(nInstr, MOD_TYPE_XM); + pIns->Convert(MOD_TYPE_XM, GetType()); // -> CODE#0027 // -> DESC="per-instrument volume ramping setup (refered as attack)" @@ -1501,7 +1501,7 @@ memcpy(pSmp->filename, psh->name, 22); pSmp->filename[21] = 0; } - ConvertSample(nSample, MOD_TYPE_XM); + pSmp->Convert(MOD_TYPE_XM, GetType()); if (dwMemPos >= dwFileLength) return true; ReadSample(pSmp, sampleflags, (LPSTR)(lpMemFile+dwMemPos), dwFileLength-dwMemPos); return true; @@ -1707,7 +1707,7 @@ if (pis->flags & 8) flags = RS_IT2148; } - ConvertSample(nSample, MOD_TYPE_IT); + pSmp->Convert(MOD_TYPE_IT, GetType()); // -> CODE#0027 // -> DESC="per-instrument volume ramping setup (refered as attack)" @@ -1792,7 +1792,7 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwFileLength) return true; - ConvertInstrument(nInstr, MOD_TYPE_IT); + pIns->Convert(MOD_TYPE_IT, GetType()); ReadExtendedInstrumentProperties(pIns, lpMemFile + dwMemPos, dwFileLength - dwMemPos); @@ -2185,161 +2185,3 @@ } return (pSmp->pSample != nullptr); } - - -// Translate sample properties between two given formats. -void CSoundFile::ConvertSample(SAMPLEINDEX sample, MODTYPE fromType, MODTYPE toType) -//---------------------------------------------------------------------------------- -{ - if(toType == MOD_TYPE_NONE) - { - toType = GetType(); - } - - if(sample < 1 || sample > GetNumSamples()) - { - return; - } - - ModSample &smp = GetSample(sample); - // Convert between frequency and transpose values if necessary. - if ((!(toType & (MOD_TYPE_MOD | MOD_TYPE_XM))) && (fromType & (MOD_TYPE_MOD | MOD_TYPE_XM))) - { - smp.nC5Speed = TransposeToFrequency(smp.RelativeTone, smp.nFineTune); - smp.RelativeTone = 0; - smp.nFineTune = 0; - } else if((toType & (MOD_TYPE_MOD | MOD_TYPE_XM)) && (!(fromType & (MOD_TYPE_MOD | MOD_TYPE_XM)))) - { - FrequencyToTranspose(&smp); - if(toType & MOD_TYPE_MOD) - { - smp.RelativeTone = 0; - } - } - - // No ping-pong loop, panning and auto-vibrato for MOD / S3M samples - if(toType & (MOD_TYPE_MOD | MOD_TYPE_S3M)) - { - smp.uFlags &= ~(CHN_PINGPONGLOOP | CHN_PANNING); - - smp.nVibDepth = 0; - smp.nVibRate = 0; - smp.nVibSweep = 0; - smp.nVibType = VIB_SINE; - } - - // No sustain loops for MOD/S3M/XM - if(toType & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_S3M)) - { - // Sustain loops - convert to normal loops - if((smp.uFlags & CHN_SUSTAINLOOP) != 0) - { - // We probably overwrite a normal loop here, but since sustain loops are evaluated before normal loops, this is just correct. - smp.nLoopStart = smp.nSustainStart; - smp.nLoopEnd = smp.nSustainEnd; - smp.uFlags |= CHN_LOOP; - if(smp.uFlags & CHN_PINGPONGSUSTAIN) - { - smp.uFlags |= CHN_PINGPONGLOOP; - } else - { - smp.uFlags &= ~CHN_PINGPONGLOOP; - } - } - smp.nSustainStart = smp.nSustainEnd = 0; - smp.uFlags &= ~(CHN_SUSTAINLOOP|CHN_PINGPONGSUSTAIN); - } - - // All XM samples have default panning, and XM's autovibrato settings are rather limited. - if(toType & MOD_TYPE_XM) - { - if(!(smp.uFlags & CHN_PANNING)) - { - smp.uFlags |= CHN_PANNING; - smp.nPan = 128; - } - - LimitMax(smp.nVibDepth, BYTE(15)); - LimitMax(smp.nVibRate, BYTE(63)); - } - - - // Autovibrato sweep setting is inverse in XM (0 = "no sweep") and IT (0 = "no vibrato") - if(((fromType & MOD_TYPE_XM) && (toType & (MOD_TYPE_IT | MOD_TYPE_MPT))) || ((toType & MOD_TYPE_XM) && (fromType & (MOD_TYPE_IT | MOD_TYPE_MPT)))) - { - if(smp.nVibRate != 0 && smp.nVibDepth != 0) - { - smp.nVibSweep = 255 - smp.nVibSweep; - } - } -} - - -// Translate instrument properties between two given formats. -void CSoundFile::ConvertInstrument(INSTRUMENTINDEX instr, MODTYPE fromType, MODTYPE toType) -//----------------------------------------------------------------------------------------- -{ - UNREFERENCED_PARAMETER(fromType); - - if(toType == MOD_TYPE_NONE) - { - toType = GetType(); - } - - if(instr < 1 || instr > GetNumInstruments() || Instruments[instr] == nullptr) - { - return; - } - - ModInstrument *pIns = Instruments[instr]; - - if(toType & MOD_TYPE_XM) - { - pIns->ResetNoteMap(); - - // Convert sustain loops to sustain "points" - pIns->VolEnv.nSustainEnd = pIns->VolEnv.nSustainStart; - pIns->PanEnv.nSustainEnd = pIns->PanEnv.nSustainStart; - - pIns->VolEnv.dwFlags &= ~ENV_CARRY; - pIns->PanEnv.dwFlags &= ~ENV_CARRY; - pIns->PitchEnv.dwFlags &= ~(ENV_CARRY|ENV_ENABLED|ENV_FILTER); - - pIns->dwFlags &= ~INS_SETPANNING; - pIns->SetCutoff(pIns->GetCutoff(), false); - pIns->SetResonance(pIns->GetResonance(), false); - pIns->nFilterMode = FLTMODE_UNCHANGED; - - pIns->nCutSwing = pIns->nPanSwing = pIns->nResSwing = pIns->nVolSwing = 0; - - pIns->nPPC = NOTE_MIDDLEC - 1; - pIns->nPPS = 0; - - pIns->nNNA = NNA_NOTECUT; - pIns->nDCT = DCT_NONE; - pIns->nDNA = DNA_NOTECUT; - - if(pIns->nMidiChannel == MidiMappedChannel) - { - pIns->nMidiChannel = 1; - } - - pIns->nGlobalVol = 64; - pIns->nPan = 128; - - LimitMax(pIns->nFadeOut, 32767u); - } - - // Limit fadeout length for IT / MPT - if(toType & (MOD_TYPE_IT | MOD_TYPE_MPT)) - { - LimitMax(pIns->nFadeOut, 8192u); - } - - // MPT-specific features - remove instrument tunings, Pitch/Tempo Lock for other formats - if(!(toType & MOD_TYPE_MPT)) - { - pIns->SetTuning(nullptr); - pIns->wPitchToTempoLock = 0; - } -} Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2012-02-25 22:04:30 UTC (rev 1196) @@ -2487,7 +2487,7 @@ { GetpModDoc()->GetSampleUndo().PrepareUndo(nSmp, sundo_replace); } -#endif // MODPLUG_TRACKER +#endif // MODPLUG_TRACKER if(DestroySample(nSmp)) { @@ -2510,7 +2510,7 @@ LPSTR pSample = pSmp->pSample; pSmp->pSample = nullptr; pSmp->nLength = 0; - pSmp->uFlags &= ~(CHN_16BIT); + pSmp->uFlags &= ~(CHN_16BIT | CHN_STEREO); for (UINT i=0; i<MAX_CHANNELS; i++) { if (Chn[i].pSample == pSample) @@ -2725,7 +2725,7 @@ { if(strcmp(m_szNames[0], titleCandidate)) { - strncpy(m_szNames[0], titleCandidate, min(MAX_SAMPLENAME - 1, strSize)); + strncpy(m_szNames[0], titleCandidate, min(CountOf(m_szNames[0]), strSize)); StringFixer::SetNullTerminator(m_szNames[0]); return true; } @@ -2748,14 +2748,16 @@ { switch(m_nTempoMode) { + case tempo_mode_classic: default: + m_nSamplesPerTick = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); + + case tempo_mode_modern: + m_nSamplesPerTick = gdwMixingFreq * (60 / m_nMusicTempo / (m_nMusicSpeed * m_nCurrentRowsPerBeat)); + break; + case tempo_mode_alternative: m_nSamplesPerTick = gdwMixingFreq / m_nMusicTempo; break; - case tempo_mode_modern: - m_nSamplesPerTick = gdwMixingFreq * (60/m_nMusicTempo / (m_nMusicSpeed * m_nCurrentRowsPerBeat)); - break; - case tempo_mode_classic: default: - m_nSamplesPerTick = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8); } } @@ -2881,7 +2883,7 @@ //------------------------------------------------ { // Setup LRRL panning, max channel volume - if((m_nType & MOD_TYPE_MOD) == 0 && bForceSetup == false) return; + if((GetType() & MOD_TYPE_MOD) == 0 && bForceSetup == false) return; for(CHANNELINDEX nChn = 0; nChn < MAX_BASECHANNELS; nChn++) { @@ -2916,7 +2918,7 @@ // If there are any plugins, enable volume bug emulation. for(PLUGINDEX i = 0; i < MAX_MIXPLUGINS; i++) { - if(m_MixPlugins[i].Info.dwPluginId1 | m_MixPlugins[i].Info.dwPluginId2) + if((m_MixPlugins[i].Info.dwPluginId1 | m_MixPlugins[i].Info.dwPluginId2)) { SetModFlag(MSF_MIDICC_BUGEMULATION, true); break; @@ -3033,6 +3035,14 @@ // This was corrected in compatible mode in OpenMPT 1.18, and in OpenMPT 1.20 it is corrected in normal mode as well. Instruments[i]->nPPS = (Instruments[i]->nPPS + (Instruments[i]->nPPS >= 0 ? 1 : -1)) / 2; } + + if(!IsCompatibleMode(TRK_IMPULSETRACKER) || m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 03, 02)) + { + // IT compatibility 24. Short envelope loops + // Previously, the pitch / filter envelope loop handling was broken, the loop was shortened by a tick (like in XM). + // This was corrected in compatible mode in OpenMPT 1.17.03.02, and in OpenMPT 1.20 it is corrected in normal mode as well. + Instruments[i]->GetEnvelope(ENV_PITCH).Convert(MOD_TYPE_XM, GetType()); + } } if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && (m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 03, 02) || !IsCompatibleMode(TRK_IMPULSETRACKER))) Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/Sndfile.h 2012-02-25 22:04:30 UTC (rev 1196) @@ -325,7 +325,7 @@ SAMPLEINDEX GetNumSamples() const { return m_nSamples; } UINT GetCurrentPos() const; PATTERNINDEX GetCurrentPattern() const { return m_nPattern; } - ORDERINDEX GetCurrentOrder() const { return static_cast<ORDERINDEX>(m_nCurrentOrder); } + ORDERINDEX GetCurrentOrder() const { return m_nCurrentOrder; } CHANNELINDEX GetNumChannels() const { return m_nChannels; } IMixPlugin* GetInstrumentPlugin(INSTRUMENTINDEX instr); @@ -348,7 +348,7 @@ public: //Returns song length in seconds. - DWORD GetSongTime() { return static_cast<DWORD>((m_nTempoMode == tempo_mode_alternative) ? GetLength(eNoAdjust).duration + 1.0 : GetLength(eNoAdjust).duration + 0.5); } + DWORD GetSongTime() { return static_cast<DWORD>(GetLength(eNoAdjust).duration + 0.5); } void RecalculateSamplesPerTick(); double GetRowDuration(UINT tempo, UINT speed, UINT additionalTicks = 0) const; @@ -356,7 +356,7 @@ // A repeat count value of -1 means infinite loop void SetRepeatCount(int n) { m_nRepeatCount = n; } int GetRepeatCount() const { return m_nRepeatCount; } - bool IsPaused() const { return (m_dwSongFlags & (SONG_PAUSED|SONG_STEP)) != 0; } // Added SONG_STEP as it seems to be desirable in most cases to check for this as well. + bool IsPaused() const { return (m_dwSongFlags & (SONG_PAUSED | SONG_STEP)) != 0; } // Added SONG_STEP as it seems to be desirable in most cases to check for this as well. void LoopPattern(PATTERNINDEX nPat, ROWINDEX nRow = 0); void CheckCPUUsage(UINT nCPU); @@ -434,11 +434,6 @@ static void S3MSxx2MODExx(ModCommand *m); // Convert Sxx to Exx void SetupMODPanning(bool bForceSetup = false); // Setup LRRL panning, max channel volume - // Translate sample properties between two given formats. - void ConvertSample(SAMPLEINDEX sample, MODTYPE fromType, MODTYPE toType = MOD_TYPE_NONE); - // Translate instrument properties between two given formats. - void ConvertInstrument(INSTRUMENTINDEX instr, MODTYPE fromType, MODTYPE toType = MOD_TYPE_NONE); - public: // Real-time sound functions void SuspendPlugins(); //rewbs.VSTCompliance @@ -523,6 +518,7 @@ void ProcessTremolo(ModChannel *pChn, int &vol); void ProcessTremor(ModChannel *pChn, int &vol); + bool IsEnvelopeProcessed(const ModChannel *pChn, enmEnvelopeTypes env) const; void ProcessVolumeEnvelope(ModChannel *pChn, int &vol); void ProcessPanningEnvelope(ModChannel *pChn); void ProcessPitchFilterEnvelope(ModChannel *pChn, int &period); Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2012-02-25 21:56:25 UTC (rev 1195) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2012-02-25 22:04:30 UTC (rev 1196) @@ -1063,14 +1063,28 @@ } +bool CSoundFile::IsEnvelopeProcessed(const ModChannel *pChn, enmEnvelopeTypes env) const +//-------------------------------------------------------------------------------------- +{ + if(pChn->pModInstrument == nullptr) + { + return false; + } + const InstrumentEnvelope &insEnv = pChn->pModInstrument->GetEnvelope(env); + + // IT Compatibility: S77/S79/S7B do not disable the envelope, they just pause the counter + return (((pChn->GetEnvelope(env).flags & ENV_ENABLED) || ((insEnv.dwFlags & ENV_ENABLED) && IsCompatibleMode(TRK_IMPULSETRACKER))) + && insEnv.nNodes != 0); +} + + void CSoundFile::ProcessVolumeEnvelope(ModChannel *pChn, int &vol) //---------------------------------------------------------------- { - const ModInstrument *pIns = pChn->pModInstrument; + if(IsEnvelopeProcessed(pChn, ENV_VOLUME)) + { + const ModInstrument *pIns = pChn->pModInstrument; - // IT Compatibility: S77 does not disable the volume envelope, it just pauses the counter - if (((pChn->VolEnv.flags & ENV_ENABLED) || ((pIns->VolEnv.dwFlags & ENV_ENABLED) && IsCompatibleMode(TRK_IMPULSETRACKER))) && (pIns->VolEnv.nNodes)) - { if(IsCompatibleMode(TRK_IMPULSETRACKER) && pChn->VolEnv.nEnvPosition == 0) { // If the envelope is disabled at the very same moment as it is triggered, we do not process anything. @@ -1107,11 +1121,10 @@ void CSoundFile::ProcessPanningEnvelope(ModChannel *pChn) //------------------------------------------------------- { - const ModInstrument *pIns = pChn->pModInstrument; + if(IsEnvelopeProcessed(pChn, ENV_PANNING)) + { + const ModInstrument *pIns = pChn->pModInstrument; - // IT Compatibility: S79 does not disable the panning envelope, it just pauses the counter - if (((pChn->PanEnv.flags & ENV_ENABLED) || ((pIns->PanEnv.dwFlags & ENV_ENABLED) && IsCompatibleMode(TRK_IMPULSETRACKER))) && (pIns->PanEnv.nNodes)) - { if(IsCompatibleMode(TRK_IMPULSETRACKER) && pChn->PanEnv.nEnvPosition == 0) { // If the envelope is disabled at the very same moment as it is triggered, we do not process anything. @@ -1166,11 +1179,10 @@ void CSoundFile::ProcessPitchFilterEnvelope(ModChannel *pChn, int &period) //------------------------------------------------------------------------ { - const ModInstrument *pIns = pChn->pModInstrument; + if(IsEnvelopeProcessed(pChn, ENV_PITCH)) + { + const ModInstrument *pIns = pChn->pModInstrument; - // IT Compatibility: S7B does not disable the pitch envelope, it just pauses the counter - if ((pIns) && ((pChn->PitchEnv.flags & ENV_ENABLED) || ((pIns->PitchEnv.dwFlags & ENV_ENABLED) && IsCompatibleMode(TRK_IMPULSETRACKER))) && (pChn->pModInstrument->PitchEnv.nNodes)) - { if(IsCompatibleMode(TRK_IMPULSETRACKER) && pChn->PitchEnv.nEnvPosition == 0) { // If the envelope is disabled at the very same moment as it is triggered, we do not process anything. @@ -1351,8 +1363,7 @@ if (pIns->PitchEnv.dwFlags & ENV_LOOP) { UINT pitchloopend = pIns->PitchEnv.Ticks[pIns->PitchEnv.nLoopEnd]; - //IT compatibility 24. Short envelope loops - if (IsCompatibleMode(TRK_IMPULSETRACKER)) pitchloopend++; + if (GetType() != MOD_TYPE_XM) pitchloopend++; if (position >= pitchloopend) position = pIns->PitchEnv.Ticks[pIns->PitchEnv.nLoopStart]; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |