From: <sag...@us...> - 2013-10-21 12:54:03
|
Revision: 2958 http://sourceforge.net/p/modplug/code/2958 Author: saga-games Date: 2013-10-21 12:53:54 +0000 (Mon, 21 Oct 2013) Log Message: ----------- [Fix] AMS Loader: Default speed + tempo was broken since rev.1977 [Fix] AMS Loader: Velvet Studio format version was printed wrong. [Fix] AMS Loader: Instrument Fadeout was too quick. [Fix] AMS Loader: Vibrato Envelope is now imported more correctly. Works best in libopenmpt builds, since in that case the envelope is kept in a more precise manner than IT-compatible envelopes allow. [Imp] AMS Loader: Added support for AMS format 2.00 Modified Paths: -------------- trunk/OpenMPT/common/versionNumber.h trunk/OpenMPT/soundlib/Load_ams.cpp trunk/OpenMPT/soundlib/ModInstrument.cpp trunk/OpenMPT/soundlib/ModInstrument.h trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/common/versionNumber.h =================================================================== --- trunk/OpenMPT/common/versionNumber.h 2013-10-21 11:03:05 UTC (rev 2957) +++ trunk/OpenMPT/common/versionNumber.h 2013-10-21 12:53:54 UTC (rev 2958) @@ -17,7 +17,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 22 #define VER_MINOR 05 -#define VER_MINORMINOR 06 +#define VER_MINORMINOR 07 //Version string. For example "1.17.02.28" #define MPT_VERSION_STR VER_STRINGIZE(VER_MAJORMAJOR) "." VER_STRINGIZE(VER_MAJOR) "." VER_STRINGIZE(VER_MINOR) "." VER_STRINGIZE(VER_MINORMINOR) Modified: trunk/OpenMPT/soundlib/Load_ams.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ams.cpp 2013-10-21 11:03:05 UTC (rev 2957) +++ trunk/OpenMPT/soundlib/Load_ams.cpp 2013-10-21 12:53:54 UTC (rev 2958) @@ -411,7 +411,7 @@ m_nSamples = fileHeader.numSamps; SetModFlag(MSF_COMPATIBLE_PLAY, true); SetupMODPanning(true); - madeWithTracker = mpt::String::Format("Extreme's tracker %d.%d", fileHeader.versionHigh, fileHeader.versionLow); + madeWithTracker = mpt::String::Format("Extreme's Tracker %d.%d", fileHeader.versionHigh, fileHeader.versionLow); std::vector<bool> packSample(fileHeader.numSamps); @@ -532,7 +532,8 @@ linearSlides = 0x40, }; - uint16 format; // Version of format (Hi = MainVer, Low = SubVer e.g. 0202 = 2.2) + uint8 versionLow; // Version of format (Hi = MainVer, Low = SubVer e.g. 0202 = 2.2) + uint8 versionHigh; // ditto uint8 numIns; // Nr of Instruments (0-255) uint16 numPats; // Nr of Patterns (1-1024) uint16 numOrds; // Nr of Positions (1-65535) @@ -541,7 +542,6 @@ // Convert all multi-byte numeric values to current platform's endianness or vice versa. void ConvertEndianness() { - SwapBytesLE(format); SwapBytesLE(numPats); SwapBytesLE(numOrds); }; @@ -758,7 +758,8 @@ AMS2FileHeader fileHeader; if(!file.ReadMagic("AMShdr\x1A") || !ReadAMSString(songName, file) - || !file.ReadConvertEndianness(fileHeader)) + || !file.ReadConvertEndianness(fileHeader) + || fileHeader.versionHigh != 2 || fileHeader.versionLow > 2) { return false; } else if(loadFlags == onlyVerifyHeader) @@ -766,32 +767,30 @@ return true; } + InitializeGlobals(); + + m_nType = MOD_TYPE_AMS2; + m_nInstruments = fileHeader.numIns; + m_nChannels = 32; + SetModFlag(MSF_COMPATIBLE_PLAY, true); + SetupMODPanning(true); + madeWithTracker = mpt::String::Format("Velvet Studio %d.%02d", fileHeader.versionHigh, fileHeader.versionLow); + uint16 headerFlags; - if(fileHeader.format == 0x202) + if(fileHeader.versionLow >= 2) { m_nDefaultTempo = std::max(uint8(32), static_cast<uint8>(file.ReadUint16LE() >> 8)); // 16.16 Tempo m_nDefaultSpeed = std::max(uint8(1), file.ReadUint8()); file.Skip(3); // Default values for pattern editor headerFlags = file.ReadUint16LE(); - } else if(fileHeader.format == 0x201) + } else { m_nDefaultTempo = std::max(uint8(32), file.ReadUint8()); m_nDefaultSpeed = std::max(uint8(1), file.ReadUint8()); headerFlags = file.ReadUint8(); - } else - { - return false; } - InitializeGlobals(); - - m_nType = MOD_TYPE_AMS2; m_SongFlags = SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS | ((headerFlags & AMS2FileHeader::linearSlides) ? SONG_LINEARSLIDES : SongFlags(0)); - m_nInstruments = fileHeader.numIns; - m_nChannels = 32; - SetModFlag(MSF_COMPATIBLE_PLAY, true); - SetupMODPanning(true); - madeWithTracker = mpt::String::Format("Velvet Studio %d.%02x", fileHeader.format & 0x0F, fileHeader.format >> 4); // Instruments std::vector<SAMPLEINDEX> firstSample; // First sample of instrument @@ -816,9 +815,11 @@ uint8 numSamples = file.ReadUint8(); uint8 sampleAssignment[120]; + MemsetZero(sampleAssignment); // Only really needed for v2.0, where the lowest and highest octave aren't cleared. if(numSamples == 0 - || !file.ReadArray(sampleAssignment)) + || (fileHeader.versionLow > 0 && !file.ReadArray(sampleAssignment)) // v2.01+: 120 Notes + || (fileHeader.versionLow == 0 && !file.ReadArray(reinterpret_cast<uint8 (&) [96]>(sampleAssignment[12])))) // v2.0: 96 Notes { continue; } @@ -836,8 +837,8 @@ AMS2Instrument instrHeader; file.ReadConvertEndianness(instrHeader); - instrument->nFadeOut = (instrHeader.vibampFadeout & AMS2Instrument::fadeOutMask) * 2; - const uint8 vibAmp = 1 + ((instrHeader.vibampFadeout & AMS2Instrument::vibAmpMask) >> AMS2Instrument::vibAmpShift); // "Close enough" + instrument->nFadeOut = (instrHeader.vibampFadeout & AMS2Instrument::fadeOutMask); + const int16 vibAmp = 1 << ((instrHeader.vibampFadeout & AMS2Instrument::vibAmpMask) >> AMS2Instrument::vibAmpShift); instrHeader.ApplyFlags(instrument->VolEnv, AMS2Instrument::volEnvShift); instrHeader.ApplyFlags(instrument->PanEnv, AMS2Instrument::panEnvShift); @@ -848,7 +849,12 @@ { instrument->VolEnv.Values[i] = std::min(uint8(ENVELOPE_MAX), static_cast<uint8>((instrument->VolEnv.Values[i] * ENVELOPE_MAX + 64u) / 127u)); instrument->PanEnv.Values[i] = std::min(uint8(ENVELOPE_MAX), static_cast<uint8>((instrument->PanEnv.Values[i] * ENVELOPE_MAX + 128u) / 255u)); - instrument->PitchEnv.Values[i] = std::min(uint8(ENVELOPE_MAX), static_cast<uint8>(32 + (static_cast<int8>(instrument->PitchEnv.Values[i] - 128) * vibAmp) / 255)); +#ifdef MODPLUG_TRACKER + instrument->PitchEnv.Values[i] = std::min(uint8(ENVELOPE_MAX), static_cast<uint8>(32 + Util::muldivrfloor(static_cast<int8>(instrument->PitchEnv.Values[i] - 128), vibAmp, 255))); +#else + // Try to keep as much precision as possible... divide by 8 since that's the highest possible vibAmp factor. + instrument->PitchEnv.Values[i] = static_cast<uint8>(128 + Util::muldivrfloor(static_cast<int8>(instrument->PitchEnv.Values[i] - 128), vibAmp, 8)); +#endif } // Sample headers - we will have to read them even for shadow samples, and we will have to load them several times, @@ -867,7 +873,9 @@ file.ReadConvertEndianness(sampleHeader); sampleHeader.ConvertToMPT(Samples[firstSmp + smp]); - uint16 settings = (instrHeader.shadowInstr & instrIndexMask) | ((smp << sampleIndexShift) & sampleIndexMask) | ((sampleHeader.flags & AMS2SampleHeader::smpPacked) ? packStatusMask : 0); + uint16 settings = (instrHeader.shadowInstr & instrIndexMask) + | ((smp << sampleIndexShift) & sampleIndexMask) + | ((sampleHeader.flags & AMS2SampleHeader::smpPacked) ? packStatusMask : 0); sampleSettings.push_back(settings); } Modified: trunk/OpenMPT/soundlib/ModInstrument.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModInstrument.cpp 2013-10-21 11:03:05 UTC (rev 2957) +++ trunk/OpenMPT/soundlib/ModInstrument.cpp 2013-10-21 12:53:54 UTC (rev 2958) @@ -74,8 +74,8 @@ // Get envelope value at a given tick. Returns value in range [0.0, 1.0]. -float InstrumentEnvelope::GetValueFromPosition(int position) const -//---------------------------------------------------------------- +float InstrumentEnvelope::GetValueFromPosition(int position, int range) const +//--------------------------------------------------------------------------- { uint32 pt = nNodes - 1u; @@ -95,7 +95,7 @@ if(position >= x2) { // Case: current 'tick' is on a envelope point. - value = static_cast<float>(Values[pt]) / 64.0f; + value = static_cast<float>(Values[pt]) / float(range); } else { // Case: current 'tick' is between two envelope points. @@ -104,7 +104,7 @@ if(pt) { // Get previous node's value and tick. - value = static_cast<float>(Values[pt - 1]) / 64.0f; + value = static_cast<float>(Values[pt - 1]) / float(range); x1 = Ticks[pt - 1]; } @@ -112,7 +112,7 @@ { // 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); + value += ((position - x1) * (static_cast<float>(Values[pt]) / float(range) - value)) / (x2 - x1); } } Modified: trunk/OpenMPT/soundlib/ModInstrument.h =================================================================== --- trunk/OpenMPT/soundlib/ModInstrument.h 2013-10-21 11:03:05 UTC (rev 2957) +++ trunk/OpenMPT/soundlib/ModInstrument.h 2013-10-21 12:53:54 UTC (rev 2958) @@ -42,7 +42,7 @@ 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; + float GetValueFromPosition(int position, int range = ENVELOPE_MAX) const; }; Modified: trunk/OpenMPT/soundlib/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2013-10-21 11:03:05 UTC (rev 2957) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2013-10-21 12:53:54 UTC (rev 2958) @@ -850,7 +850,14 @@ 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); +#ifdef MODPLUG_TRACKER + const int range = ENVELOPE_MAX; + const float amp = 512.0f; +#else + const int range = GetType() == MOD_TYPE_AMS2 ? uint8_max : ENVELOPE_MAX; + const int amp = GetType() == MOD_TYPE_AMS2 ? 64.0f : 512.0f; +#endif + const int envval = Util::Round<int>((pIns->PitchEnv.GetValueFromPosition(envpos, range) - 0.5f) * amp); if(pChn->PitchEnv.flags[ENV_FILTER]) { @@ -1176,7 +1183,8 @@ } } - if (note > 108 + NOTE_MIN && arpPos != 0) + // Test case: ArpeggioClamp.xm + if(note > 108 + NOTE_MIN && arpPos != 0) note = 108 + NOTE_MIN; // FT2's note limit period = GetPeriodFromNote(note, pChn->nFineTune, pChn->nC5Speed); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |