summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/mptAlloc.cpp4
-rw-r--r--common/mptAlloc.h2
-rw-r--r--common/versionNumber.h4
-rwxr-xr-xconfigure26
-rw-r--r--configure.ac8
-rw-r--r--debian/changelog6
-rw-r--r--libopenmpt/dox/changelog.md14
-rw-r--r--libopenmpt/libopenmpt_version.h2
-rw-r--r--libopenmpt/libopenmpt_version.mk4
-rw-r--r--man/openmpt123.12
-rw-r--r--soundlib/Fastmix.cpp2
-rw-r--r--soundlib/Load_it.cpp22
-rw-r--r--soundlib/Load_mo3.cpp19
-rw-r--r--soundlib/Snd_defs.h1
-rw-r--r--soundlib/Snd_fx.cpp34
-rw-r--r--soundlib/Sndfile.cpp1
-rw-r--r--soundlib/Sndmix.cpp2
-rw-r--r--soundlib/UpgradeModule.cpp163
18 files changed, 187 insertions, 129 deletions
diff --git a/common/mptAlloc.cpp b/common/mptAlloc.cpp
index 431887f..2f072ae 100644
--- a/common/mptAlloc.cpp
+++ b/common/mptAlloc.cpp
@@ -56,7 +56,7 @@ void* align(std::size_t alignment, std::size_t size, void* &ptr, std::size_t &sp
aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::size_t alignment)
{
- #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !MPT_OS_EMSCRIPTEN
+ #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) && !MPT_OS_EMSCRIPTEN
std::size_t space = count * size;
void* mem = std::aligned_alloc(alignment, space);
if(!mem)
@@ -103,7 +103,7 @@ aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::
void aligned_free(aligned_raw_memory raw)
{
- #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !MPT_OS_EMSCRIPTEN
+ #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) && !MPT_OS_EMSCRIPTEN
std::free(raw.mem);
#elif MPT_COMPILER_MSVC
_aligned_free(raw.mem);
diff --git a/common/mptAlloc.h b/common/mptAlloc.h
index 1d616b4..f881be9 100644
--- a/common/mptAlloc.h
+++ b/common/mptAlloc.h
@@ -100,7 +100,7 @@ namespace mpt
-#if MPT_CXX_AT_LEAST(17) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__))
+#if MPT_CXX_AT_LEAST(17) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS)
using std::launder;
#else
template <class T>
diff --git a/common/versionNumber.h b/common/versionNumber.h
index 7c63c40..64d7080 100644
--- a/common/versionNumber.h
+++ b/common/versionNumber.h
@@ -20,8 +20,8 @@ OPENMPT_NAMESPACE_BEGIN
//Version definitions. The only thing that needs to be changed when changing version number.
#define VER_MAJORMAJOR 1
#define VER_MAJOR 28
-#define VER_MINOR 02
-#define VER_MINORMINOR 04
+#define VER_MINOR 03
+#define VER_MINORMINOR 00
//Numerical value of the version.
#define MPT_VERSION_CURRENT MAKE_VERSION_NUMERIC(VER_MAJORMAJOR,VER_MAJOR,VER_MINOR,VER_MINORMINOR)
diff --git a/configure b/configure
index 788cb4c..3b1ceda 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libopenmpt 0.4.2+release.autotools.
+# Generated by GNU Autoconf 2.69 for libopenmpt 0.4.3+release.autotools.
#
# Report bugs to <https://bugs.openmpt.org/>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libopenmpt'
PACKAGE_TARNAME='libopenmpt'
-PACKAGE_VERSION='0.4.2+release.autotools'
-PACKAGE_STRING='libopenmpt 0.4.2+release.autotools'
+PACKAGE_VERSION='0.4.3+release.autotools'
+PACKAGE_STRING='libopenmpt 0.4.3+release.autotools'
PACKAGE_BUGREPORT='https://bugs.openmpt.org/'
PACKAGE_URL='https://lib.openmpt.org/'
@@ -1485,7 +1485,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures libopenmpt 0.4.2+release.autotools to adapt to many kinds of systems.
+\`configure' configures libopenmpt 0.4.3+release.autotools to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1556,7 +1556,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of libopenmpt 0.4.2+release.autotools:";;
+ short | recursive ) echo "Configuration of libopenmpt 0.4.3+release.autotools:";;
esac
cat <<\_ACEOF
@@ -1756,7 +1756,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-libopenmpt configure 0.4.2+release.autotools
+libopenmpt configure 0.4.3+release.autotools
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2246,7 +2246,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by libopenmpt $as_me 0.4.2+release.autotools, which was
+It was created by libopenmpt $as_me 0.4.3+release.autotools, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3117,7 +3117,7 @@ fi
# Define the identity of the package.
PACKAGE='libopenmpt'
- VERSION='0.4.2+release.autotools'
+ VERSION='0.4.3+release.autotools'
cat >>confdefs.h <<_ACEOF
@@ -17281,13 +17281,13 @@ LIBOPENMPT_LTVER_AGE=1
-$as_echo "#define MPT_SVNURL \"https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.2\"" >>confdefs.h
+$as_echo "#define MPT_SVNURL \"https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.3\"" >>confdefs.h
-$as_echo "#define MPT_SVNVERSION \"11243\"" >>confdefs.h
+$as_echo "#define MPT_SVNVERSION \"11358\"" >>confdefs.h
-$as_echo "#define MPT_SVNDATE \"2019-01-22T08:59:00.771884Z\"" >>confdefs.h
+$as_echo "#define MPT_SVNDATE \"2019-02-11T05:32:52.673531Z\"" >>confdefs.h
$as_echo "#define MPT_PACKAGE true" >>confdefs.h
@@ -23527,7 +23527,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by libopenmpt $as_me 0.4.2+release.autotools, which was
+This file was extended by libopenmpt $as_me 0.4.3+release.autotools, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -23594,7 +23594,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-libopenmpt config.status 0.4.2+release.autotools
+libopenmpt config.status 0.4.3+release.autotools
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 8e83afb..e34b3db 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([libopenmpt], [0.4.2+release.autotools], [https://bugs.openmpt.org/], [libopenmpt], [https://lib.openmpt.org/])
+AC_INIT([libopenmpt], [0.4.3+release.autotools], [https://bugs.openmpt.org/], [libopenmpt], [https://lib.openmpt.org/])
AC_PREREQ([2.68])
AC_CONFIG_MACRO_DIR([m4])
@@ -27,9 +27,9 @@ AC_SUBST([LIBOPENMPT_LTVER_CURRENT])
AC_SUBST([LIBOPENMPT_LTVER_REVISION])
AC_SUBST([LIBOPENMPT_LTVER_AGE])
-AC_DEFINE([MPT_SVNURL], ["https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.2"], [svn version])
-AC_DEFINE([MPT_SVNVERSION], ["11243"], [svn version])
-AC_DEFINE([MPT_SVNDATE], ["2019-01-22T08:59:00.771884Z"], [svn date])
+AC_DEFINE([MPT_SVNURL], ["https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.3"], [svn version])
+AC_DEFINE([MPT_SVNVERSION], ["11358"], [svn version])
+AC_DEFINE([MPT_SVNDATE], ["2019-02-11T05:32:52.673531Z"], [svn date])
AC_DEFINE([MPT_PACKAGE], [true], [is package])
diff --git a/debian/changelog b/debian/changelog
index 925f1f4..c134415 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+libopenmpt (0.4.3-1) unstable; urgency=medium
+
+ * New upstream release.
+
+ -- James Cowgill <jcowgill@debian.org> Fri, 15 Feb 2019 09:30:30 +0000
+
libopenmpt (0.4.2-1) unstable; urgency=medium
* New upstream release.
diff --git a/libopenmpt/dox/changelog.md b/libopenmpt/dox/changelog.md
index 3dfb7d9..75441c0 100644
--- a/libopenmpt/dox/changelog.md
+++ b/libopenmpt/dox/changelog.md
@@ -5,6 +5,20 @@ Changelog {#changelog}
For fully detailed change log, please see the source repository directly. This
is just a high-level summary.
+### libopenmpt 0.4.3 (2019-02-11)
+
+ * [**Sec**] Possible crash due to null-pointer access when doing a portamento
+ from an OPL instrument to an empty instrument note map slot (r11348).
+
+ * [**Bug**] libopenmpt did not compile on Apple platforms in C++17 mode.
+
+ * IT: Various fixes for note-off + instrument number in Old Effects mode.
+ * MO3: Import IT row highlights as written by MO3 2.4.1.2 or newer. Required
+ for modules using modern tempo mode.
+
+ * miniz: Update to v2.0.8 (2018-09-19).
+ * stb_vorbis: Update to v1.15 (2019-02-07).
+
### libopenmpt 0.4.2 (2019-01-22)
* [**Sec**] DSM: Assertion failure during file parsing with debug STLs
diff --git a/libopenmpt/libopenmpt_version.h b/libopenmpt/libopenmpt_version.h
index ecf1f3a..a99c9b3 100644
--- a/libopenmpt/libopenmpt_version.h
+++ b/libopenmpt/libopenmpt_version.h
@@ -19,7 +19,7 @@
/*! \brief libopenmpt minor version number */
#define OPENMPT_API_VERSION_MINOR 4
/*! \brief libopenmpt patch version number */
-#define OPENMPT_API_VERSION_PATCH 2
+#define OPENMPT_API_VERSION_PATCH 3
/*! \brief libopenmpt pre-release tag */
#define OPENMPT_API_VERSION_PREREL ""
/*! \brief libopenmpt pre-release flag */
diff --git a/libopenmpt/libopenmpt_version.mk b/libopenmpt/libopenmpt_version.mk
index bcf578f..72706d4 100644
--- a/libopenmpt/libopenmpt_version.mk
+++ b/libopenmpt/libopenmpt_version.mk
@@ -1,8 +1,8 @@
LIBOPENMPT_VERSION_MAJOR=0
LIBOPENMPT_VERSION_MINOR=4
-LIBOPENMPT_VERSION_PATCH=2
+LIBOPENMPT_VERSION_PATCH=3
LIBOPENMPT_VERSION_PREREL=
LIBOPENMPT_LTVER_CURRENT=1
-LIBOPENMPT_LTVER_REVISION=2
+LIBOPENMPT_LTVER_REVISION=3
LIBOPENMPT_LTVER_AGE=1
diff --git a/man/openmpt123.1 b/man/openmpt123.1
index 6a8d696..7ba7639 100644
--- a/man/openmpt123.1
+++ b/man/openmpt123.1
@@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4.
-.TH OPENMPT123 "1" "January 2019" "openmpt123 v0.4.2" "User Commands"
+.TH OPENMPT123 "1" "February 2019" "openmpt123 v0.4.3" "User Commands"
.SH NAME
openmpt123 - command line module music player based on libopenmpt
.SH SYNOPSIS
diff --git a/soundlib/Fastmix.cpp b/soundlib/Fastmix.cpp
index 40fd9a2..1266d64 100644
--- a/soundlib/Fastmix.cpp
+++ b/soundlib/Fastmix.cpp
@@ -63,7 +63,7 @@ struct MixLoopState
// If there is no interpolation happening, there is no lookahead happening the sample read-out is exact.
if(chn.dwFlags[CHN_LOOP] && chn.resamplingMode != SRCMODE_NEAREST)
{
- const bool inSustainLoop = chn.InSustainLoop();
+ const bool inSustainLoop = chn.InSustainLoop() && chn.nLoopStart == chn.pModSample->nSustainStart && chn.nLoopEnd == chn.pModSample->nSustainEnd;
// Do not enable wraparound magic if we're previewing a custom loop!
if(inSustainLoop || chn.nLoopEnd == chn.pModSample->nLoopEnd)
diff --git a/soundlib/Load_it.cpp b/soundlib/Load_it.cpp
index 83a0225..223dc6e 100644
--- a/soundlib/Load_it.cpp
+++ b/soundlib/Load_it.cpp
@@ -1415,7 +1415,7 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c
if(!compatibilityExport)
{
- // This way, we indicate that the file will most likely contain OpenMPT hacks. Compatibility export puts 0 here.
+ // This way, we indicate that the file might contain OpenMPT hacks. Compatibility export puts 0 here.
memcpy(&itHeader.reserved, "OMPT", 4);
}
}
@@ -1428,17 +1428,17 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c
if(m_SongFlags[SONG_ITCOMPATGXX]) itHeader.flags |= ITFileHeader::itCompatGxx;
if(m_SongFlags[SONG_EXFILTERRANGE] && !compatibilityExport) itHeader.flags |= ITFileHeader::extendedFilterRange;
- itHeader.globalvol = (uint8)(m_nDefaultGlobalVolume >> 1);
- itHeader.mv = (uint8)MIN(m_nSamplePreAmp, 128u);
- itHeader.speed = (uint8)MIN(m_nDefaultSpeed, 255u);
- itHeader.tempo = (uint8)MIN(m_nDefaultTempo.GetInt(), 255u); //Limit this one to 255, we save the real one as an extension below.
+ itHeader.globalvol = static_cast<uint8>(m_nDefaultGlobalVolume / 2u);
+ itHeader.mv = static_cast<uint8>(std::min(m_nSamplePreAmp, uint32(128)));
+ itHeader.speed = mpt::saturate_cast<uint8>(m_nDefaultSpeed);
+ itHeader.tempo = mpt::saturate_cast<uint8>(m_nDefaultTempo.GetInt()); // We save the real tempo in an extension below if it exceeds 255.
itHeader.sep = 128; // pan separation
// IT doesn't have a per-instrument Pitch Wheel Depth setting, so we just store the first non-zero PWD setting in the header.
- for(INSTRUMENTINDEX ins = 1; ins < GetNumInstruments(); ins++)
+ for(INSTRUMENTINDEX ins = 1; ins <= GetNumInstruments(); ins++)
{
if(Instruments[ins] != nullptr && Instruments[ins]->midiPWD != 0)
{
- itHeader.pwd = (uint8)mpt::abs(Instruments[ins]->midiPWD);
+ itHeader.pwd = static_cast<uint8>(mpt::abs(Instruments[ins]->midiPWD));
break;
}
}
@@ -1613,7 +1613,7 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c
uint16 writeSize = 0;
uint16le patinfo[4];
patinfo[0] = 0;
- patinfo[1] = (uint16)writeRows;
+ patinfo[1] = static_cast<uint16>(writeRows);
patinfo[2] = 0;
patinfo[3] = 0;
@@ -1744,11 +1744,11 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c
if (b != chnmask[ch])
{
chnmask[ch] = b;
- buf[len++] = uint8((ch + 1) | IT_bitmask_patternChanEnabled_c);
+ buf[len++] = static_cast<uint8>((ch + 1) | IT_bitmask_patternChanEnabled_c);
buf[len++] = b;
} else
{
- buf[len++] = uint8(ch + 1);
+ buf[len++] = static_cast<uint8>(ch + 1);
}
if (b & 1) buf[len++] = note;
if (b & 2) buf[len++] = m->instr;
@@ -1790,7 +1790,7 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c
bool compress = false;
#endif // MODPLUG_TRACKER
// Old MPT, DUMB and probably other libraries will only consider the IT2.15 compression flag if the header version also indicates IT2.15.
- // MilkyTracker <= 0.90.85 will only assume IT2.15 compression with cmwt == 0x215, ignoring the delta flag completely.
+ // MilkyTracker <= 0.90.85 assumes IT2.15 compression with cmwt == 0x215, ignoring the delta flag completely.
itss.ConvertToIT(sample, GetType(), compress, itHeader.cmwt >= 0x215, GetType() == MOD_TYPE_MPT);
const bool isExternal = itss.cvt == ITSample::cvtExternalSample;
diff --git a/soundlib/Load_mo3.cpp b/soundlib/Load_mo3.cpp
index 7b849b1..5233d50 100644
--- a/soundlib/Load_mo3.cpp
+++ b/soundlib/Load_mo3.cpp
@@ -194,22 +194,29 @@ struct MO3Instrument
panEnv.ConvertToMPT(mptIns.PanEnv, 0);
pitchEnv.ConvertToMPT(mptIns.PitchEnv, 5);
mptIns.nFadeOut = fadeOut;
+
if(midiChannel >= 128)
{
// Plugin
mptIns.nMixPlug = midiChannel - 127;
} else if(midiChannel < 17 && (flags & playOnMIDI))
{
- // XM / IT with recent encoder
+ // XM, or IT with recent encoder
mptIns.nMidiChannel = midiChannel + MidiFirstChannel;
} else if(midiChannel > 0 && midiChannel < 17)
{
// IT encoded with MO3 version prior to 2.4.1 (yes, channel 0 is represented the same way as "no channel")
mptIns.nMidiChannel = midiChannel + MidiFirstChannel;
}
- mptIns.wMidiBank = midiBank;
- mptIns.nMidiProgram = midiPatch;
- mptIns.midiPWD = midiBend;
+ if(mptIns.nMidiChannel != MidiNoChannel)
+ {
+ if(mptIns.wMidiBank < 128)
+ mptIns.wMidiBank = midiBank + 1;
+ if(mptIns.nMidiProgram < 128)
+ mptIns.nMidiProgram = midiPatch + 1;
+ mptIns.midiPWD = midiBend;
+ }
+
if(type == MOD_TYPE_IT)
mptIns.nGlobalVol = std::min<uint8>(globalVol, 128) / 2u;
if(panning <= 256)
@@ -1811,6 +1818,10 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
break;
}
break;
+ case MagicLE("PRHI"):
+ m_nDefaultRowsPerBeat = chunk.ReadUint8();
+ m_nDefaultRowsPerMeasure = chunk.ReadUint8();
+ break;
case MagicLE("MIDI"):
// Full MIDI config
chunk.ReadStruct<MIDIMacroConfigData>(m_MidiCfg);
diff --git a/soundlib/Snd_defs.h b/soundlib/Snd_defs.h
index 838fee6..7522582 100644
--- a/soundlib/Snd_defs.h
+++ b/soundlib/Snd_defs.h
@@ -513,6 +513,7 @@ enum PlayBehaviour
kReleaseNodePastSustainBug, // OpenMPT 1.23.01.02 / r4009 broke release nodes past the sustain point, fixed in OpenMPT 1.28
kFT2NoteDelayWithoutInstr, // Sometime between OpenMPT 1.18.03.00 and 1.19.01.00, delayed instrument-less notes in XM started recalling the default sample volume and panning
kOPLFlexibleNoteOff, // Full control after note-off over OPL voices, ^^^ sends note cut instead of just note-off
+ kITInstrWithNoteOffOldEffects, // Instrument number with note-off recalls default volume - special cases with Old Effects enabled
// Add new play behaviours here.
diff --git a/soundlib/Snd_fx.cpp b/soundlib/Snd_fx.cpp
index 08d26fd..a2b0b87 100644
--- a/soundlib/Snd_fx.cpp
+++ b/soundlib/Snd_fx.cpp
@@ -1327,6 +1327,7 @@ void CSoundFile::InstrumentChange(ModChannel &chn, uint32 instr, bool bPorta, bo
{
const ModInstrument *pIns = instr <= GetNumInstruments() ? Instruments[instr] : nullptr;
const ModSample *pSmp = &Samples[instr];
+ const auto oldInsVol = chn.nInsVol;
ModCommand::NOTE note = chn.nNewNote;
if(note == NOTE_NONE && m_playBehaviour[kITInstrWithoutNote]) return;
@@ -1491,9 +1492,12 @@ void CSoundFile::InstrumentChange(ModChannel &chn, uint32 instr, bool bPorta, bo
if(m_playBehaviour[kITEnvelopeReset])
{
const bool insNumber = (instr != 0);
+ // IT compatibility: Note-off with instrument number + Old Effects retriggers envelopes.
+ // Test case: ResetEnvNoteOffOldFx.it
+ const bool isKeyOff = chn.dwFlags[CHN_NOTEFADE | CHN_KEYOFF] || (chn.rowCommand.note == NOTE_KEYOFF && m_playBehaviour[kITInstrWithNoteOffOldEffects]);
reset = (!chn.nLength
|| (insNumber && bPorta && m_SongFlags[SONG_ITCOMPATGXX])
- || (insNumber && !bPorta && chn.dwFlags[CHN_NOTEFADE | CHN_KEYOFF] && m_SongFlags[SONG_ITOLDEFFECTS]));
+ || (insNumber && !bPorta && isKeyOff && m_SongFlags[SONG_ITOLDEFFECTS]));
// NOTE: IT2.14 with SB/GUS/etc. output is different. We are going after IT's WAV writer here.
// For SB/GUS/etc. emulation, envelope carry should only apply when the NNA isn't set to "Note Cut".
// Test case: CarryNNA.it
@@ -1597,6 +1601,21 @@ void CSoundFile::InstrumentChange(ModChannel &chn, uint32 instr, bool bPorta, bo
chn.increment.Set(0);
}
+ // IT compatibility: Note-off with instrument number + Old Effects retriggers envelopes.
+ // If the instrument changes, keep playing the previous sample, but load the new instrument's envelopes.
+ // Test case: ResetEnvNoteOffOldFx.it
+ if(chn.rowCommand.note == NOTE_KEYOFF && m_playBehaviour[kITInstrWithNoteOffOldEffects] && m_SongFlags[SONG_ITOLDEFFECTS] && sampleChanged)
+ {
+ if(chn.pModSample)
+ {
+ chn.dwFlags |= (chn.pModSample->uFlags & CHN_SAMPLEFLAGS);
+ }
+ chn.nInsVol = oldInsVol;
+ chn.nVolume = pSmp->nVolume;
+ if(pSmp->uFlags[CHN_PANNING]) chn.nPan = pSmp->nPan;
+ return;
+ }
+
chn.pModSample = pSmp;
chn.nLength = pSmp->nLength;
chn.nLoopStart = pSmp->nLoopStart;
@@ -1622,13 +1641,11 @@ void CSoundFile::InstrumentChange(ModChannel &chn, uint32 instr, bool bPorta, bo
// Don't reset finetune changed by "set finetune" command.
// Test case: finetune.xm, finetune.mod
// But *do* change the finetune if we switch to a different sample, to fix
- // Miranda`s axe by Jamson (jam007.xm) - this file doesn't use compatible play mode,
- // so we may want to use IsCompatibleMode instead if further problems arise.
+ // Miranda`s axe by Jamson (jam007.xm).
chn.nC5Speed = pSmp->nC5Speed;
chn.nFineTune = pSmp->nFineTune;
}
-
chn.nTranspose = pSmp->RelativeTone;
// FT2 compatibility: Don't reset portamento target with new instrument numbers.
@@ -1694,6 +1711,10 @@ void CSoundFile::NoteChange(ModChannel &chn, int note, bool bPorta, bool bResetE
if(note == NOTE_KEYOFF || !(GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT)))
{
KeyOff(chn);
+ // IT compatibility: Note-off + instrument releases sample sustain but does not release envelopes or fade the instrument
+ // Test case: noteoff3.it, ResetEnvNoteOffOldFx2.it
+ if(!bPorta && m_playBehaviour[kITInstrWithNoteOffOldEffects] && m_SongFlags[SONG_ITOLDEFFECTS] && chn.rowCommand.instr)
+ chn.dwFlags.reset(CHN_NOTEFADE | CHN_KEYOFF);
} else // Invalid Note -> Note Fade
{
if(/*note == NOTE_FADE && */ GetNumInstruments())
@@ -2783,7 +2804,10 @@ bool CSoundFile::ProcessEffects()
if(smp > 0 && smp <= GetNumSamples() && !Samples[smp].uFlags[SMP_NODEFAULTVOLUME])
chn.nVolume = Samples[smp].nVolume;
}
- instr = 0;
+ // IT compatibility: Note-off with instrument number + Old Effects retriggers envelopes.
+ // Test case: ResetEnvNoteOffOldFx.it
+ if(!m_playBehaviour[kITInstrWithNoteOffOldEffects] || !m_SongFlags[SONG_ITOLDEFFECTS])
+ instr = 0;
}
if(ModCommand::IsNote(note))
diff --git a/soundlib/Sndfile.cpp b/soundlib/Sndfile.cpp
index 8531d07..2481b17 100644
--- a/soundlib/Sndfile.cpp
+++ b/soundlib/Sndfile.cpp
@@ -1038,6 +1038,7 @@ PlayBehaviourSet CSoundFile::GetSupportedPlaybackBehaviour(MODTYPE type)
playBehaviour.set(kITInstrWithNoteOff);
playBehaviour.set(kITMultiSampleInstrumentNumber);
playBehaviour.set(kRowDelayWithNoteDelay);
+ playBehaviour.set(kITInstrWithNoteOffOldEffects);
if(type == MOD_TYPE_MPT)
{
playBehaviour.set(kOPLFlexibleNoteOff);
diff --git a/soundlib/Sndmix.cpp b/soundlib/Sndmix.cpp
index 7e29aee..566441e 100644
--- a/soundlib/Sndmix.cpp
+++ b/soundlib/Sndmix.cpp
@@ -2235,7 +2235,7 @@ bool CSoundFile::ReadNote()
period = m_nMinPeriod;
}
- if((chn.dwFlags & (CHN_ADLIB | CHN_MUTE | CHN_SYNCMUTE)) == CHN_ADLIB && !chn.pModSample->uFlags[CHN_MUTE] && m_opl)
+ if((chn.dwFlags & (CHN_ADLIB | CHN_MUTE | CHN_SYNCMUTE)) == CHN_ADLIB && m_opl)
{
const bool doProcess = m_playBehaviour[kOPLFlexibleNoteOff] || !chn.dwFlags[CHN_NOTEFADE] || GetType() == MOD_TYPE_S3M;
if(doProcess && !(GetType() == MOD_TYPE_S3M && chn.dwFlags[CHN_KEYOFF]))
diff --git a/soundlib/UpgradeModule.cpp b/soundlib/UpgradeModule.cpp
index 38dbdc3..33e70af 100644
--- a/soundlib/UpgradeModule.cpp
+++ b/soundlib/UpgradeModule.cpp
@@ -430,49 +430,49 @@ void CSoundFile::UpgradeModule()
// Pre-1.26: Detailed compatibility flags did not exist.
static constexpr PlayBehaviourVersion behaviours[] =
{
- { kTempoClamp, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kPerChannelGlobalVolSlide, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kPanOverride, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITInstrWithoutNote, MAKE_VERSION_NUMERIC(1, 17, 02, 46) },
- { kITVolColFinePortamento, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
- { kITArpeggio, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
- { kITOutOfRangeDelay, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
- { kITPortaMemoryShare, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
- { kITPatternLoopTargetReset, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
- { kITFT2PatternLoop, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
- { kITPingPongNoReset, MAKE_VERSION_NUMERIC(1, 17, 02, 51) },
- { kITEnvelopeReset, MAKE_VERSION_NUMERIC(1, 17, 02, 51) },
- { kITClearOldNoteAfterCut, MAKE_VERSION_NUMERIC(1, 17, 02, 52) },
- { kITVibratoTremoloPanbrello, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITTremor, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITRetrigger, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITMultiSampleBehaviour, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITPortaTargetReached, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITPatternLoopBreak, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITOffset, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITSwingBehaviour, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
- { kITNNAReset, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
- { kITSCxStopsSample, MAKE_VERSION_NUMERIC(1, 18, 00, 01) },
- { kITEnvelopePositionHandling, MAKE_VERSION_NUMERIC(1, 18, 01, 00) },
- { kITPortamentoInstrument, MAKE_VERSION_NUMERIC(1, 19, 00, 01) },
- { kITPingPongMode, MAKE_VERSION_NUMERIC(1, 19, 00, 21) },
- { kITRealNoteMapping, MAKE_VERSION_NUMERIC(1, 19, 00, 30) },
- { kITHighOffsetNoRetrig, MAKE_VERSION_NUMERIC(1, 20, 00, 14) },
- { kITFilterBehaviour, MAKE_VERSION_NUMERIC(1, 20, 00, 35) },
- { kITNoSurroundPan, MAKE_VERSION_NUMERIC(1, 20, 00, 53) },
- { kITShortSampleRetrig, MAKE_VERSION_NUMERIC(1, 20, 00, 54) },
- { kITPortaNoNote, MAKE_VERSION_NUMERIC(1, 20, 00, 56) },
- { kRowDelayWithNoteDelay, MAKE_VERSION_NUMERIC(1, 20, 00, 76) },
- { kITDontResetNoteOffOnPorta, MAKE_VERSION_NUMERIC(1, 20, 02, 06) },
- { kITVolColMemory, MAKE_VERSION_NUMERIC(1, 21, 01, 16) },
- { kITPortamentoSwapResetsPos, MAKE_VERSION_NUMERIC(1, 21, 01, 25) },
- { kITEmptyNoteMapSlot, MAKE_VERSION_NUMERIC(1, 21, 01, 25) },
- { kITFirstTickHandling, MAKE_VERSION_NUMERIC(1, 22, 07, 09) },
- { kITSampleAndHoldPanbrello, MAKE_VERSION_NUMERIC(1, 22, 07, 19) },
- { kITClearPortaTarget, MAKE_VERSION_NUMERIC(1, 23, 04, 03) },
- { kITPanbrelloHold, MAKE_VERSION_NUMERIC(1, 24, 01, 06) },
- { kITPanningReset, MAKE_VERSION_NUMERIC(1, 24, 01, 06) },
- { kITPatternLoopWithJumps, MAKE_VERSION_NUMERIC(1, 25, 00, 19) },
+ { kTempoClamp, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kPerChannelGlobalVolSlide, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kPanOverride, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITInstrWithoutNote, MAKE_VERSION_NUMERIC(1, 17, 02, 46) },
+ { kITVolColFinePortamento, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
+ { kITArpeggio, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
+ { kITOutOfRangeDelay, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
+ { kITPortaMemoryShare, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
+ { kITPatternLoopTargetReset, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
+ { kITFT2PatternLoop, MAKE_VERSION_NUMERIC(1, 17, 02, 49) },
+ { kITPingPongNoReset, MAKE_VERSION_NUMERIC(1, 17, 02, 51) },
+ { kITEnvelopeReset, MAKE_VERSION_NUMERIC(1, 17, 02, 51) },
+ { kITClearOldNoteAfterCut, MAKE_VERSION_NUMERIC(1, 17, 02, 52) },
+ { kITVibratoTremoloPanbrello, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITTremor, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITRetrigger, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITMultiSampleBehaviour, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITPortaTargetReached, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITPatternLoopBreak, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITOffset, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITSwingBehaviour, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
+ { kITNNAReset, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
+ { kITSCxStopsSample, MAKE_VERSION_NUMERIC(1, 18, 00, 01) },
+ { kITEnvelopePositionHandling, MAKE_VERSION_NUMERIC(1, 18, 01, 00) },
+ { kITPortamentoInstrument, MAKE_VERSION_NUMERIC(1, 19, 00, 01) },
+ { kITPingPongMode, MAKE_VERSION_NUMERIC(1, 19, 00, 21) },
+ { kITRealNoteMapping, MAKE_VERSION_NUMERIC(1, 19, 00, 30) },
+ { kITHighOffsetNoRetrig, MAKE_VERSION_NUMERIC(1, 20, 00, 14) },
+ { kITFilterBehaviour, MAKE_VERSION_NUMERIC(1, 20, 00, 35) },
+ { kITNoSurroundPan, MAKE_VERSION_NUMERIC(1, 20, 00, 53) },
+ { kITShortSampleRetrig, MAKE_VERSION_NUMERIC(1, 20, 00, 54) },
+ { kITPortaNoNote, MAKE_VERSION_NUMERIC(1, 20, 00, 56) },
+ { kRowDelayWithNoteDelay, MAKE_VERSION_NUMERIC(1, 20, 00, 76) },
+ { kITDontResetNoteOffOnPorta, MAKE_VERSION_NUMERIC(1, 20, 02, 06) },
+ { kITVolColMemory, MAKE_VERSION_NUMERIC(1, 21, 01, 16) },
+ { kITPortamentoSwapResetsPos, MAKE_VERSION_NUMERIC(1, 21, 01, 25) },
+ { kITEmptyNoteMapSlot, MAKE_VERSION_NUMERIC(1, 21, 01, 25) },
+ { kITFirstTickHandling, MAKE_VERSION_NUMERIC(1, 22, 07, 09) },
+ { kITSampleAndHoldPanbrello, MAKE_VERSION_NUMERIC(1, 22, 07, 19) },
+ { kITClearPortaTarget, MAKE_VERSION_NUMERIC(1, 23, 04, 03) },
+ { kITPanbrelloHold, MAKE_VERSION_NUMERIC(1, 24, 01, 06) },
+ { kITPanningReset, MAKE_VERSION_NUMERIC(1, 24, 01, 06) },
+ { kITPatternLoopWithJumps, MAKE_VERSION_NUMERIC(1, 25, 00, 19) },
};
for(const auto &b : behaviours)
@@ -484,36 +484,36 @@ void CSoundFile::UpgradeModule()
// Pre-1.26: Detailed compatibility flags did not exist.
static constexpr PlayBehaviourVersion behaviours[] =
{
- { kTempoClamp, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kPerChannelGlobalVolSlide, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kPanOverride, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kITFT2PatternLoop, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2Arpeggio, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2Retrigger, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2VolColVibrato, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2PortaNoNote, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2KeyOff, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2PanSlide, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2OffsetOutOfRange, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
- { kFT2RestrictXCommand, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
- { kFT2RetrigWithNoteDelay, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
- { kFT2SetPanEnvPos, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
- { kFT2PortaIgnoreInstr, MAKE_VERSION_NUMERIC(1, 18, 00, 01) },
- { kFT2VolColMemory, MAKE_VERSION_NUMERIC(1, 18, 01, 00) },
- { kFT2LoopE60Restart, MAKE_VERSION_NUMERIC(1, 18, 02, 01) },
- { kFT2ProcessSilentChannels, MAKE_VERSION_NUMERIC(1, 18, 02, 01) },
- { kFT2ReloadSampleSettings, MAKE_VERSION_NUMERIC(1, 20, 00, 36) },
- { kFT2PortaDelay, MAKE_VERSION_NUMERIC(1, 20, 00, 40) },
- { kFT2Transpose, MAKE_VERSION_NUMERIC(1, 20, 00, 62) },
- { kFT2PatternLoopWithJumps, MAKE_VERSION_NUMERIC(1, 20, 00, 69) },
- { kFT2PortaTargetNoReset, MAKE_VERSION_NUMERIC(1, 20, 00, 69) },
- { kFT2EnvelopeEscape, MAKE_VERSION_NUMERIC(1, 20, 00, 77) },
- { kFT2Tremor, MAKE_VERSION_NUMERIC(1, 20, 01, 11) },
- { kFT2OutOfRangeDelay, MAKE_VERSION_NUMERIC(1, 20, 02, 02) },
- { kFT2Periods, MAKE_VERSION_NUMERIC(1, 22, 03, 01) },
- { kFT2PanWithDelayedNoteOff, MAKE_VERSION_NUMERIC(1, 22, 03, 02) },
- { kFT2VolColDelay, MAKE_VERSION_NUMERIC(1, 22, 07, 19) },
- { kFT2FinetunePrecision, MAKE_VERSION_NUMERIC(1, 22, 07, 19) },
+ { kTempoClamp, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kPerChannelGlobalVolSlide, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kPanOverride, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kITFT2PatternLoop, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2Arpeggio, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2Retrigger, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2VolColVibrato, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2PortaNoNote, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2KeyOff, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2PanSlide, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2OffsetOutOfRange, MAKE_VERSION_NUMERIC(1, 17, 03, 02) },
+ { kFT2RestrictXCommand, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
+ { kFT2RetrigWithNoteDelay, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
+ { kFT2SetPanEnvPos, MAKE_VERSION_NUMERIC(1, 18, 00, 00) },
+ { kFT2PortaIgnoreInstr, MAKE_VERSION_NUMERIC(1, 18, 00, 01) },
+ { kFT2VolColMemory, MAKE_VERSION_NUMERIC(1, 18, 01, 00) },
+ { kFT2LoopE60Restart, MAKE_VERSION_NUMERIC(1, 18, 02, 01) },
+ { kFT2ProcessSilentChannels, MAKE_VERSION_NUMERIC(1, 18, 02, 01) },
+ { kFT2ReloadSampleSettings, MAKE_VERSION_NUMERIC(1, 20, 00, 36) },
+ { kFT2PortaDelay, MAKE_VERSION_NUMERIC(1, 20, 00, 40) },
+ { kFT2Transpose, MAKE_VERSION_NUMERIC(1, 20, 00, 62) },
+ { kFT2PatternLoopWithJumps, MAKE_VERSION_NUMERIC(1, 20, 00, 69) },
+ { kFT2PortaTargetNoReset, MAKE_VERSION_NUMERIC(1, 20, 00, 69) },
+ { kFT2EnvelopeEscape, MAKE_VERSION_NUMERIC(1, 20, 00, 77) },
+ { kFT2Tremor, MAKE_VERSION_NUMERIC(1, 20, 01, 11) },
+ { kFT2OutOfRangeDelay, MAKE_VERSION_NUMERIC(1, 20, 02, 02) },
+ { kFT2Periods, MAKE_VERSION_NUMERIC(1, 22, 03, 01) },
+ { kFT2PanWithDelayedNoteOff, MAKE_VERSION_NUMERIC(1, 22, 03, 02) },
+ { kFT2VolColDelay, MAKE_VERSION_NUMERIC(1, 22, 07, 19) },
+ { kFT2FinetunePrecision, MAKE_VERSION_NUMERIC(1, 22, 07, 19) },
};
for(const auto &b : behaviours)
@@ -527,8 +527,9 @@ void CSoundFile::UpgradeModule()
// The following behaviours were added in/after OpenMPT 1.26, so are not affected by the upgrade mechanism above.
static constexpr PlayBehaviourVersion behaviours[] =
{
- { kITInstrWithNoteOff, MAKE_VERSION_NUMERIC(1, 26, 00, 01) },
- { kITMultiSampleInstrumentNumber, MAKE_VERSION_NUMERIC(1, 27, 00, 27) },
+ { kITInstrWithNoteOff, MAKE_VERSION_NUMERIC(1, 26, 00, 01) },
+ { kITMultiSampleInstrumentNumber, MAKE_VERSION_NUMERIC(1, 27, 00, 27) },
+ { kITInstrWithNoteOffOldEffects, MAKE_VERSION_NUMERIC(1, 28, 02, 06) },
};
for(const auto &b : behaviours)
@@ -544,12 +545,12 @@ void CSoundFile::UpgradeModule()
// The following behaviours were added after OpenMPT 1.26, so are not affected by the upgrade mechanism above.
static constexpr PlayBehaviourVersion behaviours[] =
{
- { kFT2NoteOffFlags, MAKE_VERSION_NUMERIC(1, 27, 00, 27) },
- { kRowDelayWithNoteDelay, MAKE_VERSION_NUMERIC(1, 27, 00, 37) },
- { kFT2TremoloRampWaveform, MAKE_VERSION_NUMERIC(1, 27, 00, 37) },
- { kFT2PortaUpDownMemory, MAKE_VERSION_NUMERIC(1, 27, 00, 37) },
- { kFT2PanSustainRelease, MAKE_VERSION_NUMERIC(1, 28, 00, 09) },
- { kFT2NoteDelayWithoutInstr, MAKE_VERSION_NUMERIC(1, 28, 00, 44) },
+ { kFT2NoteOffFlags, MAKE_VERSION_NUMERIC(1, 27, 00, 27) },
+ { kRowDelayWithNoteDelay, MAKE_VERSION_NUMERIC(1, 27, 00, 37) },
+ { kFT2TremoloRampWaveform, MAKE_VERSION_NUMERIC(1, 27, 00, 37) },
+ { kFT2PortaUpDownMemory, MAKE_VERSION_NUMERIC(1, 27, 00, 37) },
+ { kFT2PanSustainRelease, MAKE_VERSION_NUMERIC(1, 28, 00, 09) },
+ { kFT2NoteDelayWithoutInstr, MAKE_VERSION_NUMERIC(1, 28, 00, 44) },
};
for(const auto &b : behaviours)