From 894aada3d255c5777e8b4e65c8a1c2ee4bdb0186 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Tue, 11 Oct 2022 22:47:02 -0700 Subject: [PATCH] Updated libOpenMPT to version 0.6.6 Signed-off-by: Christopher Snowhill --- Frameworks/OpenMPT/OpenMPT/build/dist.mk | 6 +- .../OpenMPT/build/make/config-emscripten.mk | 10 +++ .../OpenMPT/build/svn_version/svn_version.h | 8 +- .../OpenMPT/OpenMPT/common/versionNumber.h | 2 +- .../OpenMPT/libopenmpt/dox/changelog.md | 16 ++++ .../OpenMPT/libopenmpt/libopenmpt_version.h | 2 +- .../OpenMPT/libopenmpt/libopenmpt_version.mk | 4 +- .../OpenMPT/OpenMPT/soundlib/Dlsbank.cpp | 1 + .../OpenMPT/OpenMPT/soundlib/Load_mtm.cpp | 89 ++++++++++++++++--- .../OpenMPT/soundlib/SampleFormatMP3.cpp | 38 ++++++-- .../OpenMPT/soundlib/SampleFormatSFZ.cpp | 2 +- .../OpenMPT/OpenMPT/soundlib/Snd_fx.cpp | 46 +++++----- .../OpenMPT/OpenMPT/soundlib/Sndmix.cpp | 2 +- .../OpenMPT/soundlib/UpgradeModule.cpp | 21 ++++- .../soundlib/plugins/PlugInterface.cpp | 2 +- .../OpenMPT/soundlib/plugins/dmo/Echo.cpp | 4 +- .../OpenMPT/src/mpt/base/detect_os.hpp | 3 + 17 files changed, 199 insertions(+), 57 deletions(-) diff --git a/Frameworks/OpenMPT/OpenMPT/build/dist.mk b/Frameworks/OpenMPT/OpenMPT/build/dist.mk index 90c4d0d7c..daf08768f 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/dist.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/dist.mk @@ -1,4 +1,4 @@ -MPT_SVNVERSION=17761 -MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.5 -MPT_SVNDATE=2022-08-21T11:52:57.985463Z +MPT_SVNVERSION=17954 +MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.6 +MPT_SVNDATE=2022-09-25T14:18:19.447172Z diff --git a/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk b/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk index 164750b15..02ee0d916 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk @@ -80,6 +80,11 @@ CXXFLAGS += CFLAGS += LDFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1 -Wno-transpile +# work-around . +CXXFLAGS += -fno-inline-functions +CFLAGS += -fno-inline-functions +LDFLAGS += -fno-inline-functions + LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 else ifeq ($(EMSCRIPTEN_TARGET),audioworkletprocessor) @@ -107,6 +112,11 @@ CXXFLAGS += CFLAGS += LDFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1 -Wno-transpile +# work-around . +CXXFLAGS += -fno-inline-functions +CFLAGS += -fno-inline-functions +LDFLAGS += -fno-inline-functions + LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 endif diff --git a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h index b23941a08..10e537b55 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h +++ b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h @@ -1,10 +1,10 @@ #pragma once -#define OPENMPT_VERSION_SVNVERSION "17761" -#define OPENMPT_VERSION_REVISION 17761 +#define OPENMPT_VERSION_SVNVERSION "17954" +#define OPENMPT_VERSION_REVISION 17954 #define OPENMPT_VERSION_DIRTY 0 #define OPENMPT_VERSION_MIXEDREVISIONS 0 -#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.5" -#define OPENMPT_VERSION_DATE "2022-08-21T11:52:57.985463Z" +#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.6" +#define OPENMPT_VERSION_DATE "2022-09-25T14:18:19.447172Z" #define OPENMPT_VERSION_IS_PACKAGE 1 diff --git a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h index 9977ea22c..ff9c08286 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h +++ b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h @@ -17,7 +17,7 @@ OPENMPT_NAMESPACE_BEGIN // Version definitions. The only thing that needs to be changed when changing version number. #define VER_MAJORMAJOR 1 #define VER_MAJOR 30 -#define VER_MINOR 06 +#define VER_MINOR 07 #define VER_MINORMINOR 00 OPENMPT_NAMESPACE_END diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md index 033999b35..4973dda6a 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md @@ -5,6 +5,22 @@ Changelog {#changelog} For fully detailed change log, please see the source repository directly. This is just a high-level summary. +### libopenmpt 0.6.6 (2022-09-25) + + * [**Sec**] Possible crash when playing manipulated IT / MPTM files with a T00 + command. (r17789) + + * MTM: In MultiTracker, setting speed and tempo are mutually exclusive + commands. Still, some MultiTracker modules were made to be played with + external players such as DMP, so they actually rely on "standard" speed / + tempo behaviour. Decide which behaviour to use by checking of speed and + tempo commands are found on the same row. + * MTM: Ignore sample loops if the loop end is <= 2. + * Echo DMO: Migrate left and right delay values in modules made with OpenMPT + versions between 1.27.01.00 and 1.30.05.00 to the correct interpretation. + + * FLAC: Update to v1.4.1 (2022-09-22). + ### libopenmpt 0.6.5 (2022-08-21) * [**Bug**] `Makefile` now also uses `CC`, `CXX`, `LD`, and `AR` when set as diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h index b3342e46d..383df5913 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h @@ -21,7 +21,7 @@ /*! \brief libopenmpt minor version number */ #define OPENMPT_API_VERSION_MINOR 6 /*! \brief libopenmpt patch version number */ -#define OPENMPT_API_VERSION_PATCH 5 +#define OPENMPT_API_VERSION_PATCH 6 /*! \brief libopenmpt pre-release tag */ #define OPENMPT_API_VERSION_PREREL "" /*! \brief libopenmpt pre-release flag */ diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk index 184e5400c..ab021b538 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk @@ -1,8 +1,8 @@ LIBOPENMPT_VERSION_MAJOR=0 LIBOPENMPT_VERSION_MINOR=6 -LIBOPENMPT_VERSION_PATCH=5 +LIBOPENMPT_VERSION_PATCH=6 LIBOPENMPT_VERSION_PREREL= LIBOPENMPT_LTVER_CURRENT=3 -LIBOPENMPT_LTVER_REVISION=5 +LIBOPENMPT_LTVER_REVISION=6 LIBOPENMPT_LTVER_AGE=3 diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp index f90b7b732..e5d7e52da 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp @@ -646,6 +646,7 @@ bool CDLSBank::FindAndExtract(CSoundFile &sndFile, const INSTRUMENTINDEX ins, co const uint32 program = (pIns->nMidiProgram != 0) ? pIns->nMidiProgram - 1 : 0; const uint32 key = isDrum ? (pIns->nMidiDrumKey & 0x7F) : 0xFF; if(FindInstrument(isDrum, (pIns->wMidiBank - 1) & 0x3FFF, program, key, &dlsIns) + || FindInstrument(isDrum, (pIns->wMidiBank - 1) & 0x3F80, program, key, &dlsIns) || FindInstrument(isDrum, 0xFFFF, isDrum ? 0xFF : program, key, &dlsIns)) { if(key < 0x80) drumRgn = GetRegionFromKey(dlsIns, key); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mtm.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mtm.cpp index 0740d85e6..dffadb9ba 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mtm.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mtm.cpp @@ -17,18 +17,18 @@ OPENMPT_NAMESPACE_BEGIN // File Header struct MTMFileHeader { - char id[3]; // MTM file marker - uint8le version; // Tracker version - char songName[20]; // ASCIIZ songname - uint16le numTracks; // Number of tracks saved - uint8le lastPattern; // Last pattern number saved - uint8le lastOrder; // Last order number to play (songlength-1) - uint16le commentSize; // Length of comment field - uint8le numSamples; // Number of samples saved - uint8le attribute; // Attribute byte (unused) - uint8le beatsPerTrack; // Numbers of rows in every pattern (MultiTracker itself does not seem to support values != 64) - uint8le numChannels; // Number of channels used - uint8le panPos[32]; // Channel pan positions + char id[3]; // MTM file marker + uint8le version; // Tracker version + char songName[20]; // ASCIIZ songname + uint16le numTracks; // Number of tracks saved + uint8le lastPattern; // Last pattern number saved + uint8le lastOrder; // Last order number to play (songlength-1) + uint16le commentSize; // Length of comment field + uint8le numSamples; // Number of samples saved + uint8le attribute; // Attribute byte (unused) + uint8le beatsPerTrack; // Numbers of rows in every pattern (MultiTracker itself does not seem to support values != 64) + uint8le numChannels; // Number of channels used + uint8le panPos[32]; // Channel pan positions }; MPT_BINARY_STRUCT(MTMFileHeader, 66) @@ -56,8 +56,10 @@ struct MTMSampleHeader mptSmp.nLoopStart = loopStart; mptSmp.nLoopEnd = std::max(loopEnd.get(), uint32(1)) - 1; LimitMax(mptSmp.nLoopEnd, mptSmp.nLength); - if(mptSmp.nLoopStart + 4 >= mptSmp.nLoopEnd) mptSmp.nLoopStart = mptSmp.nLoopEnd = 0; - if(mptSmp.nLoopEnd) mptSmp.uFlags.set(CHN_LOOP); + if(mptSmp.nLoopStart + 4 >= mptSmp.nLoopEnd) + mptSmp.nLoopStart = mptSmp.nLoopEnd = 0; + if(mptSmp.nLoopEnd > 2) + mptSmp.uFlags.set(CHN_LOOP); mptSmp.nFineTune = finetune; // Uses MOD units but allows the full int8 range rather than just -8...+7 so we keep the value as-is and convert it during playback mptSmp.nC5Speed = ModSample::TransposeToFrequency(0, finetune * 16); @@ -170,6 +172,8 @@ bool CSoundFile::ReadMTM(FileReader &file, ModLoadingFlags loadFlags) if(loadFlags & loadPatternData) Patterns.ResizeArray(fileHeader.lastPattern + 1); + + bool hasSpeed = false, hasTempo = false; for(PATTERNINDEX pat = 0; pat <= fileHeader.lastPattern; pat++) { if(!(loadFlags & loadPatternData) || !Patterns.Insert(pat, rowsPerPat)) @@ -228,6 +232,63 @@ bool CSoundFile::ReadMTM(FileReader &file, ModLoadingFlags loadFlags) #ifdef MODPLUG_TRACKER m->Convert(MOD_TYPE_MTM, MOD_TYPE_S3M, *this); #endif + if(m->command == CMD_SPEED) + hasSpeed = true; + else if(m->command == CMD_TEMPO) + hasTempo = true; + } + } + } + } + + // Curiously, speed commands reset the tempo to 125 in MultiTracker, and tempo commands reset the speed to 6. + // External players of the time (e.g. DMP) did not implement this quirk and assumed a more ProTracker-like interpretation of speed and tempo. + // Quite a few musicians created MTMs that make use DMP's speed and tempo interpretation, which in return means that they will play too + // fast or too slow in MultiTracker. On the other hand there are also a few MTMs that break when using ProTracker-like speed and tempo. + // As a way to support as many modules of both types as possible, we will assume a ProTracker-like interpretation if both speed and tempo + // commands are found on the same line, and a MultiTracker-like interpretation when they are never found on the same line. + if(hasSpeed && hasTempo) + { + bool hasSpeedAndTempoOnSameRow = false; + for(const auto &pattern : Patterns) + { + for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++) + { + const auto rowBase = pattern.GetRow(row); + bool hasSpeedOnRow = false, hasTempoOnRow = false; + for(CHANNELINDEX chn = 0; chn < GetNumChannels(); chn++) + { + if(rowBase[chn].command == CMD_SPEED) + hasSpeedOnRow = true; + else if(rowBase[chn].command == CMD_TEMPO) + hasTempoOnRow = true; + } + if(hasSpeedOnRow && hasTempoOnRow) + { + hasSpeedAndTempoOnSameRow = true; + break; + } + } + if(hasSpeedAndTempoOnSameRow) + break; + } + + if(!hasSpeedAndTempoOnSameRow) + { + for(auto &pattern : Patterns) + { + for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++) + { + const auto rowBase = pattern.GetRow(row); + for(CHANNELINDEX chn = 0; chn < GetNumChannels(); chn++) + { + if(rowBase[chn].command == CMD_SPEED || rowBase[chn].command == CMD_TEMPO) + { + const bool writeTempo = rowBase[chn].command == CMD_SPEED; + pattern.WriteEffect(EffectWriter(writeTempo ? CMD_TEMPO : CMD_SPEED, writeTempo ? 125 : 6).Row(row)); + break; + } + } } } } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMP3.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMP3.cpp index a038e1349..a290a1eae 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMP3.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMP3.cpp @@ -24,6 +24,10 @@ #ifdef MPT_ENABLE_MP3_SAMPLES #include "MPEGFrame.h" #endif // MPT_ENABLE_MP3_SAMPLES +#if defined(MPT_WITH_MINIMP3) +#include "mpt/base/alloc.hpp" +#endif // MPT_WITH_MINIMP3 + #if defined(MPT_WITH_MINIMP3) #include #endif // MPT_WITH_MINIMP3 @@ -163,6 +167,28 @@ static mpt::ustring ReadMPG123String(const char (&str)[N]) #endif // MPT_WITH_MPG123 +#if defined(MPT_WITH_MINIMP3) +#if MPT_COMPILER_GCC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wframe-larger-than=16000" +#endif // MPT_COMPILER_GCC +#if MPT_CLANG_AT_LEAST(13,0,0) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wframe-larger-than" +#endif // MPT_COMPILER_CLANG +static MPT_NOINLINE int mp3dec_decode_frame_no_inline(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info) +{ + return mp3dec_decode_frame(dec, mp3, mp3_bytes, pcm, info); +} +#if MPT_CLANG_AT_LEAST(13,0,0) +#pragma clang diagnostic pop +#endif // MPT_COMPILER_CLANG +#if MPT_COMPILER_GCC +#pragma GCC diagnostic pop +#endif // MPT_COMPILER_GCC +#endif // MPT_WITH_MINIMP3 + + bool CSoundFile::ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw, bool mo3Decode) { #if defined(MPT_WITH_MPG123) || defined(MPT_WITH_MINIMP3) @@ -603,19 +629,19 @@ bool CSoundFile::ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw, b std::vector raw_sample_data; - mp3dec_t mp3; - std::memset(&mp3, 0, sizeof(mp3dec_t)); - mp3dec_init(&mp3); + mpt::heap_value mp3; + std::memset(&*mp3, 0, sizeof(mp3dec_t)); + mp3dec_init(&*mp3); int rate = 0; int channels = 0; mp3dec_frame_info_t info; std::memset(&info, 0, sizeof(mp3dec_frame_info_t)); + std::vector sample_buf(MINIMP3_MAX_SAMPLES_PER_FRAME); do { - int16 sample_buf[MINIMP3_MAX_SAMPLES_PER_FRAME]; - int frame_samples = mp3dec_decode_frame(&mp3, stream_pos, mpt::saturate_cast(bytes_left), sample_buf, &info); + int frame_samples = mp3dec_decode_frame_no_inline(&*mp3, stream_pos, mpt::saturate_cast(bytes_left), sample_buf.data(), &info); if(frame_samples < 0 || info.frame_bytes < 0) break; // internal error in minimp3 if(frame_samples > 0 && info.frame_bytes == 0) break; // internal error in minimp3 if(frame_samples == 0 && info.frame_bytes == 0) break; // end of stream, no progress @@ -635,7 +661,7 @@ bool CSoundFile::ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw, b { try { - mpt::append(raw_sample_data, sample_buf, sample_buf + frame_samples * channels); + mpt::append(raw_sample_data, sample_buf.data(), sample_buf.data() + frame_samples * channels); } catch(mpt::out_of_memory e) { mpt::delete_out_of_memory(e); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatSFZ.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatSFZ.cpp index 18d1247e8..a59b1931f 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatSFZ.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatSFZ.cpp @@ -913,13 +913,13 @@ bool CSoundFile::ReadSFZInstrument(INSTRUMENTINDEX nInstr, FileReader &file) switch(region.loopMode) { case SFZRegion::LoopMode::kContinuous: - case SFZRegion::LoopMode::kOneShot: sample.uFlags.set(CHN_LOOP); break; case SFZRegion::LoopMode::kSustain: sample.uFlags.set(CHN_SUSTAINLOOP); break; case SFZRegion::LoopMode::kNoLoop: + case SFZRegion::LoopMode::kOneShot: sample.uFlags.reset(CHN_LOOP | CHN_SUSTAINLOOP); } } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp index da45cf11d..0b311f654 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp @@ -2232,8 +2232,12 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo case DuplicateNoteAction::NoteOff: case DuplicateNoteAction::NoteFade: // Switch off duplicated note played on this plugin - SendMIDINote(i, chn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]) + NOTE_MAX_SPECIAL, 0); - chn.nArpeggioLastNote = NOTE_NONE; + if(const auto oldNote = chn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]); oldNote != NOTE_NONE) + { + SendMIDINote(i, oldNote + NOTE_MAX_SPECIAL, 0); + chn.nArpeggioLastNote = NOTE_NONE; + chn.nNote = NOTE_NONE; + } break; } } @@ -2285,7 +2289,8 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo { // apply NNA to this plugin iff it is currently playing a note on this tracker channel // (and if it is playing a note, we know that would be the last note played on this chan). - applyNNAtoPlug = pPlugin->IsNotePlaying(srcChn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]), nChn); + const auto oldNote = srcChn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]); + applyNNAtoPlug = (oldNote != NOTE_NONE) && pPlugin->IsNotePlaying(oldNote, nChn); } } } @@ -2295,6 +2300,24 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo if(!srcChn.IsSamplePlaying() && !applyNNAtoPlug) return CHANNELINDEX_INVALID; +#ifndef NO_PLUGINS + if(applyNNAtoPlug && pPlugin) + { + switch(srcChn.nNNA) + { + case NewNoteAction::NoteOff: + case NewNoteAction::NoteCut: + case NewNoteAction::NoteFade: + // Switch off note played on this plugin, on this tracker channel and midi channel + SendMIDINote(nChn, NOTE_KEYOFF, 0); + srcChn.nArpeggioLastNote = NOTE_NONE; + break; + case NewNoteAction::Continue: + break; + } + } +#endif // NO_PLUGINS + CHANNELINDEX nnaChn = GetNNAChannel(nChn); if(nnaChn == CHANNELINDEX_INVALID) return CHANNELINDEX_INVALID; @@ -2309,23 +2332,6 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo chn.nMasterChn = nChn < GetNumChannels() ? nChn + 1 : 0; chn.nCommand = CMD_NONE; -#ifndef NO_PLUGINS - if(applyNNAtoPlug && pPlugin) - { - switch(srcChn.nNNA) - { - case NewNoteAction::NoteOff: - case NewNoteAction::NoteCut: - case NewNoteAction::NoteFade: - // Switch off note played on this plugin, on this tracker channel and midi channel - SendMIDINote(nChn, NOTE_KEYOFF, 0); - srcChn.nArpeggioLastNote = NOTE_NONE; - break; - case NewNoteAction::Continue: - break; - } - } -#endif // NO_PLUGINS // Key Off the note switch(srcChn.nNNA) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp index 30d49faca..f66586e42 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp @@ -696,7 +696,7 @@ bool CSoundFile::ProcessRow() { // ProTracker sets the tempo after the first tick. This block handles the case of one tick per row. // Test case: TempoChange.mod - m_PlayState.m_nMusicTempo = TEMPO(pChn->rowCommand.param, 0); + m_PlayState.m_nMusicTempo = TEMPO(std::max(ModCommand::PARAM(1), pChn->rowCommand.param), 0); } pChn->rowCommand = *m; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp index 1cb2ffe7b..4a548f95e 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp @@ -1,7 +1,8 @@ /* * UpdateModule.cpp * ---------------- - * Purpose: CSoundFile functions for correcting modules made with previous versions of OpenMPT. + * Purpose: Compensate for playback bugs of previous OpenMPT versions during import + * by rewriting patterns / samples / instruments or enabling / disabling specific compatibility flags * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. @@ -726,6 +727,24 @@ void CSoundFile::UpgradeModule() plugin.Info.szLibraryName = "Flanger (Legacy)"; } } + + if(m_dwLastSavedWithVersion >= MPT_V("1.27") && m_dwLastSavedWithVersion < MPT_V("1.30.06.00") && (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT | MOD_TYPE_XM))) + { + // Fix off-by-one delay length in older Echo DMO emulation + for(auto &plugin : m_MixPlugins) + { + if(plugin.Info.dwPluginId1 == kDmoMagic && plugin.Info.dwPluginId2 == int32(0xEF3E932C) && plugin.pluginData.size() == 24) + { + float32le leftDelay, rightDelay; + memcpy(&leftDelay, plugin.pluginData.data() + 12, 4); + memcpy(&rightDelay, plugin.pluginData.data() + 16, 4); + leftDelay = float32le{mpt::safe_clamp(((leftDelay * 2000.0f) - 1.0f) / 1999.0f, 0.0f, 1.0f)}; + rightDelay = float32le{mpt::safe_clamp(((rightDelay * 2000.0f) - 1.0f) / 1999.0f, 0.0f, 1.0f)}; + memcpy(plugin.pluginData.data() + 12, &leftDelay, 4); + memcpy(plugin.pluginData.data() + 16, &rightDelay, 4); + } + } + } } OPENMPT_NAMESPACE_END diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp index d0e8534ff..7e524c7a3 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp @@ -884,7 +884,7 @@ void IMidiPlugin::MidiCommand(const ModInstrument &instr, uint16 note, uint16 vo bool bankChanged = (channel.currentBank != midiBank) && (midiBank < 0x4000); bool progChanged = (channel.currentProgram != midiProg) && (midiProg < 0x80); //get vol in [0,128[ - uint8 volume = static_cast(std::min(vol / 2u, 127u)); + uint8 volume = static_cast(std::min((vol + 1u) / 2u, 127u)); // Bank change if(bankChanged) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/dmo/Echo.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/dmo/Echo.cpp index 3037418bf..98251ccaf 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/dmo/Echo.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/dmo/Echo.cpp @@ -37,8 +37,8 @@ Echo::Echo(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct) { m_param[kEchoWetDry] = 0.5f; m_param[kEchoFeedback] = 0.5f; - m_param[kEchoLeftDelay] = 0.25f; - m_param[kEchoRightDelay] = 0.25f; + m_param[kEchoLeftDelay] = (500.0f - 1.0f) / 1999.0f; + m_param[kEchoRightDelay] = (500.0f - 1.0f) / 1999.0f; m_param[kEchoPanDelay] = 0.0f; m_mixBuffer.Initialize(2, 2); diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_os.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_os.hpp index 8daa740e6..507cce88d 100644 --- a/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_os.hpp +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_os.hpp @@ -10,6 +10,9 @@ #define MPT_OS_DJGPP 1 #elif defined(__EMSCRIPTEN__) #define MPT_OS_EMSCRIPTEN 1 +#if !defined(__EMSCRIPTEN_major__) || !defined(__EMSCRIPTEN_minor__) || !defined(__EMSCRIPTEN_tiny__) +#include +#endif #if defined(__EMSCRIPTEN_major__) && defined(__EMSCRIPTEN_minor__) #if (__EMSCRIPTEN_major__ > 1) // ok