From 24dfaf7d5c6007115f8787f9a4bcf9557ed1b2e0 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sun, 16 May 2021 16:54:35 -0700 Subject: [PATCH] Updated libopenmpt to version 0.5.9 --- Frameworks/OpenMPT/OpenMPT/build/dist.mk | 6 +- .../OpenMPT/build/make/config-emscripten.mk | 20 ++--- .../OpenMPT/build/svn_version/svn_version.h | 8 +- Frameworks/OpenMPT/OpenMPT/common/misc_util.h | 14 ++++ Frameworks/OpenMPT/OpenMPT/common/mptCPU.cpp | 23 ++++-- Frameworks/OpenMPT/OpenMPT/common/stdafx.h | 2 + Frameworks/OpenMPT/OpenMPT/common/version.cpp | 17 ---- .../OpenMPT/OpenMPT/common/versionNumber.h | 2 +- .../OpenMPT/libopenmpt/dox/changelog.md | 20 +++++ .../OpenMPT/OpenMPT/libopenmpt/libopenmpt.h | 6 +- .../OpenMPT/OpenMPT/libopenmpt/libopenmpt.hpp | 8 +- .../libopenmpt/libopenmpt_ext_impl.cpp | 12 +-- .../OpenMPT/libopenmpt/libopenmpt_version.h | 2 +- .../OpenMPT/libopenmpt/libopenmpt_version.mk | 4 +- .../OpenMPT/libopenmpt/xmp-openmpt.cpp | 2 +- Frameworks/OpenMPT/OpenMPT/sounddsp/DSP.cpp | 2 +- .../OpenMPT/OpenMPT/soundlib/ContainerXPK.cpp | 77 ++++++++----------- .../OpenMPT/OpenMPT/soundlib/Fastmix.cpp | 5 +- .../OpenMPT/OpenMPT/soundlib/ITTools.cpp | 12 ++- Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.h | 2 +- .../OpenMPT/OpenMPT/soundlib/Load_669.cpp | 9 +-- .../OpenMPT/OpenMPT/soundlib/Load_it.cpp | 16 ++-- .../OpenMPT/OpenMPT/soundlib/Load_mdl.cpp | 7 +- .../OpenMPT/OpenMPT/soundlib/Load_mod.cpp | 10 +-- .../OpenMPT/OpenMPT/soundlib/Load_mt2.cpp | 4 +- .../OpenMPT/OpenMPT/soundlib/Load_s3m.cpp | 18 ++++- .../OpenMPT/OpenMPT/soundlib/MixerLoops.cpp | 2 +- .../OpenMPT/OpenMPT/soundlib/ModChannel.cpp | 7 +- .../OpenMPT/OpenMPT/soundlib/ModChannel.h | 2 +- .../OpenMPT/OpenMPT/soundlib/ModSample.cpp | 17 ++-- .../OpenMPT/OpenMPT/soundlib/ModSample.h | 2 +- .../OpenMPT/OpenMPT/soundlib/S3MTools.h | 2 +- .../soundlib/SampleFormatMediaFoundation.cpp | 2 +- .../OpenMPT/OpenMPT/soundlib/Snd_defs.h | 2 +- .../OpenMPT/OpenMPT/soundlib/Snd_fx.cpp | 72 +++++++++-------- .../OpenMPT/OpenMPT/soundlib/Sndfile.cpp | 30 +++++--- Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h | 15 ++-- .../OpenMPT/OpenMPT/soundlib/Sndmix.cpp | 27 +++---- .../OpenMPT/soundlib/UpgradeModule.cpp | 9 ++- .../OpenMPT/OpenMPT/soundlib/XMTools.cpp | 4 +- .../soundlib/plugins/PlugInterface.cpp | 2 + .../soundlib/plugins/PluginManager.cpp | 4 +- Frameworks/OpenMPT/OpenMPT/test/test.cpp | 2 +- 43 files changed, 283 insertions(+), 226 deletions(-) diff --git a/Frameworks/OpenMPT/OpenMPT/build/dist.mk b/Frameworks/OpenMPT/OpenMPT/build/dist.mk index d400f0196..5bb517aa0 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/dist.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/dist.mk @@ -1,4 +1,4 @@ -MPT_SVNVERSION=14580 -MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.8 -MPT_SVNDATE=2021-04-11T14:02:18.903044Z +MPT_SVNVERSION=15019 +MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.9 +MPT_SVNDATE=2021-05-16T14:59:54.252327Z diff --git a/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk b/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk index 69488d0b0..ed6112b7f 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/make/config-emscripten.mk @@ -42,8 +42,8 @@ else ifeq ($(EMSCRIPTEN_TARGET),all) # emits native wasm AND javascript with full wasm optimizations. # as of emscripten 1.38, this is equivalent to default. CPPFLAGS += -DMPT_BUILD_WASM -CXXFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1 -CFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1 +CXXFLAGS += +CFLAGS += LDFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1 LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 @@ -51,8 +51,8 @@ LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 else ifeq ($(EMSCRIPTEN_TARGET),audioworkletprocessor) # emits an es6 module in a single file suitable for use in an AudioWorkletProcessor CPPFLAGS += -DMPT_BUILD_WASM -DMPT_BUILD_AUDIOWORKLETPROCESSOR -CXXFLAGS += -s WASM=1 -s WASM_ASYNC_COMPILATION=0 -s MODULARIZE=1 -s EXPORT_ES6=1 -s SINGLE_FILE=1 -CFLAGS += -s WASM=1 -s WASM_ASYNC_COMPILATION=0 -s MODULARIZE=1 -s EXPORT_ES6=1 -s SINGLE_FILE=1 +CXXFLAGS += +CFLAGS += LDFLAGS += -s WASM=1 -s WASM_ASYNC_COMPILATION=0 -s MODULARIZE=1 -s EXPORT_ES6=1 -s SINGLE_FILE=1 LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 @@ -60,8 +60,8 @@ LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 else ifeq ($(EMSCRIPTEN_TARGET),wasm) # emits native wasm. CPPFLAGS += -DMPT_BUILD_WASM -CXXFLAGS += -s WASM=1 -CFLAGS += -s WASM=1 +CXXFLAGS += +CFLAGS += LDFLAGS += -s WASM=1 LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 @@ -69,16 +69,16 @@ LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 else ifeq ($(EMSCRIPTEN_TARGET),js) # emits only plain javascript with plain javascript focused optimizations. CPPFLAGS += -DMPT_BUILD_ASMJS -CXXFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1 -CFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1 +CXXFLAGS += +CFLAGS += LDFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1 LDFLAGS += -s ALLOW_MEMORY_GROWTH=1 endif -CXXFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ERROR_ON_MISSING_LIBRARIES=1 -ffast-math -CFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ERROR_ON_MISSING_LIBRARIES=1 -ffast-math -fno-strict-aliasing +CXXFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -ffast-math +CFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -ffast-math -fno-strict-aliasing LDFLAGS += -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ERROR_ON_MISSING_LIBRARIES=1 -s EXPORT_NAME="'libopenmpt'" CFLAGS_SILENT += -Wno-\#warnings diff --git a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h index ee3b8e325..828906e76 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 "14580" -#define OPENMPT_VERSION_REVISION 14580 +#define OPENMPT_VERSION_SVNVERSION "15019" +#define OPENMPT_VERSION_REVISION 15019 #define OPENMPT_VERSION_DIRTY 0 #define OPENMPT_VERSION_MIXEDREVISIONS 0 -#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.8" -#define OPENMPT_VERSION_DATE "2021-04-11T14:02:18.903044Z" +#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.9" +#define OPENMPT_VERSION_DATE "2021-05-16T14:59:54.252327Z" #define OPENMPT_VERSION_IS_PACKAGE 1 diff --git a/Frameworks/OpenMPT/OpenMPT/common/misc_util.h b/Frameworks/OpenMPT/OpenMPT/common/misc_util.h index 720e08c14..cfc633002 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/misc_util.h +++ b/Frameworks/OpenMPT/OpenMPT/common/misc_util.h @@ -30,6 +30,7 @@ #include "mptTime.h" #include "mptLibrary.h" +#include #include #include @@ -230,4 +231,17 @@ std::string getenv(const std::string &env_var, const std::string &def = std::str #endif // MODPLUG_TRACKER || (LIBOPENMPT_BUILD && LIBOPENMPT_BUILD_TEST) +#if MPT_OS_WINDOWS + +template +Tstring ParseMaybeNullTerminatedStringFromBufferWithSizeInBytes(const Tbuf *buf, Tsize sizeBytes) +{ + // REG_SZ may contain a single NUL terminator, multiple NUL terminators, or no NUL terminator at all + return Tstring(reinterpret_cast(buf), reinterpret_cast(buf) + (sizeBytes / sizeof(typename Tstring::value_type))).c_str(); +} + + +#endif // MPT_OS_WINDOWS + + OPENMPT_NAMESPACE_END diff --git a/Frameworks/OpenMPT/OpenMPT/common/mptCPU.cpp b/Frameworks/OpenMPT/OpenMPT/common/mptCPU.cpp index ef3b6ab4a..14a260e5e 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/mptCPU.cpp +++ b/Frameworks/OpenMPT/OpenMPT/common/mptCPU.cpp @@ -98,6 +98,19 @@ static cpuid_result cpuid(uint32 function) } +static cpuid_result cpuidex(uint32 function_a, uint32 function_c) +{ + cpuid_result result; + int CPUInfo[4]; + __cpuidex(CPUInfo, function_a, function_c); + result.a = CPUInfo[0]; + result.b = CPUInfo[1]; + result.c = CPUInfo[2]; + result.d = CPUInfo[3]; + return result; +} + + void InitProcSupport() { @@ -150,6 +163,11 @@ void InitProcSupport() if(StandardFeatureFlags.c & (1<<20)) ProcSupport |= PROCSUPPORT_SSE4_2; if(StandardFeatureFlags.c & (1<<28)) ProcSupport |= PROCSUPPORT_AVX; } + if(VendorString.a >= 0x00000007u) + { + cpuid_result ExtendedFeatures = cpuidex(0x00000007u, 0x00000000u); + if(ExtendedFeatures.b & (1<< 5)) ProcSupport |= PROCSUPPORT_AVX2; + } cpuid_result ExtendedVendorString = cpuid(0x80000000u); if(ExtendedVendorString.a >= 0x80000001u) @@ -160,11 +178,6 @@ void InitProcSupport() if(ExtendedVendorString.a >= 0x80000004u) { mpt::String::WriteAutoBuf(ProcBrandID) = cpuid(0x80000002u).as_string4() + cpuid(0x80000003u).as_string4() + cpuid(0x80000004u).as_string4(); - if(ExtendedVendorString.a >= 0x80000007u) - { - cpuid_result ExtendedFeatures = cpuid(0x80000007u); - if(ExtendedFeatures.b & (1<< 5)) ProcSupport |= PROCSUPPORT_AVX2; - } } } diff --git a/Frameworks/OpenMPT/OpenMPT/common/stdafx.h b/Frameworks/OpenMPT/OpenMPT/common/stdafx.h index e1210fcef..0a0eb35cb 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/stdafx.h +++ b/Frameworks/OpenMPT/OpenMPT/common/stdafx.h @@ -140,6 +140,8 @@ // #include "../common/misc_util.h" +// +// // for std::abs #include diff --git a/Frameworks/OpenMPT/OpenMPT/common/version.cpp b/Frameworks/OpenMPT/OpenMPT/common/version.cpp index 8489288f7..8684b7044 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/version.cpp +++ b/Frameworks/OpenMPT/OpenMPT/common/version.cpp @@ -357,23 +357,6 @@ mpt::ustring GetBuildFeaturesString() ; #endif #ifdef MODPLUG_TRACKER - if constexpr(mpt::arch_bits == 64) - { - if (true - && (mpt::Windows::Version::GetMinimumKernelLevel() <= mpt::Windows::Version::WinXP64) - && (mpt::Windows::Version::GetMinimumAPILevel() <= mpt::Windows::Version::WinXP64) - ) { - retval += UL_(" WIN64OLD"); - } - } else if constexpr(mpt::arch_bits == 32) - { - if (true - && (mpt::Windows::Version::GetMinimumKernelLevel() <= mpt::Windows::Version::WinXP) - && (mpt::Windows::Version::GetMinimumAPILevel() <= mpt::Windows::Version::WinXP) - ) { - retval += UL_(" WIN32OLD"); - } - } retval += UL_("") #if defined(UNICODE) UL_(" UNICODE") diff --git a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h index 494fa548d..4fa3570f2 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 29 -#define VER_MINOR 09 +#define VER_MINOR 10 #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 3b4c619e1..474322de4 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md @@ -5,6 +5,26 @@ Changelog {#changelog} For fully detailed change log, please see the source repository directly. This is just a high-level summary. +### libopenmpt 0.5.9 (2021-05-16) + + * `Makefile` `CONFIG=emscripten` does not pass linker options to the compiler + any more, which caused latest Emscripten to issue warnings. + + * The retrigger effect didn't work correctly for OPL instruments in some cases + depending on the chosen output sample rate. + * S3M: Emulate IT short sample retrigger quirk in S3M files saved with + Impulse Tracker and Schism Tracker. + * ProTracker 3.6 doesn't support sample swapping. It is now disabled when + loading a ProTracker 3.6 IFF module. + * Some files with "hidden" garbage patterns were not played correctly since + libopenmpt 0.5.3. + * MOD: E9x retrigger now works the same way as in ProTracker 2. + * MDL: Improve auto-vibrato accuracy. + * 669: Reject files that contain any pattern tempo higher than 15. + * Reduce memory consumption of malformed XPK-compressed files. + + * mpg123: Update to v1.27.2 (2021-05-08). + ### libopenmpt 0.5.8 (2021-04-11) * [**Sec**] Possible null-pointer dereference read caused by a sequence of diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.h b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.h index 8aa69b5e3..97ce46b73 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.h +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.h @@ -559,14 +559,14 @@ LIBOPENMPT_API double openmpt_could_open_probability2( openmpt_stream_callbacks LIBOPENMPT_API size_t openmpt_probe_file_header_get_recommended_size(void); /*! Probe for module formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ -#define OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES 0x1ul +#define OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES 0x1ull /*! Probe for module-specific container formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ -#define OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS 0x2ul +#define OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS 0x2ull /*! Probe for the default set of formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ #define OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT ( OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES | OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS ) /*! Probe for no formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ -#define OPENMPT_PROBE_FILE_HEADER_FLAGS_NONE 0x0ul +#define OPENMPT_PROBE_FILE_HEADER_FLAGS_NONE 0x0ull /*! Possible return values fo openmpt_probe_file_header() and openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ #define OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS 1 diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.hpp b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.hpp index 6b9684936..0cfbaf3f0 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.hpp +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt.hpp @@ -103,7 +103,7 @@ * threads for internal use. * - You must ensure to only ever access a particular libopenmpt object via * non-const member functions from a single thread at a time. - * - You may access a particular libopenmpt objects concurrently from different + * - You may access a particular libopenmpt object concurrently from different * threads when using only const member functions from all threads. * - Consecutive accesses can happen from different threads. * - Different objects can be accessed concurrently from different threads. @@ -273,16 +273,16 @@ LIBOPENMPT_ATTR_DEPRECATED LIBOPENMPT_CXX_API double could_open_propability( std LIBOPENMPT_CXX_API std::size_t probe_file_header_get_recommended_size(); //! Probe for module formats in openmpt::probe_file_header(). \since 0.3.0 -static const std::uint64_t probe_file_header_flags_modules = 0x1ul; +static const std::uint64_t probe_file_header_flags_modules = 0x1ull; //! Probe for module-specific container formats in openmpt::probe_file_header(). \since 0.3.0 -static const std::uint64_t probe_file_header_flags_containers = 0x2ul; +static const std::uint64_t probe_file_header_flags_containers = 0x2ull; //! Probe for the default set of formats in openmpt::probe_file_header(). \since 0.3.0 static const std::uint64_t probe_file_header_flags_default = probe_file_header_flags_modules | probe_file_header_flags_containers; //! Probe for no formats in openmpt::probe_file_header(). \since 0.3.0 -static const std::uint64_t probe_file_header_flags_none = 0x0ul; +static const std::uint64_t probe_file_header_flags_none = 0x0ull; //! Possible return values for openmpt::probe_file_header(). \since 0.3.0 enum probe_file_header_result { diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_ext_impl.cpp b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_ext_impl.cpp index 1910154d8..ac8adff74 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_ext_impl.cpp +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_ext_impl.cpp @@ -215,7 +215,7 @@ namespace openmpt { void module_ext_impl::set_instrument_mute_status( std::int32_t instrument, bool mute ) { const bool instrument_mode = get_num_instruments() != 0; - const int32_t max_instrument = instrument_mode ? get_num_instruments() : get_num_samples(); + const std::int32_t max_instrument = instrument_mode ? get_num_instruments() : get_num_samples(); if ( instrument < 0 || instrument >= max_instrument ) { throw openmpt::exception("invalid instrument"); } @@ -230,7 +230,7 @@ namespace openmpt { bool module_ext_impl::get_instrument_mute_status( std::int32_t instrument ) const { const bool instrument_mode = get_num_instruments() != 0; - const int32_t max_instrument = instrument_mode ? get_num_instruments() : get_num_samples(); + const std::int32_t max_instrument = instrument_mode ? get_num_instruments() : get_num_samples(); if ( instrument < 0 || instrument >= max_instrument ) { throw openmpt::exception("invalid instrument"); } @@ -246,7 +246,7 @@ namespace openmpt { std::int32_t module_ext_impl::play_note( std::int32_t instrument, std::int32_t note, double volume, double panning ) { const bool instrument_mode = get_num_instruments() != 0; - const int32_t max_instrument = instrument_mode ? get_num_instruments() : get_num_samples(); + const std::int32_t max_instrument = instrument_mode ? get_num_instruments() : get_num_samples(); if ( instrument < 0 || instrument >= max_instrument ) { throw openmpt::exception("invalid instrument"); } @@ -261,15 +261,15 @@ namespace openmpt { free_channel = MAX_CHANNELS - 1; ModChannel &chn = m_sndFile->m_PlayState.Chn[free_channel]; - chn.Reset(ModChannel::resetTotal, *m_sndFile, CHANNELINDEX_INVALID); + chn.Reset(ModChannel::resetTotal, *m_sndFile, CHANNELINDEX_INVALID, CHN_MUTE); chn.nMasterChn = 0; // remove NNA association chn.nNewNote = chn.nLastNote = static_cast(note); chn.ResetEnvelopes(); m_sndFile->InstrumentChange(chn, instrument + 1); chn.nFadeOutVol = 0x10000; m_sndFile->NoteChange(chn, note, false, true, true); - chn.nPan = mpt::saturate_round( Clamp( panning * 128.0, -128.0, 128.0 ) + 128.0 ); - chn.nVolume = mpt::saturate_round( Clamp( volume * 256.0, 0.0, 256.0 ) ); + chn.nPan = mpt::saturate_round( Clamp( panning * 128.0, -128.0, 128.0 ) + 128.0 ); + chn.nVolume = mpt::saturate_round( Clamp( volume * 256.0, 0.0, 256.0 ) ); // Remove channel from list of mixed channels to fix https://bugs.openmpt.org/view.php?id=209 // This is required because a previous note on the same channel might have just stopped playing, diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h index 2287500f4..37fbb63d3 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h @@ -19,7 +19,7 @@ /*! \brief libopenmpt minor version number */ #define OPENMPT_API_VERSION_MINOR 5 /*! \brief libopenmpt patch version number */ -#define OPENMPT_API_VERSION_PATCH 8 +#define OPENMPT_API_VERSION_PATCH 9 /*! \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 22147841c..cac7acd43 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=5 -LIBOPENMPT_VERSION_PATCH=8 +LIBOPENMPT_VERSION_PATCH=9 LIBOPENMPT_VERSION_PREREL= LIBOPENMPT_LTVER_CURRENT=2 -LIBOPENMPT_LTVER_REVISION=8 +LIBOPENMPT_LTVER_REVISION=9 LIBOPENMPT_LTVER_AGE=2 diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/xmp-openmpt.cpp b/Frameworks/OpenMPT/OpenMPT/libopenmpt/xmp-openmpt.cpp index 5fa96f99a..51f158a2e 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/xmp-openmpt.cpp +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/xmp-openmpt.cpp @@ -1748,7 +1748,7 @@ XMPIN * WINAPI XMPIN_GetInterface( DWORD face, InterfaceProc faceproc ) { } #pragma comment(linker, "/EXPORT:XMPIN_GetInterface=_XMPIN_GetInterface@8") -}; // extern "C" +} // extern "C" #ifdef _MFC_VER diff --git a/Frameworks/OpenMPT/OpenMPT/sounddsp/DSP.cpp b/Frameworks/OpenMPT/OpenMPT/sounddsp/DSP.cpp index 0da829da2..6eb503b70 100644 --- a/Frameworks/OpenMPT/OpenMPT/sounddsp/DSP.cpp +++ b/Frameworks/OpenMPT/OpenMPT/sounddsp/DSP.cpp @@ -280,7 +280,7 @@ void CMegaBass::Process(int * MixSoundBuffer, int * MixRearBuffer, int count, ui if(nChannels >= 2) { X86_StereoDCRemoval(MixSoundBuffer, count, nDCRFlt_Y1lf, nDCRFlt_X1lf, nDCRFlt_Y1rf, nDCRFlt_X1rf); - if(nChannels > 2) X86_StereoDCRemoval(MixSoundBuffer, count, nDCRFlt_Y1lb, nDCRFlt_X1lb, nDCRFlt_Y1rb, nDCRFlt_X1rb); + if(nChannels > 2) X86_StereoDCRemoval(MixRearBuffer, count, nDCRFlt_Y1lb, nDCRFlt_X1lb, nDCRFlt_Y1rb, nDCRFlt_X1rb); int *px = MixSoundBuffer; int *py = MixRearBuffer; int x1 = nXBassFlt_X1; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerXPK.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerXPK.cpp index 5eb301fc2..7f35f999d 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerXPK.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ContainerXPK.cpp @@ -48,24 +48,12 @@ struct XPK_BufferBounds { const uint8 *pSrcBeg; std::size_t SrcSize; - uint8 *pDstBeg; - std::size_t DstSize; inline uint8 SrcRead(std::size_t index) { if(index >= SrcSize) throw XPK_error(); return pSrcBeg[index]; } - inline void DstWrite(std::size_t index, uint8 value) - { - if(index >= DstSize) throw XPK_error(); - pDstBeg[index] = value; - } - inline uint8 DstRead(std::size_t index) - { - if(index >= DstSize) throw XPK_error(); - return pDstBeg[index]; - } }; static int32 bfextu(std::size_t p, int32 bo, int32 bc, XPK_BufferBounds &bufs) @@ -119,23 +107,17 @@ static bool XPK_DoUnpack(const uint8 *src_, uint32 srcLen, std::vector &un int32 cp, cup1, type; std::size_t c; std::size_t src; - std::size_t dst; - std::size_t phist = 0; - std::size_t dstmax = len; - unpackedData.resize(len); + unpackedData.reserve(std::min(static_cast(len), std::min(srcLen, uint32_max / 20u) * 20u)); XPK_BufferBounds bufs; bufs.pSrcBeg = src_; bufs.SrcSize = srcLen; - bufs.pDstBeg = mpt::byte_cast(unpackedData.data()); - bufs.DstSize = len; src = 0; - dst = 0; c = src; - while (len > 0) + while(len > 0) { type = bufs.SrcRead(c+0); cp = (bufs.SrcRead(c+4)<<8) | (bufs.SrcRead(c+5)); // packed @@ -146,12 +128,11 @@ static bool XPK_DoUnpack(const uint8 *src_, uint32 srcLen, std::vector &un if (type == 0) { // RAW chunk - if(cp < 0) throw XPK_error(); + if(cp < 0 || cp > len) throw XPK_error(); for(int32 i = 0; i < cp; ++i) { - bufs.DstWrite(dst + i, bufs.SrcRead(c + i)); + unpackedData.push_back(bufs.SrcRead(c + i)); } - dst+=cp; c+=cp; len -= cp; continue; @@ -164,14 +145,14 @@ static bool XPK_DoUnpack(const uint8 *src_, uint32 srcLen, std::vector &un #endif break; } + LimitMax(cup1, len); len -= cup1; cp = (cp + 3) & 0xfffc; c += cp; d0 = d1 = d2 = a2 = 0; d3 = bufs.SrcRead(src); src++; - bufs.DstWrite(dst, (uint8)d3); - if (dst < dstmax) dst++; + unpackedData.push_back(static_cast(d3)); cup1--; while (cup1 > 0) @@ -230,8 +211,7 @@ static bool XPK_DoUnpack(const uint8 *src_, uint32 srcLen, std::vector &un d4 = bfexts(src,d0,d6,bufs); d0 += d6; d3 -= d4; - bufs.DstWrite(dst, (uint8)d3); - if (dst < dstmax) dst++; + unpackedData.push_back(static_cast(d3)); cup1--; d5--; } @@ -243,7 +223,6 @@ static bool XPK_DoUnpack(const uint8 *src_, uint32 srcLen, std::vector &un d2 -= d6; } } - unpackedData.resize(bufs.DstSize - len); return !unpackedData.empty(); l75a: @@ -287,22 +266,24 @@ l79e: l7a6: d6 += d4; l7a8: - if (bfextu(src,d0,1,bufs)) goto l7c4; - d0 += 1; - if (bfextu(src,d0,1,bufs)) goto l7bc; - d5 = 8; - a5 = 0; - goto l7ca; + if(bfextu(src, d0, 1, bufs)) + { + d5 = 12; + a5 = -0x100; + } else + { + d0 += 1; + if(bfextu(src, d0, 1, bufs)) + { + d5 = 14; + a5 = -0x1100; + } else + { + d5 = 8; + a5 = 0; + } + } -l7bc: - d5 = 14; - a5 = -0x1100; - goto l7ca; - -l7c4: - d5 = 12; - a5 = -0x100; -l7ca: d0 += 1; d4 = bfextu(src,d0,d5,bufs); d0 += d5; @@ -314,13 +295,15 @@ l7ca: if (d1 < 0) d1 = 0; } d6 += 2; - phist = dst + a5 - d4 - 1; + phist = unpackedData.size() + a5 - d4 - 1; + if(phist >= unpackedData.size()) + throw XPK_error(); while ((d6 >= 0) && (cup1 > 0)) { - d3 = bufs.DstRead(phist); phist++; - bufs.DstWrite(dst, (uint8)d3); - if (dst < dstmax) dst++; + d3 = unpackedData[phist]; + phist++; + unpackedData.push_back(static_cast(d3)); cup1--; d6--; } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp index 4674339a5..9bb79a80c 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp @@ -59,6 +59,8 @@ struct MixLoopState { samplePointer = static_cast(chn.pCurrentSample); lookaheadPointer = nullptr; + if(!samplePointer) + return; if(chn.nLoopEnd < InterpolationMaxLookahead) lookaheadStart = chn.nLoopStart; else @@ -94,7 +96,8 @@ struct MixLoopState int32 nLoopStart = chn.dwFlags[CHN_LOOP] ? chn.nLoopStart : 0; SamplePosition nInc = chn.increment; - if ((nSamples <= 0) || nInc.IsZero() || (!chn.nLength)) return 0; + if(nSamples <= 0 || nInc.IsZero() || !chn.nLength || !samplePointer) + return 0; // Part 1: Making sure the play position is valid, and if necessary, invert the play direction in case we reached a loop boundary of a ping-pong loop. chn.pCurrentSample = samplePointer; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.cpp index 1ea975a69..51db8188c 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.cpp @@ -448,7 +448,7 @@ void ITSample::ConvertToIT(const ModSample &mptSmp, MODTYPE fromType, bool compr if(mptSmp.uFlags[CHN_PANNING]) dfp |= ITSample::enablePanning; // Sample Format / Loop Flags - if(mptSmp.HasSampleData()) + if(mptSmp.HasSampleData() && !mptSmp.uFlags[CHN_ADLIB]) { flags = ITSample::sampleDataPresent; if(mptSmp.uFlags[CHN_LOOP]) flags |= ITSample::sampleLoop; @@ -498,12 +498,16 @@ void ITSample::ConvertToIT(const ModSample &mptSmp, MODTYPE fromType, bool compr if((vid | vis) != 0 && (fromType & MOD_TYPE_XM)) { // Sweep is upside down in XM - vir = 255 - vir; + if(mptSmp.nVibSweep != 0) + vir = mpt::saturate_cast(Util::muldivr_unsigned(mptSmp.nVibDepth, 256, mptSmp.nVibSweep)); + else + vir = 255; } if(mptSmp.uFlags[CHN_ADLIB]) { length = 12; + flags = ITSample::sampleDataPresent; cvt = ITSample::cvtOPLInstrument; } else if(mptSmp.uFlags[SMP_KEEPONDISK]) { @@ -668,9 +672,9 @@ uint32 DecodeITEditTimer(uint16 cwtv, uint32 editTime) if((cwtv & 0xFFF) >= 0x0208) { editTime ^= 0x4954524B; // 'ITRK' - editTime = (editTime >> 7) | (editTime << (32 - 7)); + editTime = mpt::rotr(editTime, 7); editTime = ~editTime + 1; - editTime = (editTime << 4) | (editTime >> (32 - 4)); + editTime = mpt::rotl(editTime, 4); editTime ^= 0x4A54484C; // 'JTHL' } return editTime; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.h b/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.h index 64751f8e2..79bdc978f 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ITTools.h @@ -63,7 +63,7 @@ struct ITFileHeader uint8le pwd; // Pitch Wheel Depth uint16le msglength; // Length of Song Message uint32le msgoffset; // Offset of Song Message in File (IT crops message after first null) - uint32le reserved; // Some IT versions save an edit timer here. ChibiTracker writes "CHBI" here. OpenMPT writes "OMPT" here in some cases, see Load_it.cpp + uint32le reserved; // Some IT versions save an edit timer here. ChibiTracker writes "CHBI" here. OpenMPT and Schism Tracker save extended version information here. uint8le chnpan[64]; // Initial Channel Panning uint8le chnvol[64]; // Initial Channel Volume }; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_669.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_669.cpp index f09c1545c..1d1aa881f 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_669.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_669.cpp @@ -74,17 +74,13 @@ static bool ValidateHeader(const _669FileHeader &fileHeader) for(std::size_t i = 0; i < CountOf(fileHeader.breaks); i++) { if(fileHeader.orders[i] >= 128 && fileHeader.orders[i] < 0xFE) - { return false; - } if(fileHeader.orders[i] < 128 && fileHeader.tempoList[i] == 0) - { return false; - } + if(fileHeader.tempoList[i] > 15) + return false; if(fileHeader.breaks[i] >= 64) - { return false; - } } return true; } @@ -242,6 +238,7 @@ bool CSoundFile::Read669(FileReader &file, ModLoadingFlags loadFlags) m->param = effect[chn] & 0x0F; + // Weird stuff happening in corehop.669 with effects > 8... they seem to do the same thing as if the high bit wasn't set, but the sample also behaves strangely. uint8 command = effect[chn] >> 4; if(command < static_cast(CountOf(effTrans))) { diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp index 66f07a02e..a9e8a00e1 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp @@ -478,9 +478,12 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags) { // OpenMPT Version number (Major.Minor) // This will only be interpreted as "made with ModPlug" (i.e. disable compatible playback etc) if the "reserved" field is set to "OMPT" - else, compatibility was used. - m_dwLastSavedWithVersion = Version((fileHeader.cwtv & 0x0FFF) << 16); + uint32 mptVersion = (fileHeader.cwtv & 0x0FFF) << 16; if(!memcmp(&fileHeader.reserved, "OMPT", 4)) interpretModPlugMade = true; + else if(mptVersion >= 0x01'29'00'00) + mptVersion |= fileHeader.reserved & 0xFFFF; + m_dwLastSavedWithVersion = Version(mptVersion); } else if(fileHeader.cmwt == 0x888 || fileHeader.cwtv == 0x888) { // OpenMPT 1.17.02.26 (r122) to 1.18 (raped IT format) @@ -1416,8 +1419,8 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c } else { // IT - uint32 vVersion = Version::Current().GetRawVersion(); - itHeader.cwtv = 0x5000 | (uint16)((vVersion >> 16) & 0x0FFF); // format: txyy (t = tracker ID, x = version major, yy = version minor), e.g. 0x5117 (OpenMPT = 5, 117 = v1.17) + const uint32 mptVersion = Version::Current().GetRawVersion(); + itHeader.cwtv = 0x5000 | static_cast((mptVersion >> 16) & 0x0FFF); // format: txyy (t = tracker ID, x = version major, yy = version minor), e.g. 0x5117 (OpenMPT = 5, 117 = v1.17) itHeader.cmwt = 0x0214; // Common compatible tracker :) // Hack from schism tracker: for(INSTRUMENTINDEX nIns = 1; nIns <= GetNumInstruments(); nIns++) @@ -1429,11 +1432,10 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c } } - if(!compatibilityExport) - { - // This way, we indicate that the file might contain OpenMPT hacks. Compatibility export puts 0 here. + if(compatibilityExport) + itHeader.reserved = mptVersion & 0xFFFF; + else memcpy(&itHeader.reserved, "OMPT", 4); - } } itHeader.flags = ITFileHeader::useStereoPlayback | ITFileHeader::useMIDIPitchController; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mdl.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mdl.cpp index e383294b3..699a929ca 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mdl.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mdl.cpp @@ -635,8 +635,13 @@ bool CSoundFile::ReadMDL(FileReader &file, ModLoadingFlags loadFlags) mptSmp.nPan = std::min(static_cast(sampleHeader.panning * 2), uint16(254)); mptSmp.nVibType = MDLVibratoType[sampleHeader.vibType & 3]; mptSmp.nVibSweep = sampleHeader.vibSweep; - mptSmp.nVibDepth = sampleHeader.vibDepth; + mptSmp.nVibDepth = (sampleHeader.vibDepth + 3u) / 4u; mptSmp.nVibRate = sampleHeader.vibSpeed; + // Convert to IT-like vibrato sweep + if(mptSmp.nVibSweep != 0) + mptSmp.nVibSweep = mpt::saturate_cast(Util::muldivr_unsigned(mptSmp.nVibDepth, 256, mptSmp.nVibSweep)); + else + mptSmp.nVibSweep = 255; if(sampleHeader.panEnvFlags & 0x40) mptSmp.uFlags.set(CHN_PANNING); } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp index a4fcbaed7..f327c5041 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp @@ -552,7 +552,7 @@ static bool ValidateMODPatternData(TFileReader &file, const uint32 threshold, co // Parse the order list to determine how many patterns are used in the file. -static PATTERNINDEX GetNumPatterns(FileReader &file, ModSequence &Order, ORDERINDEX numOrders, SmpLength totalSampleLen, CHANNELINDEX &numChannels, SmpLength wowSampleLen = 0) +static PATTERNINDEX GetNumPatterns(FileReader &file, ModSequence &Order, ORDERINDEX numOrders, SmpLength totalSampleLen, CHANNELINDEX &numChannels, SmpLength wowSampleLen, bool validateHiddenPatterns) { PATTERNINDEX numPatterns = 0; // Total number of patterns in file (determined by going through the whole order list) with pattern number < 128 PATTERNINDEX officialPatterns = 0; // Number of patterns only found in the "official" part of the order list (i.e. order positions < claimed order length) @@ -590,7 +590,7 @@ static PATTERNINDEX GetNumPatterns(FileReader &file, ModSequence &Order, ORDERIN if(ValidateMODPatternData(file, 16, true)) numChannels = 8; file.Seek(patternStartOffset); - } else if(numPatterns != officialPatterns && numChannels == 4 && !wowSampleLen) + } else if(numPatterns != officialPatterns && validateHiddenPatterns) { // Fix SoundTracker modules where "hidden" patterns should be ignored. // razor-1911.mod (MD5 b75f0f471b0ae400185585ca05bf7fe8, SHA1 4de31af234229faec00f1e85e1e8f78f405d454b) @@ -913,7 +913,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags) } // Get number of patterns (including some order list sanity checks) - PATTERNINDEX numPatterns = GetNumPatterns(file, Order(), realOrders, totalSampleLen, m_nChannels, wowSampleLen); + PATTERNINDEX numPatterns = GetNumPatterns(file, Order(), realOrders, totalSampleLen, m_nChannels, wowSampleLen, false); if(maybeWOW && GetNumChannels() == 8) { // M.K. with 8 channels = Mod's Grave @@ -1511,7 +1511,7 @@ bool CSoundFile::ReadM15(FileReader &file, ModLoadingFlags loadFlags) file.ReadStruct(fileHeader); ReadOrderFromArray(Order(), fileHeader.orderList); - PATTERNINDEX numPatterns = GetNumPatterns(file, Order(), fileHeader.numOrders, totalSampleLen, m_nChannels); + PATTERNINDEX numPatterns = GetNumPatterns(file, Order(), fileHeader.numOrders, totalSampleLen, m_nChannels, 0, true); // Most likely just a file with lots of NULs at the start if(fileHeader.restartPos == 0 && fileHeader.numOrders == 0 && numPatterns <= 1) @@ -2201,7 +2201,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) m_SongFlags.set(SONG_PT_MODE); m_playBehaviour.set(kMODIgnorePanning); m_playBehaviour.set(kMODOneShotLoops); - m_playBehaviour.set(kMODSampleSwap); + m_playBehaviour.reset(kMODSampleSwap); return ok; } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp index 30faa6268..00366012c 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp @@ -721,12 +721,12 @@ bool CSoundFile::ReadMT2(FileReader &file, ModLoadingFlags loadFlags) // MT2 only ever calls effGetChunk for programs, and OpenMPT uses the defaultProgram value to determine // whether it should use effSetChunk for programs or banks... mixPlug.defaultProgram = -1; - LimitMax(vstHeader.n, Util::MaxValueOfType(dataSize) - 4); + LimitMax(vstHeader.n, std::numeric_limits::max() - 4); dataSize = vstHeader.n + 4; } else { mixPlug.defaultProgram = vstHeader.programNr; - LimitMax(vstHeader.n, (Util::MaxValueOfType(dataSize) / 4u) - 1); + LimitMax(vstHeader.n, (std::numeric_limits::max() / 4u) - 1); dataSize = vstHeader.n * 4 + 4; } mixPlug.pluginData.resize(dataSize); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_s3m.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_s3m.cpp index 6f07e14e9..4620637cf 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_s3m.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_s3m.cpp @@ -284,6 +284,8 @@ bool CSoundFile::ReadS3M(FileReader &file, ModLoadingFlags loadFlags) m_FileHistory.push_back(hist); } nonCompatTracker = true; + m_playBehaviour.set(kITRetrigger); + m_playBehaviour.set(kITShortSampleRetrig); m_playBehaviour.set(kST3SampleSwap); // Not exactly like ST3, but close enough m_nMinPeriod = 1; break; @@ -297,13 +299,19 @@ bool CSoundFile::ReadS3M(FileReader &file, ModLoadingFlags loadFlags) madeWithTracker = GetSchismTrackerVersion(fileHeader.cwtv, fileHeader.reserved2); m_nMinPeriod = 1; isSchism = true; + if(fileHeader.cwtv >= SchismVersionFromDate<2016, 05, 13>::Version(S3MFileHeader::trkSchismTracker)) + m_playBehaviour.set(kITShortSampleRetrig); } nonCompatTracker = true; break; case S3MFileHeader::trkOpenMPT: - madeWithTracker = U_("OpenMPT"); - formatTrackerStr = true; - m_dwLastSavedWithVersion = Version((fileHeader.cwtv & S3MFileHeader::versionMask) << 16); + { + uint32 mptVersion = (fileHeader.cwtv & S3MFileHeader::versionMask) << 16; + if(mptVersion >= 0x01'29'00'00) + mptVersion |= fileHeader.reserved2; + m_dwLastSavedWithVersion = Version(mptVersion); + madeWithTracker = U_("OpenMPT ") + mpt::ufmt::val(m_dwLastSavedWithVersion); + } break; case S3MFileHeader::trkBeRoTracker: madeWithTracker = U_("BeRoTracker"); @@ -676,7 +684,9 @@ bool CSoundFile::SaveS3M(std::ostream &f) const // Version info following: ST3.20 = 0x1320 // Most significant nibble = Tracker ID, see S3MFileHeader::S3MTrackerVersions // Following: One nibble = Major version, one byte = Minor version (hex) - fileHeader.cwtv = S3MFileHeader::trkOpenMPT | static_cast((Version::Current().GetRawVersion() >> 16) & S3MFileHeader::versionMask); + const uint32 mptVersion = Version::Current().GetRawVersion(); + fileHeader.cwtv = S3MFileHeader::trkOpenMPT | static_cast((mptVersion >> 16) & S3MFileHeader::versionMask); + fileHeader.reserved2 = static_cast(mptVersion); fileHeader.formatVersion = S3MFileHeader::newVersion; memcpy(fileHeader.magic, "SCRM", 4); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/MixerLoops.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/MixerLoops.cpp index 5b4345e4e..af8cb8541 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/MixerLoops.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/MixerLoops.cpp @@ -12,7 +12,7 @@ #include "stdafx.h" #include "MixerLoops.h" -#include "..//soundbase/SampleBuffer.h" +#include "../soundbase/SampleBuffer.h" #include "Snd_defs.h" #include "ModChannel.h" #ifdef ENABLE_SSE2 diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp index 847665c14..626373bfc 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp @@ -15,7 +15,7 @@ OPENMPT_NAMESPACE_BEGIN -void ModChannel::Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELINDEX sourceChannel) +void ModChannel::Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELINDEX sourceChannel, ChannelFlags muteFlag) { if(resetMask & resetSetPosBasic) { @@ -81,6 +81,11 @@ void ModChannel::Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELI dwFlags = sndFile.ChnSettings[sourceChannel].dwFlags; nPan = sndFile.ChnSettings[sourceChannel].nPan; nGlobalVol = sndFile.ChnSettings[sourceChannel].nVolume; + if(dwFlags[CHN_MUTE]) + { + dwFlags.reset(CHN_MUTE); + dwFlags.set(muteFlag); + } } else { dwFlags.reset(); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.h b/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.h index af51342fe..a1af33a10 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.h @@ -174,7 +174,7 @@ struct ModChannel resetTotal = resetSetPosFull, }; - void Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELINDEX sourceChannel); + void Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELINDEX sourceChannel, ChannelFlags muteFlag); void Stop(); bool IsSamplePlaying() const noexcept { return !increment.IsZero(); } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.cpp index e639f9ca1..7868c38e1 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.cpp @@ -457,22 +457,21 @@ void ModSample::TransposeToFrequency() } -// Return tranpose.finetune as 25.7 fixed point value. -int32 ModSample::FrequencyToTranspose(uint32 freq) +// Return a pair of {tranpose, finetune} +std::pair ModSample::FrequencyToTranspose(uint32 freq) { if(!freq) - return 0; - else - return mpt::saturate_round(std::log(freq * (1.0 / 8363.0)) * (12.0 * 128.0 * (1.0 / M_LN2))); + return {}; + + const auto f2t = mpt::saturate_round(std::log(freq * (1.0 / 8363.0)) * (12.0 * 128.0 * (1.0 / M_LN2))); + const auto fine = std::div(Clamp(f2t, -16384, 16383), int32(128)); + return {static_cast(fine.quot), static_cast(fine.rem)}; } void ModSample::FrequencyToTranspose() { - const int f2t = Clamp(FrequencyToTranspose(nC5Speed), -16384, 16383); - const auto fine = std::div(f2t, 128); - RelativeTone = static_cast(fine.quot); - nFineTune = static_cast(fine.rem); + std::tie(RelativeTone, nFineTune) = FrequencyToTranspose(nC5Speed); } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.h b/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.h index c23769ca3..a168dff24 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ModSample.h @@ -146,7 +146,7 @@ struct ModSample // Transpose <-> Frequency conversions static uint32 TransposeToFrequency(int transpose, int finetune = 0); void TransposeToFrequency(); - static int32 FrequencyToTranspose(uint32 freq); + static std::pair FrequencyToTranspose(uint32 freq); void FrequencyToTranspose(); // Transpose the sample by amount specified in octaves (i.e. amount=1 transposes one octave up) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/S3MTools.h b/Frameworks/OpenMPT/OpenMPT/soundlib/S3MTools.h index 4c0e5885d..5dba75dbf 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/S3MTools.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/S3MTools.h @@ -84,7 +84,7 @@ struct S3MFileHeader uint8le masterVolume; // Sample Volume (0...127, stereo if high bit is set) uint8le ultraClicks; // Number of channels used for ultra click removal uint8le usePanningTable; // 0xFC => read extended panning table - uint16le reserved2; // Schism Tracker uses this for its extended version information + uint16le reserved2; // Schism Tracker and OpenMPT use this for their extended version information uint32le reserved3; // Impulse Tracker hides its edit timer here uint16le reserved4; uint16le special; // Pointer to special custom data (unused) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMediaFoundation.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMediaFoundation.cpp index 8cc9c3d2a..6bba97110 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMediaFoundation.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatMediaFoundation.cpp @@ -249,7 +249,7 @@ std::vector CSoundFile::GetMediaFoundationFileTypes() std::wstring guid = std::wstring(valueNameBuf); - mpt::ustring description = mpt::ToUnicode(std::wstring(reinterpret_cast(valueData))); + mpt::ustring description = mpt::ToUnicode(ParseMaybeNullTerminatedStringFromBufferWithSizeInBytes(valueData, valueDataLen)); description = mpt::String::Replace(description, U_("Byte Stream Handler"), U_("Files")); description = mpt::String::Replace(description, U_("ByteStreamHandler"), U_("Files")); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h index deebd26f1..26b9ab96d 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h @@ -268,7 +268,7 @@ enum SongFlags }; DECLARE_FLAGSET(SongFlags) -#define SONG_FILE_FLAGS (SONG_FASTVOLSLIDES|SONG_ITOLDEFFECTS|SONG_ITCOMPATGXX|SONG_LINEARSLIDES|SONG_EXFILTERRANGE|SONG_AMIGALIMITS|SONG_S3MOLDVIBRATO|SONG_PT_MODE|SONG_ISAMIGA) +#define SONG_FILE_FLAGS (SONG_FASTVOLSLIDES|SONG_ITOLDEFFECTS|SONG_ITCOMPATGXX|SONG_LINEARSLIDES|SONG_EXFILTERRANGE|SONG_AMIGALIMITS|SONG_S3MOLDVIBRATO|SONG_PT_MODE|SONG_ISAMIGA|SONG_IMPORTED) #define SONG_PLAY_FLAGS (~SONG_FILE_FLAGS) // Global Options (Renderer) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp index 7ba86dfe5..8d7875798 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp @@ -93,9 +93,10 @@ public: state->m_nMusicTempo = sndFile.m_nDefaultTempo; state->m_nGlobalVolume = sndFile.m_nDefaultGlobalVolume; chnSettings.assign(sndFile.GetNumChannels(), ChnSettings()); + const auto muteFlag = CSoundFile::GetChannelMuteFlag(); for(CHANNELINDEX chn = 0; chn < sndFile.GetNumChannels(); chn++) { - state->Chn[chn].Reset(ModChannel::resetTotal, sndFile, chn); + state->Chn[chn].Reset(ModChannel::resetTotal, sndFile, chn, muteFlag); state->Chn[chn].nOldGlobalVolSlide = 0; state->Chn[chn].nOldChnVolSlide = 0; state->Chn[chn].nNote = state->Chn[chn].nNewNote = state->Chn[chn].nLastNote = NOTE_NONE; @@ -592,7 +593,7 @@ std::vector CSoundFile::GetLength(enmGetLengthResetMode adjustMod if(chn.rowCommand.vol) { const auto [porta, clearEffectCommand] = GetVolCmdTonePorta(chn.rowCommand, 0); - chn.nPortamentoSlide = porta * 4; + chn.nPortamentoSlide = porta; if(clearEffectCommand) command = CMD_NONE; } @@ -791,7 +792,7 @@ std::vector CSoundFile::GetLength(enmGetLengthResetMode adjustMod break; // Tone-Portamento case CMD_TONEPORTAMENTO: - if (param) chn.nPortamentoSlide = param << 2; + if (param) chn.nPortamentoSlide = param; break; // Offset case CMD_OFFSET: @@ -2192,6 +2193,12 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo if(!srcChn.nLength || srcChn.dwFlags[CHN_MUTE] || !(srcChn.rightVol | srcChn.leftVol)) return CHANNELINDEX_INVALID; + if(srcChn.dwFlags[CHN_ADLIB] && m_opl) + { + m_opl->NoteCut(nChn, false); + return CHANNELINDEX_INVALID; + } + const CHANNELINDEX nnaChn = GetNNAChannel(nChn); if(nnaChn == CHANNELINDEX_INVALID) return CHANNELINDEX_INVALID; @@ -2211,10 +2218,6 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo srcChn.position.Set(0); srcChn.nROfs = srcChn.nLOfs = 0; srcChn.rightVol = srcChn.leftVol = 0; - if(srcChn.dwFlags[CHN_ADLIB] && m_opl) - { - m_opl->NoteCut(nChn); - } return nnaChn; } if(instr > GetNumInstruments()) @@ -4193,18 +4196,17 @@ void CSoundFile::TonePortamento(ModChannel &chn, uint32 param) const chn.nOldPortaUp = chn.nOldPortaDown = static_cast(param); } + if(param) + chn.nPortamentoSlide = param; + if(chn.HasCustomTuning()) { //Behavior: Param tells number of finesteps(or 'fullsteps'(notes) with glissando) //to slide per row(not per tick). const int32 oldPortamentoTickSlide = (m_PlayState.m_nTickCount != 0) ? chn.m_PortamentoTickSlide : 0; - if(param) - chn.nPortamentoSlide = param; - else - if(chn.nPortamentoSlide == 0) - return; - + if(chn.nPortamentoSlide == 0) + return; if((chn.nPortamentoDest > 0 && chn.nPortamentoSlide < 0) || (chn.nPortamentoDest < 0 && chn.nPortamentoSlide > 0)) @@ -4242,47 +4244,49 @@ void CSoundFile::TonePortamento(ModChannel &chn, uint32 param) const || (GetType() & (MOD_TYPE_DBM | MOD_TYPE_669)) || (m_PlayState.m_nMusicSpeed == 1 && m_playBehaviour[kSlidesAtSpeed1]) || (GetType() == MOD_TYPE_MED && m_SongFlags[SONG_FASTVOLSLIDES]); - if(GetType() == MOD_TYPE_PLM && param >= 0xF0) + + int32 delta = chn.nPortamentoSlide; + if(GetType() == MOD_TYPE_PLM && delta >= 0xF0) { - param -= 0xF0; + delta -= 0xF0; doPorta = chn.isFirstTick; } - if(param) + if(GetType() == MOD_TYPE_669) { - if(GetType() == MOD_TYPE_669) - { - param *= 10; - } - chn.nPortamentoSlide = param * 4; + delta *= 10; } if(chn.nPeriod && chn.nPortamentoDest && doPorta) { if (chn.nPeriod < chn.nPortamentoDest) { - int32 delta = chn.nPortamentoSlide; if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { - uint32 n = chn.nPortamentoSlide / 4; + uint32 n = delta; if (n > 255) n = 255; // Return (a*b+c/2)/c - no divide error // Table is 65536*2(n/192) delta = Util::muldivr(chn.nPeriod, LinearSlideUpTable[n], 65536) - chn.nPeriod; if (delta < 1) delta = 1; + } else + { + delta *= 4; } chn.nPeriod += delta; if (chn.nPeriod > chn.nPortamentoDest) chn.nPeriod = chn.nPortamentoDest; } else if (chn.nPeriod > chn.nPortamentoDest) { - int32 delta = -chn.nPortamentoSlide; if(m_SongFlags[SONG_LINEARSLIDES] && GetType() != MOD_TYPE_XM) { - uint32 n = chn.nPortamentoSlide / 4; + uint32 n = delta; if (n > 255) n = 255; delta = Util::muldivr(chn.nPeriod, LinearSlideDownTable[n], 65536) - chn.nPeriod; if (delta > -1) delta = -1; + } else + { + delta *= -4; } chn.nPeriod += delta; if (chn.nPeriod < chn.nPortamentoDest) chn.nPeriod = chn.nPortamentoDest; @@ -5562,6 +5566,15 @@ void CSoundFile::RetrigNote(CHANNELINDEX nChn, int param, int offset) if(retrigCount && !(retrigCount % retrigSpeed)) doRetrig = true; retrigCount++; + } else if(GetType() == MOD_TYPE_MOD) + { + // ProTracker-style retrigger + // Test case: PTRetrigger.mod + const auto tick = m_PlayState.m_nTickCount % m_PlayState.m_nMusicSpeed; + if(!tick && chn.rowCommand.IsNote()) + return; + if(retrigSpeed && !(tick % retrigSpeed)) + doRetrig = true; } else if(GetType() == MOD_TYPE_MTM) { // In MultiTracker, E9x retriggers the last note at exactly the x-th tick of the row @@ -5624,8 +5637,8 @@ void CSoundFile::RetrigNote(CHANNELINDEX nChn, int param, int offset) } uint32 note = chn.nNewNote; int32 oldPeriod = chn.nPeriod; - const bool retrigAdlib = chn.dwFlags[CHN_ADLIB] && m_playBehaviour[kOPLRealRetrig]; - if(note >= NOTE_MIN && note <= NOTE_MAX && chn.nLength && retrigAdlib) + // ST3 doesn't retrigger OPL notes + if(note >= NOTE_MIN && note <= NOTE_MAX && chn.nLength && (!chn.dwFlags[CHN_ADLIB] || GetType() != MOD_TYPE_S3M || m_playBehaviour[kOPLRealRetrig])) CheckNNA(nChn, 0, note, true); bool resetEnv = false; if(GetType() & (MOD_TYPE_XM | MOD_TYPE_MT2)) @@ -5638,11 +5651,6 @@ void CSoundFile::RetrigNote(CHANNELINDEX nChn, int param, int offset) if(param < 0x100) resetEnv = true; } - if(retrigAdlib && chn.pModSample && m_opl) - { - m_opl->NoteCut(nChn); - m_opl->Patch(nChn, chn.pModSample->adlib); - } const bool fading = chn.dwFlags[CHN_NOTEFADE]; const auto oldPrevNoteOffset = chn.prevNoteOffset; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp index d7fbb909b..6ec23911d 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp @@ -478,11 +478,13 @@ bool CSoundFile::Create(FileReader file, ModLoadingFlags loadFlags) } // Adjust channels - for(CHANNELINDEX ich = 0; ich < MAX_BASECHANNELS; ich++) + const auto muteFlag = GetChannelMuteFlag(); + for(CHANNELINDEX chn = 0; chn < MAX_BASECHANNELS; chn++) { - LimitMax(ChnSettings[ich].nVolume, uint16(64)); - if (ChnSettings[ich].nPan > 256) ChnSettings[ich].nPan = 128; - m_PlayState.Chn[ich].Reset(ModChannel::resetTotal, *this, ich); + LimitMax(ChnSettings[chn].nVolume, uint16(64)); + if(ChnSettings[chn].nPan > 256) + ChnSettings[chn].nPan = 128; + m_PlayState.Chn[chn].Reset(ModChannel::resetTotal, *this, chn, muteFlag); } // Checking samples, load external samples @@ -770,8 +772,9 @@ double CSoundFile::GetCurrentBPM() const void CSoundFile::ResetPlayPos() { + const auto muteFlag = GetChannelMuteFlag(); for(CHANNELINDEX i = 0; i < MAX_CHANNELS; i++) - m_PlayState.Chn[i].Reset(ModChannel::resetSetPosFull, *this, i); + m_PlayState.Chn[i].Reset(ModChannel::resetSetPosFull, *this, i, muteFlag); visitedSongRows.Initialize(true); m_SongFlags.reset(SONG_FADINGSONG | SONG_ENDREACHED); @@ -1055,7 +1058,6 @@ PlayBehaviourSet CSoundFile::GetSupportedPlaybackBehaviour(MODTYPE type) { playBehaviour.set(kOPLFlexibleNoteOff); playBehaviour.set(kOPLwithNNA); - playBehaviour.set(kOPLRealRetrig); } break; @@ -1176,7 +1178,6 @@ PlayBehaviourSet CSoundFile::GetDefaultPlaybackBehaviour(MODTYPE type) playBehaviour.set(kITDoNotOverrideChannelPan); playBehaviour.set(kITDCTBehaviour); playBehaviour.set(kOPLwithNNA); - playBehaviour.set(kOPLRealRetrig); break; case MOD_TYPE_S3M: @@ -1293,10 +1294,11 @@ const char *CSoundFile::GetInstrumentName(INSTRUMENTINDEX nInstr) const bool CSoundFile::InitChannel(CHANNELINDEX nChn) { - if(nChn >= MAX_BASECHANNELS) return true; + if(nChn >= MAX_BASECHANNELS) + return true; ChnSettings[nChn].Reset(); - m_PlayState.Chn[nChn].Reset(ModChannel::resetTotal, *this, nChn); + m_PlayState.Chn[nChn].Reset(ModChannel::resetTotal, *this, nChn, GetChannelMuteFlag()); #ifdef MODPLUG_TRACKER if(GetpModDoc() != nullptr) @@ -1775,6 +1777,16 @@ const CModSpecifications& CSoundFile::GetModSpecifications(const MODTYPE type) } +ChannelFlags CSoundFile::GetChannelMuteFlag() +{ +#ifdef MODPLUG_TRACKER + return (TrackerSettings::Instance().m_dwPatternSetup & PATTERN_SYNCMUTE) ? CHN_SYNCMUTE : CHN_MUTE; +#else + return CHN_MUTE; +#endif +} + + // Find an unused sample slot. If it is going to be assigned to an instrument, targetInstrument should be specified. // SAMPLEINDEX_INVLAID is returned if no free sample slot could be found. SAMPLEINDEX CSoundFile::GetNextFreeSample(INSTRUMENTINDEX targetInstrument, SAMPLEINDEX start) const diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h index 2275401da..b3cf850cd 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h @@ -462,16 +462,17 @@ public: ResamplingMode m_nResampling; // Resampling mode (if overriding the globally set resampling) int32 m_nRepeatCount = 0; // -1 means repeat infinitely. ORDERINDEX m_nMaxOrderPosition; - ModChannelSettings ChnSettings[MAX_BASECHANNELS]; // Initial channels settings + ModChannelSettings ChnSettings[MAX_BASECHANNELS]; // Initial channels settings CPatternContainer Patterns; - ModSequenceSet Order; // Pattern sequences (order lists) + ModSequenceSet Order; // Pattern sequences (order lists) protected: - ModSample Samples[MAX_SAMPLES]; // Sample Headers + ModSample Samples[MAX_SAMPLES]; public: - ModInstrument *Instruments[MAX_INSTRUMENTS]; // Instrument Headers - MIDIMacroConfig m_MidiCfg; // MIDI Macro config table + ModInstrument *Instruments[MAX_INSTRUMENTS]; // Instrument Headers + MIDIMacroConfig m_MidiCfg; // MIDI Macro config table #ifndef NO_PLUGINS - SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS]; // Mix plugins + SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS]; // Mix plugins + uint32 m_loadedPlugins = 0; // Not a PLUGINDEX because number of loaded plugins may exceed MAX_MIXPLUGINS during MIDI conversion #endif mpt::charbuf m_szNames[MAX_SAMPLES]; // Sample names @@ -720,6 +721,8 @@ public: const CModSpecifications& GetModSpecifications() const {return *m_pModSpecs;} static const CModSpecifications& GetModSpecifications(const MODTYPE type); + static ChannelFlags GetChannelMuteFlag(); + #ifdef MODPLUG_TRACKER void PatternTranstionChnSolo(const CHANNELINDEX chnIndex); void PatternTransitionChnUnmuteAll(); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp index 499ff1e98..61be7833c 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp @@ -206,18 +206,6 @@ CSoundFile::samplecount_t CSoundFile::Read(samplecount_t count, IAudioReadTarget { MPT_ASSERT_ALWAYS(m_MixerSettings.IsValid()); - bool mixPlugins = false; -#ifndef NO_PLUGINS - for(const auto &plug : m_MixPlugins) - { - if(plug.pMixPlugin) - { - mixPlugins = true; - break; - } - } -#endif // NO_PLUGINS - samplecount_t countRendered = 0; samplecount_t countToRender = count; @@ -303,14 +291,16 @@ CSoundFile::samplecount_t CSoundFile::Read(samplecount_t count, IAudioReadTarget m_opl->Mix(MixSoundBuffer, countChunk, m_OPLVolumeFactor * m_nVSTiVolume / 48); } - #ifndef NO_REVERB - m_Reverb.Process(MixSoundBuffer, countChunk); - #endif // NO_REVERB +#ifndef NO_REVERB + m_Reverb.Process(MixSoundBuffer, countChunk); +#endif // NO_REVERB - if(mixPlugins) +#ifndef NO_PLUGINS + if(m_loadedPlugins) { ProcessPlugins(countChunk); } +#endif // NO_PLUGINS if(m_MixerSettings.gnChannels == 1) { @@ -653,8 +643,9 @@ bool CSoundFile::ProcessRow() visitedSongRows.Initialize(true); } // When jumping to the next subsong, stop all playing notes from the previous song... + const auto muteFlag = CSoundFile::GetChannelMuteFlag(); for(CHANNELINDEX i = 0; i < MAX_CHANNELS; i++) - m_PlayState.Chn[i].Reset(ModChannel::resetSetPosFull, *this, i); + m_PlayState.Chn[i].Reset(ModChannel::resetSetPosFull, *this, i, muteFlag); StopAllVsti(); // ...and the global playback information. m_PlayState.m_nMusicSpeed = m_nDefaultSpeed; @@ -2348,7 +2339,7 @@ bool CSoundFile::ReadNote() } // Volume ramping - chn.dwFlags.set(CHN_VOLUMERAMP, (chn.nRealVolume | chn.rightVol | chn.leftVol) != 0); + chn.dwFlags.set(CHN_VOLUMERAMP, (chn.nRealVolume | chn.rightVol | chn.leftVol) != 0 && !chn.dwFlags[CHN_ADLIB]); constexpr uint8 VUMETER_DECAY = 4; chn.nLeftVU = (chn.nLeftVU > VUMETER_DECAY) ? (chn.nLeftVU - VUMETER_DECAY) : 0; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp index 527abc700..ef46acb5b 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp @@ -656,13 +656,18 @@ void CSoundFile::UpgradeModule() } } - if(GetType() == MOD_TYPE_MPT && GetNumInstruments() && m_dwLastSavedWithVersion >= MPT_V("1.28.00.20") && m_dwLastSavedWithVersion <= MPT_V("1.29.55.00")) + if(GetType() & (MOD_TYPE_MPT | MOD_TYPE_S3M)) { for(SAMPLEINDEX i = 1; i <= GetNumSamples(); i++) { if(Samples[i].uFlags[CHN_ADLIB]) { - m_playBehaviour.set(kOPLNoResetAtEnvelopeEnd); + if(GetType() == MOD_TYPE_MPT && GetNumInstruments() && m_dwLastSavedWithVersion >= MPT_V("1.28.00.20") && m_dwLastSavedWithVersion <= MPT_V("1.29.00.55")) + m_playBehaviour.set(kOPLNoResetAtEnvelopeEnd); + if(GetType() == MOD_TYPE_S3M && m_dwLastSavedWithVersion < MPT_V("1.29")) + m_playBehaviour.set(kOPLRealRetrig); + else if(GetType() != MOD_TYPE_S3M) + m_playBehaviour.reset(kOPLRealRetrig); break; } } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/XMTools.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/XMTools.cpp index eb799bd04..5cddbad8c 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/XMTools.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/XMTools.cpp @@ -330,9 +330,7 @@ void XMSample::ConvertToXM(const ModSample &mptSmp, MODTYPE fromType, bool compa relnote = mptSmp.RelativeTone; } else { - int f2t = ModSample::FrequencyToTranspose(mptSmp.nC5Speed); - relnote = static_cast(f2t / 128); - finetune = static_cast(f2t & 0x7F); + std::tie(relnote, finetune) = ModSample::FrequencyToTranspose(mptSmp.nC5Speed); } flags = 0; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp index d8e3a390b..97b817884 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PlugInterface.cpp @@ -44,6 +44,7 @@ IMixPlugin::IMixPlugin(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN , m_SndFile(sndFile) , m_pMixStruct(mixStruct) { + m_SndFile.m_loadedPlugins++; m_MixState.pMixBuffer = (mixsample_t *)((((intptr_t)m_MixBuffer) + 7) & ~7); while(m_pMixStruct != &(m_SndFile.m_MixPlugins[m_nSlot]) && m_nSlot < MAX_MIXPLUGINS - 1) { @@ -71,6 +72,7 @@ IMixPlugin::~IMixPlugin() if (m_pPrev) m_pPrev->m_pNext = m_pNext; m_pPrev = nullptr; m_pNext = nullptr; + m_SndFile.m_loadedPlugins--; } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginManager.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginManager.cpp index ad515561e..5167c01d4 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginManager.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginManager.cpp @@ -392,9 +392,7 @@ void CVstPluginManager::EnumerateDirectXDMOs() if(ERROR_SUCCESS == RegQueryValueEx(hksub, nullptr, 0, &datatype, (LPBYTE)name, &datasize)) { - mpt::String::SetNullTerminator(name); - - VSTPluginLib *plug = new (std::nothrow) VSTPluginLib(DMOPlugin::Create, true, mpt::PathString::FromNative(Util::GUIDToString(clsid)), mpt::PathString::FromNative(name)); + VSTPluginLib *plug = new (std::nothrow) VSTPluginLib(DMOPlugin::Create, true, mpt::PathString::FromNative(Util::GUIDToString(clsid)), mpt::PathString::FromNative(ParseMaybeNullTerminatedStringFromBufferWithSizeInBytes(name, datasize))); if(plug != nullptr) { try diff --git a/Frameworks/OpenMPT/OpenMPT/test/test.cpp b/Frameworks/OpenMPT/OpenMPT/test/test.cpp index f7014d89b..bc92fdb51 100644 --- a/Frameworks/OpenMPT/OpenMPT/test/test.cpp +++ b/Frameworks/OpenMPT/OpenMPT/test/test.cpp @@ -3607,7 +3607,7 @@ static void TestLoadS3MFile(const CSoundFile &sndFile, bool resaved) VERIFY_EQUAL_NONCONT((sndFile.m_SongFlags & SONG_FILE_FLAGS), SONG_FASTVOLSLIDES); VERIFY_EQUAL_NONCONT(sndFile.GetMixLevels(), mixLevelsCompatible); VERIFY_EQUAL_NONCONT(sndFile.m_nTempoMode, tempoModeClassic); - VERIFY_EQUAL_NONCONT(sndFile.m_dwLastSavedWithVersion, resaved ? Version(Version::Current().GetRawVersion() & 0xFFFF0000u) : MPT_V("1.27.00.00")); + VERIFY_EQUAL_NONCONT(sndFile.m_dwLastSavedWithVersion, resaved ? Version::Current() : MPT_V("1.27.00.00")); VERIFY_EQUAL_NONCONT(sndFile.Order().GetRestartPos(), 0); // Channels