libOpenMPT Legacy: Updated to version 0.5.16
Signed-off-by: Christopher Snowhill <kode54@gmail.com>CQTexperiment
parent
9e42182928
commit
ebb9c5b4f1
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2004-2021, OpenMPT contributors
|
||||
Copyright (c) 2004-2022, OpenMPT contributors
|
||||
Copyright (c) 1997-2003, Olivier Lapicque
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
# LOCAL_OGG=1 Build local copy of libogg, even if found
|
||||
# LOCAL_VORBIS=1 Build local copy of libvorbis, even if found
|
||||
#
|
||||
# NO_MINIZ=1 Do not fallback to miniz
|
||||
# NO_MINIMP3=1 Do not fallback to minimp3
|
||||
# NO_STBVORBIS=1 Do not fallback to stb_vorbis
|
||||
#
|
||||
|
@ -867,11 +868,14 @@ LIBOPENMPT_C_SOURCES += $(LOCAL_ZLIB_SOURCES)
|
|||
LIBOPENMPTTEST_C_SOURCES += $(LOCAL_ZLIB_SOURCES)
|
||||
else
|
||||
ifeq ($(NO_ZLIB),1)
|
||||
ifeq ($(NO_MINIZ),1)
|
||||
else
|
||||
LIBOPENMPT_C_SOURCES += include/miniz/miniz.c
|
||||
LIBOPENMPTTEST_C_SOURCES += include/miniz/miniz.c
|
||||
CPPFLAGS += -DMPT_WITH_MINIZ
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
include/minimp3/minimp3.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||
include/minimp3/minimp3.test.o : CFLAGS+=$(CFLAGS_SILENT)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
MPT_SVNVERSION=16119
|
||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.14
|
||||
MPT_SVNDATE=2021-12-05T14:17:40.071493Z
|
||||
MPT_SVNVERSION=16768
|
||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.16
|
||||
MPT_SVNDATE=2022-01-30T16:50:10.915999Z
|
||||
|
|
|
@ -40,11 +40,10 @@ LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
|||
|
||||
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 +=
|
||||
CFLAGS +=
|
||||
LDFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1
|
||||
LDFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1 -Wno-transpile
|
||||
|
||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||
|
||||
|
@ -71,7 +70,7 @@ else ifeq ($(EMSCRIPTEN_TARGET),js)
|
|||
CPPFLAGS += -DMPT_BUILD_ASMJS
|
||||
CXXFLAGS +=
|
||||
CFLAGS +=
|
||||
LDFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1
|
||||
LDFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1 -Wno-transpile
|
||||
|
||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
#pragma once
|
||||
#define OPENMPT_VERSION_SVNVERSION "16119"
|
||||
#define OPENMPT_VERSION_REVISION 16119
|
||||
#define OPENMPT_VERSION_SVNVERSION "16768"
|
||||
#define OPENMPT_VERSION_REVISION 16768
|
||||
#define OPENMPT_VERSION_DIRTY 0
|
||||
#define OPENMPT_VERSION_MIXEDREVISIONS 0
|
||||
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.14"
|
||||
#define OPENMPT_VERSION_DATE "2021-12-05T14:17:40.071493Z"
|
||||
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.16"
|
||||
#define OPENMPT_VERSION_DATE "2022-01-30T16:50:10.915999Z"
|
||||
#define OPENMPT_VERSION_IS_PACKAGE 1
|
||||
|
||||
|
|
|
@ -418,6 +418,30 @@ inline T ExponentialGrow(const T &x)
|
|||
} //namespace Util
|
||||
|
||||
|
||||
namespace mpt
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
inline T sanitize_nan(T val)
|
||||
{
|
||||
static_assert(std::is_floating_point<T>::value);
|
||||
if(std::isnan(val))
|
||||
{
|
||||
return T(0.0);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T safe_clamp(T v, T lo, T hi)
|
||||
{
|
||||
static_assert(std::is_floating_point<T>::value);
|
||||
return std::clamp(mpt::sanitize_nan(v), lo, hi);
|
||||
}
|
||||
|
||||
} // namespace mpt
|
||||
|
||||
|
||||
// Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'.
|
||||
// Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'.
|
||||
// If 'lowerLimit' > 'upperLimit', 'val' won't be modified.
|
||||
|
|
|
@ -565,12 +565,12 @@ mpt::ustring GetFullCreditsString()
|
|||
"libopenmpt (based on OpenMPT / ModPlug Tracker)\n"
|
||||
#endif
|
||||
"\n"
|
||||
"Copyright \xC2\xA9 2004-2021 Contributors\n"
|
||||
"Copyright \xC2\xA9 2004-2022 Contributors\n"
|
||||
"Copyright \xC2\xA9 1997-2003 Olivier Lapicque\n"
|
||||
"\n"
|
||||
"Contributors:\n"
|
||||
"Johannes Schultz (2008-2021)\n"
|
||||
"J\xC3\xB6rn Heusipp (2012-2021)\n"
|
||||
"Johannes Schultz (2008-2022)\n"
|
||||
"J\xC3\xB6rn Heusipp (2012-2022)\n"
|
||||
"Ahti Lepp\xC3\xA4nen (2005-2011)\n"
|
||||
"Robin Fernandes (2004-2007)\n"
|
||||
"Sergiy Pylypenko (2007)\n"
|
||||
|
@ -760,7 +760,7 @@ mpt::ustring GetFullCreditsString()
|
|||
mpt::ustring GetLicenseString()
|
||||
{
|
||||
return MPT_UTF8(
|
||||
"Copyright (c) 2004-2021, OpenMPT contributors" "\n"
|
||||
"Copyright (c) 2004-2022, OpenMPT contributors" "\n"
|
||||
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
||||
"All rights reserved." "\n"
|
||||
"" "\n"
|
||||
|
|
|
@ -18,6 +18,6 @@ OPENMPT_NAMESPACE_BEGIN
|
|||
#define VER_MAJORMAJOR 1
|
||||
#define VER_MAJOR 29
|
||||
#define VER_MINOR 15
|
||||
#define VER_MINORMINOR 00
|
||||
#define VER_MINORMINOR 04
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2004-2021, OpenMPT contributors
|
||||
Copyright (c) 2004-2022, OpenMPT contributors
|
||||
Copyright (c) 1997-2003, Olivier Lapicque
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2004-2021, OpenMPT contributors
|
||||
Copyright (c) 2004-2022, OpenMPT contributors
|
||||
Copyright (c) 1997-2003, Olivier Lapicque
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
@ -5,6 +5,39 @@ Changelog {#changelog}
|
|||
For fully detailed change log, please see the source repository directly. This
|
||||
is just a high-level summary.
|
||||
|
||||
### libopenmpt 0.5.16 (2022-01-30)
|
||||
|
||||
* [**Bug**] Possible hang with malformed DMF, DSM, MED and OKT files
|
||||
containing 65536 or more patterns when destroying the module.
|
||||
* [**Bug**] Avoid NaNs and infinite values with custom tunings.
|
||||
|
||||
* The letter "z" is now evaluated in fixed MIDI macros (Z80...ZFF) the same
|
||||
way as in Impulse Tracker.
|
||||
* MOD: Loosened VBlank timing heuristics so that "frame of mind" by Dascon
|
||||
plays correctly.
|
||||
* MOD: Validate the contents of "hidden" patterns beyond the end of the order
|
||||
list when the file size matches the expected size when only taken "official"
|
||||
patterns into account. This fixes Shofixti Ditty.mod from Star Control 2
|
||||
while keeping other (partly broken) modules working.
|
||||
* MED: Command 20 (reverse sample) is now only applied when it's next to a
|
||||
note.
|
||||
|
||||
### libopenmpt 0.5.15 (2021-12-23)
|
||||
|
||||
* [**Sec**] Possible out-of-bounds read of stack-allocated array in malformed
|
||||
AMS files. (r16243)
|
||||
|
||||
* [**Bug**] Fixed various undefined behaviour found with ubsan.
|
||||
|
||||
* IT: Even after libopenmpt 0.5.14 the filter reset logic was still not 100%
|
||||
identical to Impulse Tracker: A note triggered on tick 0 of a row with a
|
||||
Pattern Delay effect still caused the filter to be reset on repetitions of
|
||||
that row even though the note wasn't retriggered.
|
||||
* MOD: Loosened VBlank timing heuristics so that the original copy of
|
||||
Guitar Slinger from Dizzy Tunes II plays correctly.
|
||||
|
||||
* mpg123: Update to v1.29.3 (2021-12-11).
|
||||
|
||||
### libopenmpt 0.5.14 (2021-12-05)
|
||||
|
||||
* [**Sec**] Possible out-of-bounds read in Chorus plugin with NaN plugin
|
||||
|
|
|
@ -214,7 +214,7 @@ static void config( HWND hwndParent ) {
|
|||
static void about( HWND hwndParent ) {
|
||||
std::ostringstream about;
|
||||
about << SHORT_TITLE << " version " << openmpt::string::get( "library_version" ) << " " << "(built " << openmpt::string::get( "build" ) << ")" << std::endl;
|
||||
about << " Copyright (c) 2013-2021 OpenMPT developers (https://lib.openmpt.org/)" << std::endl;
|
||||
about << " Copyright (c) 2013-2022 OpenMPT developers (https://lib.openmpt.org/)" << std::endl;
|
||||
about << " OpenMPT version " << openmpt::string::get( "core_version" ) << std::endl;
|
||||
about << std::endl;
|
||||
about << openmpt::string::get( "contact" ) << std::endl;
|
||||
|
|
|
@ -159,6 +159,8 @@ LIBOPENMPT_DEPRECATED static const int LIBOPENMPT_DEPRECATED_STRING_CONSTANT = 0
|
|||
#else
|
||||
#define LIBOPENMPT_DEPRECATED_STRING( str ) str
|
||||
#endif
|
||||
#else
|
||||
#define LIBOPENMPT_DEPRECATED_STRING( str ) str
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -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 14
|
||||
#define OPENMPT_API_VERSION_PATCH 16
|
||||
/*! \brief libopenmpt pre-release tag */
|
||||
#define OPENMPT_API_VERSION_PREREL ""
|
||||
/*! \brief libopenmpt pre-release flag */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
LIBOPENMPT_VERSION_MAJOR=0
|
||||
LIBOPENMPT_VERSION_MINOR=5
|
||||
LIBOPENMPT_VERSION_PATCH=14
|
||||
LIBOPENMPT_VERSION_PATCH=16
|
||||
LIBOPENMPT_VERSION_PREREL=
|
||||
|
||||
LIBOPENMPT_LTVER_CURRENT=2
|
||||
LIBOPENMPT_LTVER_REVISION=14
|
||||
LIBOPENMPT_LTVER_REVISION=16
|
||||
LIBOPENMPT_LTVER_AGE=2
|
||||
|
|
|
@ -192,7 +192,7 @@ BEGIN
|
|||
VALUE "FileDescription", VER_FILEDESC_STR
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", VER_FILENAME_STR
|
||||
VALUE "LegalCopyright", "Copyright © 2004-2020 OpenMPT contributors, Copyright © 1997-2003 Olivier Lapicque"
|
||||
VALUE "LegalCopyright", "Copyright © 2004-2022 OpenMPT contributors, Copyright © 1997-2003 Olivier Lapicque"
|
||||
VALUE "OriginalFilename", VER_FILENAME_STR
|
||||
VALUE "ProductName", "libopenmpt"
|
||||
VALUE "ProductVersion", VER_FILEVERSION_STR
|
||||
|
|
|
@ -468,7 +468,7 @@ static void clear_current_timeinfo() {
|
|||
static void WINAPI openmpt_About( HWND win ) {
|
||||
std::ostringstream about;
|
||||
about << SHORT_TITLE << " version " << openmpt::string::get( "library_version" ) << " " << "(built " << openmpt::string::get( "build" ) << ")" << std::endl;
|
||||
about << " Copyright (c) 2013-2021 OpenMPT developers (https://lib.openmpt.org/)" << std::endl;
|
||||
about << " Copyright (c) 2013-2022 OpenMPT developers (https://lib.openmpt.org/)" << std::endl;
|
||||
about << " OpenMPT version " << openmpt::string::get( "core_version" ) << std::endl;
|
||||
about << std::endl;
|
||||
about << openmpt::string::get( "contact" ) << std::endl;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
|
||||
static const char * const license =
|
||||
"Copyright (c) 2004-2021, OpenMPT contributors" "\n"
|
||||
"Copyright (c) 2004-2022, OpenMPT contributors" "\n"
|
||||
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
||||
"All rights reserved." "\n"
|
||||
"" "\n"
|
||||
|
@ -461,7 +461,7 @@ static std::string seconds_to_string( double time ) {
|
|||
|
||||
static void show_info( std::ostream & log, bool verbose ) {
|
||||
log << "openmpt123" << " v" << OPENMPT123_VERSION_STRING << ", libopenmpt " << openmpt::string::get( "library_version" ) << " (" << "OpenMPT " << openmpt::string::get( "core_version" ) << ")" << std::endl;
|
||||
log << "Copyright (c) 2013-2021 OpenMPT developers <https://lib.openmpt.org/>" << std::endl;
|
||||
log << "Copyright (c) 2013-2022 OpenMPT developers <https://lib.openmpt.org/>" << std::endl;
|
||||
if ( !verbose ) {
|
||||
log << std::endl;
|
||||
return;
|
||||
|
@ -538,7 +538,7 @@ static void show_info( std::ostream & log, bool verbose ) {
|
|||
static void show_man_version( textout & log ) {
|
||||
log << "openmpt123" << " v" << OPENMPT123_VERSION_STRING << std::endl;
|
||||
log << std::endl;
|
||||
log << "Copyright (c) 2013-2021 OpenMPT developers <https://lib.openmpt.org/>" << std::endl;
|
||||
log << "Copyright (c) 2013-2022 OpenMPT developers <https://lib.openmpt.org/>" << std::endl;
|
||||
}
|
||||
|
||||
static void show_short_version( textout & log ) {
|
||||
|
|
|
@ -213,7 +213,19 @@ struct DecodeFloat32
|
|||
static constexpr std::size_t input_inc = 4;
|
||||
MPT_FORCEINLINE output_t operator() (const input_t *inBuf)
|
||||
{
|
||||
return IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
|
||||
float32 val = IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
|
||||
val = mpt::sanitize_nan(val);
|
||||
if(std::isinf(val))
|
||||
{
|
||||
if(val >= 0.0f)
|
||||
{
|
||||
val = 1.0f;
|
||||
} else
|
||||
{
|
||||
val = -1.0f;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -226,7 +238,20 @@ struct DecodeScaledFloat32
|
|||
float factor;
|
||||
MPT_FORCEINLINE output_t operator() (const input_t *inBuf)
|
||||
{
|
||||
return factor * IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
|
||||
float32 val = IEEE754binary32LE(inBuf[loLoByteIndex], inBuf[loHiByteIndex], inBuf[hiLoByteIndex], inBuf[hiHiByteIndex]);
|
||||
val = mpt::sanitize_nan(val);
|
||||
if(std::isinf(val))
|
||||
{
|
||||
if(val >= 0.0f)
|
||||
{
|
||||
val = 1.0f;
|
||||
} else
|
||||
{
|
||||
val = -1.0f;
|
||||
}
|
||||
}
|
||||
return factor * val;
|
||||
|
||||
}
|
||||
MPT_FORCEINLINE DecodeScaledFloat32(float scaleFactor)
|
||||
: factor(scaleFactor)
|
||||
|
@ -243,7 +268,19 @@ struct DecodeFloat64
|
|||
static constexpr std::size_t input_inc = 8;
|
||||
MPT_FORCEINLINE output_t operator() (const input_t *inBuf)
|
||||
{
|
||||
return IEEE754binary64LE(inBuf[b0], inBuf[b1], inBuf[b2], inBuf[b3], inBuf[b4], inBuf[b5], inBuf[b6], inBuf[b7]);
|
||||
float64 val = IEEE754binary64LE(inBuf[b0], inBuf[b1], inBuf[b2], inBuf[b3], inBuf[b4], inBuf[b5], inBuf[b6], inBuf[b7]);
|
||||
val = mpt::sanitize_nan(val);
|
||||
if(std::isinf(val))
|
||||
{
|
||||
if(val >= 0.0)
|
||||
{
|
||||
val = 1.0;
|
||||
} else
|
||||
{
|
||||
val = -1.0;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -371,7 +408,7 @@ struct Convert<uint8, float32>
|
|||
typedef uint8 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0f, 1.0f);
|
||||
val = mpt::safe_clamp(val, -1.0f, 1.0f);
|
||||
val *= 128.0f;
|
||||
return static_cast<uint8>(mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)))+0x80);
|
||||
}
|
||||
|
@ -384,7 +421,7 @@ struct Convert<uint8, double>
|
|||
typedef uint8 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0, 1.0);
|
||||
val = mpt::safe_clamp(val, -1.0, 1.0);
|
||||
val *= 128.0;
|
||||
return static_cast<uint8>(mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)))+0x80);
|
||||
}
|
||||
|
@ -452,7 +489,7 @@ struct Convert<int8, float32>
|
|||
typedef int8 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0f, 1.0f);
|
||||
val = mpt::safe_clamp(val, -1.0f, 1.0f);
|
||||
val *= 128.0f;
|
||||
return mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)));
|
||||
}
|
||||
|
@ -465,7 +502,7 @@ struct Convert<int8, double>
|
|||
typedef int8 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0, 1.0);
|
||||
val = mpt::safe_clamp(val, -1.0, 1.0);
|
||||
val *= 128.0;
|
||||
return mpt::saturate_cast<int8>(static_cast<int>(MPT_SC_FASTROUND(val)));
|
||||
}
|
||||
|
@ -533,7 +570,7 @@ struct Convert<int16, float32>
|
|||
typedef int16 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0f, 1.0f);
|
||||
val = mpt::safe_clamp(val, -1.0f, 1.0f);
|
||||
val *= 32768.0f;
|
||||
return mpt::saturate_cast<int16>(static_cast<int>(MPT_SC_FASTROUND(val)));
|
||||
}
|
||||
|
@ -546,7 +583,7 @@ struct Convert<int16, double>
|
|||
typedef int16 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0, 1.0);
|
||||
val = mpt::safe_clamp(val, -1.0, 1.0);
|
||||
val *= 32768.0;
|
||||
return mpt::saturate_cast<int16>(static_cast<int>(MPT_SC_FASTROUND(val)));
|
||||
}
|
||||
|
@ -614,7 +651,7 @@ struct Convert<int24, float32>
|
|||
typedef int24 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0f, 1.0f);
|
||||
val = mpt::safe_clamp(val, -1.0f, 1.0f);
|
||||
val *= 2147483648.0f;
|
||||
return static_cast<int24>(MPT_SC_RSHIFT_SIGNED(mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val))), 8));
|
||||
}
|
||||
|
@ -627,7 +664,7 @@ struct Convert<int24, double>
|
|||
typedef int24 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0, 1.0);
|
||||
val = mpt::safe_clamp(val, -1.0, 1.0);
|
||||
val *= 2147483648.0;
|
||||
return static_cast<int24>(MPT_SC_RSHIFT_SIGNED(mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val))), 8));
|
||||
}
|
||||
|
@ -695,7 +732,7 @@ struct Convert<int32, float32>
|
|||
typedef int32 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0f, 1.0f);
|
||||
val = mpt::safe_clamp(val, -1.0f, 1.0f);
|
||||
val *= 2147483648.0f;
|
||||
return mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val)));
|
||||
}
|
||||
|
@ -708,7 +745,7 @@ struct Convert<int32, double>
|
|||
typedef int32 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0, 1.0);
|
||||
val = mpt::safe_clamp(val, -1.0, 1.0);
|
||||
val *= 2147483648.0;
|
||||
return mpt::saturate_cast<int32>(static_cast<int64>(MPT_SC_FASTROUND(val)));
|
||||
}
|
||||
|
@ -776,7 +813,7 @@ struct Convert<int64, float32>
|
|||
typedef int64 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0f, 1.0f);
|
||||
val = mpt::safe_clamp(val, -1.0f, 1.0f);
|
||||
val *= static_cast<float>(uint64(1)<<63);
|
||||
return mpt::saturate_cast<int64>(MPT_SC_FASTROUND(val));
|
||||
}
|
||||
|
@ -789,7 +826,7 @@ struct Convert<int64, double>
|
|||
typedef int64 output_t;
|
||||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
Limit(val, -1.0, 1.0);
|
||||
val = mpt::safe_clamp(val, -1.0, 1.0);
|
||||
val *= static_cast<double>(uint64(1)<<63);
|
||||
return mpt::saturate_cast<int64>(MPT_SC_FASTROUND(val));
|
||||
}
|
||||
|
@ -1155,6 +1192,7 @@ struct ConvertToFixedPoint<int32, float32, fractionalBits>
|
|||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
|
||||
val = mpt::sanitize_nan(val);
|
||||
return mpt::saturate_cast<output_t>(MPT_SC_FASTROUND(val * factor));
|
||||
}
|
||||
};
|
||||
|
@ -1173,6 +1211,7 @@ struct ConvertToFixedPoint<int32, float64, fractionalBits>
|
|||
MPT_FORCEINLINE output_t operator() (input_t val)
|
||||
{
|
||||
static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t)*8-1);
|
||||
val = mpt::sanitize_nan(val);
|
||||
return mpt::saturate_cast<output_t>(MPT_SC_FASTROUND(val * factor));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -58,7 +58,7 @@ struct XPK_BufferBounds
|
|||
|
||||
static int32 bfextu(std::size_t p, int32 bo, int32 bc, XPK_BufferBounds &bufs)
|
||||
{
|
||||
int32 r;
|
||||
uint32 r;
|
||||
|
||||
p += bo / 8;
|
||||
r = bufs.SrcRead(p); p++;
|
||||
|
@ -75,7 +75,7 @@ static int32 bfextu(std::size_t p, int32 bo, int32 bc, XPK_BufferBounds &bufs)
|
|||
|
||||
static int32 bfexts(std::size_t p, int32 bo, int32 bc, XPK_BufferBounds &bufs)
|
||||
{
|
||||
int32 r;
|
||||
uint32 r;
|
||||
|
||||
p += bo / 8;
|
||||
r = bufs.SrcRead(p); p++;
|
||||
|
@ -84,9 +84,7 @@ static int32 bfexts(std::size_t p, int32 bo, int32 bc, XPK_BufferBounds &bufs)
|
|||
r <<= 8;
|
||||
r |= bufs.SrcRead(p);
|
||||
r <<= (bo % 8) + 8;
|
||||
r >>= 32 - bc;
|
||||
|
||||
return r;
|
||||
return mpt::rshift_signed(static_cast<int32>(r), 32 - bc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -438,14 +438,14 @@ bool CSoundFile::ReadAMS(FileReader &file, ModLoadingFlags loadFlags)
|
|||
file.ReadSizedString<uint8le, mpt::String::spacePadded>(ChnSettings[chn].szName);
|
||||
}
|
||||
|
||||
// Read pattern names
|
||||
// Read pattern names and create patterns
|
||||
Patterns.ResizeArray(fileHeader.numPats);
|
||||
for(PATTERNINDEX pat = 0; pat < fileHeader.numPats; pat++)
|
||||
{
|
||||
char name[11];
|
||||
file.ReadSizedString<uint8le, mpt::String::spacePadded>(name);
|
||||
const bool ok = file.ReadSizedString<uint8le, mpt::String::spacePadded>(name);
|
||||
// Create pattern now, so name won't be reset later.
|
||||
if(Patterns.Insert(pat, 64))
|
||||
if(Patterns.Insert(pat, 64) && ok)
|
||||
{
|
||||
Patterns[pat].SetName(name);
|
||||
}
|
||||
|
@ -973,7 +973,7 @@ bool CSoundFile::ReadAMS2(FileReader &file, ModLoadingFlags loadFlags)
|
|||
}
|
||||
|
||||
char patternName[11];
|
||||
patternChunk.ReadSizedString<uint8le, mpt::String::spacePadded>(patternName);
|
||||
if(patternChunk.ReadSizedString<uint8le, mpt::String::spacePadded>(patternName))
|
||||
Patterns[pat].SetName(patternName);
|
||||
|
||||
ReadAMSPattern(Patterns[pat], true, patternChunk);
|
||||
|
|
|
@ -542,9 +542,12 @@ static void ConvertMEDEffect(ModCommand &m, bool is8ch, bool bpmMode, uint8 rows
|
|||
}
|
||||
case 0x20: // Reverse sample + skip samples
|
||||
if(m.param == 0 && m.vol == 0)
|
||||
{
|
||||
if(m.IsNote())
|
||||
{
|
||||
m.command = CMD_S3MCMDEX;
|
||||
m.param = 0x9F;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// Skip given number of samples
|
||||
|
|
|
@ -279,7 +279,7 @@ struct MO3Sample
|
|||
smpCompressionMask = 0x1000 | 0x2000 | 0x4000 | 0x8000
|
||||
};
|
||||
|
||||
int32le freqFinetune; // Frequency in S3M and IT, finetune (0...255) in MOD, MTM, XM
|
||||
uint32le freqFinetune; // Frequency in S3M and IT, finetune (0...255) in MOD, MTM, XM
|
||||
int8le transpose;
|
||||
uint8le defaultVolume; // 0...64
|
||||
uint16le panning; // 0...256 if enabled, 0xFFFF otherwise
|
||||
|
@ -304,9 +304,9 @@ struct MO3Sample
|
|||
if(type & (MOD_TYPE_IT | MOD_TYPE_S3M))
|
||||
{
|
||||
if(frequencyIsHertz)
|
||||
mptSmp.nC5Speed = static_cast<uint32>(freqFinetune);
|
||||
mptSmp.nC5Speed = freqFinetune;
|
||||
else
|
||||
mptSmp.nC5Speed = mpt::saturate_round<uint32>(8363.0 * std::pow(2.0, (freqFinetune + 1408) / 1536.0));
|
||||
mptSmp.nC5Speed = mpt::saturate_round<uint32>(8363.0 * std::pow(2.0, static_cast<int32>(freqFinetune + 1408) / 1536.0));
|
||||
} else
|
||||
{
|
||||
mptSmp.nFineTune = static_cast<int8>(freqFinetune);
|
||||
|
@ -394,7 +394,7 @@ struct MO3SampleChunk
|
|||
do \
|
||||
{ \
|
||||
READ_CTRL_BIT; \
|
||||
strLen = (strLen << 1) + carry; \
|
||||
strLen = mpt::lshift_signed(strLen, 1) + carry; \
|
||||
READ_CTRL_BIT; \
|
||||
} while(carry); \
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ static bool UnpackMO3Data(FileReader &file, std::vector<uint8> &uncompressed, co
|
|||
{
|
||||
// LZ ptr in ctrl stream
|
||||
if(uint8 b; file.Read(b))
|
||||
strOffset = (strLen << 8) | b; // read less significant offset byte from stream
|
||||
strOffset = mpt::lshift_signed(strLen, 8) | b; // read less significant offset byte from stream
|
||||
else
|
||||
break;
|
||||
strLen = 0;
|
||||
|
@ -456,9 +456,9 @@ static bool UnpackMO3Data(FileReader &file, std::vector<uint8> &uncompressed, co
|
|||
|
||||
// read the next 2 bits as part of strLen
|
||||
READ_CTRL_BIT;
|
||||
strLen = (strLen << 1) + carry;
|
||||
strLen = mpt::lshift_signed(strLen, 1) + carry;
|
||||
READ_CTRL_BIT;
|
||||
strLen = (strLen << 1) + carry;
|
||||
strLen = mpt::lshift_signed(strLen, 1) + carry;
|
||||
if(strLen == 0)
|
||||
{
|
||||
// length does not fit in 2 bits
|
||||
|
|
|
@ -63,11 +63,11 @@ void CSoundFile::ConvertModCommand(ModCommand &m)
|
|||
case 'T' - 55: m.command = CMD_TREMOR; break;
|
||||
case 'W' - 55: m.command = CMD_DUMMY; break;
|
||||
case 'X' - 55: m.command = CMD_XFINEPORTAUPDOWN; break;
|
||||
case 'Y' - 55: m.command = CMD_PANBRELLO; break; //34
|
||||
case 'Z' - 55: m.command = CMD_MIDI; break; //35
|
||||
case '\\' - 56: m.command = CMD_SMOOTHMIDI; break; //rewbs.smoothVST: 36 - note: this is actually displayed as "-" in FT2, but seems to be doing nothing.
|
||||
//case ':' - 21: m.command = CMD_DELAYCUT; break; //37
|
||||
case '#' + 3: m.command = CMD_XPARAM; break; //rewbs.XMfixes - Xm.param is 38
|
||||
case 'Y' - 55: m.command = CMD_PANBRELLO; break; // 34
|
||||
case 'Z' - 55: m.command = CMD_MIDI; break; // 35
|
||||
case '\\' - 56: m.command = CMD_SMOOTHMIDI; break; // 36 - note: this is actually displayed as "-" in FT2, but seems to be doing nothing.
|
||||
case 37: m.command = CMD_SMOOTHMIDI; break; // BeRoTracker uses this for smooth MIDI macros for some reason; in old OpenMPT versions this was reserved for the unimplemented "velocity" command
|
||||
case '#' + 3: m.command = CMD_XPARAM; break; // 38
|
||||
default: m.command = CMD_NONE;
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ void CSoundFile::ModSaveCommand(uint8 &command, uint8 ¶m, bool toXM, bool co
|
|||
struct MODFileHeader
|
||||
{
|
||||
uint8be numOrders;
|
||||
uint8be restartPos;
|
||||
uint8be restartPos; // Tempo (early SoundTracker) or restart position (only PC trackers?)
|
||||
uint8be orderList[128];
|
||||
};
|
||||
|
||||
|
@ -582,6 +582,7 @@ static PATTERNINDEX GetNumPatterns(FileReader &file, ModSequence &Order, ORDERIN
|
|||
|
||||
const size_t patternStartOffset = file.GetPosition();
|
||||
const size_t sizeWithoutPatterns = totalSampleLen + patternStartOffset;
|
||||
const size_t sizeWithOfficialPatterns = sizeWithoutPatterns + officialPatterns * numChannels * 256;
|
||||
|
||||
if(wowSampleLen && (wowSampleLen + patternStartOffset) + numPatterns * 8 * 256 == (file.GetLength() & ~1))
|
||||
{
|
||||
|
@ -592,8 +593,9 @@ static PATTERNINDEX GetNumPatterns(FileReader &file, ModSequence &Order, ORDERIN
|
|||
if(ValidateMODPatternData(file, 16, true))
|
||||
numChannels = 8;
|
||||
file.Seek(patternStartOffset);
|
||||
} else if(numPatterns != officialPatterns && validateHiddenPatterns)
|
||||
} else if(numPatterns != officialPatterns && (validateHiddenPatterns || sizeWithOfficialPatterns == file.GetLength()))
|
||||
{
|
||||
// 15-sample SoundTracker specifics:
|
||||
// Fix SoundTracker modules where "hidden" patterns should be ignored.
|
||||
// razor-1911.mod (MD5 b75f0f471b0ae400185585ca05bf7fe8, SHA1 4de31af234229faec00f1e85e1e8f78f405d454b)
|
||||
// and captain_fizz.mod (MD5 55bd89fe5a8e345df65438dbfc2df94e, SHA1 9e0e8b7dc67939885435ea8d3ff4be7704207a43)
|
||||
|
@ -606,28 +608,21 @@ static PATTERNINDEX GetNumPatterns(FileReader &file, ModSequence &Order, ORDERIN
|
|||
// only play correctly if we ignore the hidden patterns.
|
||||
// Hence, we have a peek at the first hidden pattern and check if it contains a lot of illegal data.
|
||||
// If that is the case, we assume it's part of the sample data and only consider the "official" patterns.
|
||||
file.Seek(patternStartOffset + officialPatterns * 1024);
|
||||
if(!ValidateMODPatternData(file, 64, true))
|
||||
numPatterns = officialPatterns;
|
||||
file.Seek(patternStartOffset);
|
||||
}
|
||||
|
||||
#ifdef MPT_BUILD_DEBUG
|
||||
// Check if the "hidden" patterns in the order list are actually real, i.e. if they are saved in the file.
|
||||
// OpenMPT did this check in the past, but no other tracker appears to do this.
|
||||
// 31-sample NoiseTracker / ProTracker specifics:
|
||||
// Interestingly, (broken) variants of the ProTracker modules
|
||||
// "killing butterfly" (MD5 bd676358b1dbb40d40f25435e845cf6b, SHA1 9df4ae21214ff753802756b616a0cafaeced8021),
|
||||
// "quartex" by Reflex (MD5 35526bef0fb21cb96394838d94c14bab, SHA1 116756c68c7b6598dcfbad75a043477fcc54c96c),
|
||||
// seem to have the "correct" file size when only taking the "official" patterns into account, but they only play
|
||||
// correctly when also loading the inofficial patterns.
|
||||
// See also the above check for ambiguities with SoundTracker modules.
|
||||
// Keep this assertion in the code to find potential other broken MODs.
|
||||
if(numPatterns != officialPatterns && sizeWithoutPatterns + officialPatterns * numChannels * 256 == file.GetLength())
|
||||
{
|
||||
MPT_ASSERT(false);
|
||||
//numPatterns = officialPatterns;
|
||||
} else
|
||||
#endif
|
||||
// On the other hand, "Shofixti Ditty.mod" from Star Control 2 (MD5 62b7b0819123400e4d5a7813eef7fc7d, SHA1 8330cd595c61f51c37a3b6f2a8559cf3fcaaa6e8)
|
||||
// doesn't sound correct when taking the second "inofficial" pattern into account.
|
||||
file.Seek(patternStartOffset + officialPatterns * numChannels * 256);
|
||||
if(!ValidateMODPatternData(file, 64, true))
|
||||
numPatterns = officialPatterns;
|
||||
file.Seek(patternStartOffset);
|
||||
}
|
||||
|
||||
if(numPatternsIllegal > numPatterns && sizeWithoutPatterns + numPatternsIllegal * numChannels * 256 == file.GetLength())
|
||||
{
|
||||
// Even those illegal pattern indexes (> 128) appear to be valid... What a weird file!
|
||||
|
@ -776,7 +771,7 @@ static bool CheckMODMagic(const char magic[4], MODMagicResult &result)
|
|||
|
||||
CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderMOD(MemoryFileReader file, const uint64 *pfilesize)
|
||||
{
|
||||
if(!file.CanRead(1080 + 4))
|
||||
if(!file.LengthIsAtLeast(1080 + 4))
|
||||
{
|
||||
return ProbeWantMoreData;
|
||||
}
|
||||
|
@ -1283,7 +1278,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
|
|||
}
|
||||
#endif // MPT_EXTERNAL_SAMPLES || MPT_BUILD_FUZZER
|
||||
|
||||
// Fix VBlank MODs. Arbitrary threshold: 10 minutes.
|
||||
// Fix VBlank MODs. Arbitrary threshold: 8 minutes (enough for "frame of mind" by Dascon...).
|
||||
// Basically, this just converts all tempo commands into speed commands
|
||||
// for MODs which are supposed to have VBlank timing (instead of CIA timing).
|
||||
// There is no perfect way to do this, since both MOD types look the same,
|
||||
|
@ -1296,12 +1291,12 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
|
|||
if(isMdKd && hasTempoCommands && !definitelyCIA)
|
||||
{
|
||||
const double songTime = GetLength(eNoAdjust).front().duration;
|
||||
if(songTime >= 600.0)
|
||||
if(songTime >= 480.0)
|
||||
{
|
||||
m_playBehaviour.set(kMODVBlankTiming);
|
||||
if(GetLength(eNoAdjust, GetLengthTarget(songTime)).front().targetReached)
|
||||
{
|
||||
// This just makes things worse, song is at least as long as in CIA mode (e.g. in "Stary Hallway" by Neurodancer)
|
||||
// This just makes things worse, song is at least as long as in CIA mode
|
||||
// Obviously we should keep using CIA timing then...
|
||||
m_playBehaviour.reset(kMODVBlankTiming);
|
||||
} else
|
||||
|
|
|
@ -59,6 +59,9 @@ void CSoundFile::S3MConvert(ModCommand &m, bool fromIT)
|
|||
// Chars under 0x40 don't save properly, so map : to ] and # to [.
|
||||
case ']': m.command = CMD_DELAYCUT; break;
|
||||
case '[': m.command = CMD_XPARAM; break;
|
||||
// BeRoTracker extensions
|
||||
case '1' + 0x41: m.command = fromIT ? CMD_KEYOFF : CMD_NONE; break;
|
||||
case '2' + 0x41: m.command = fromIT ? CMD_SETENVPOSITION : CMD_NONE; break;
|
||||
default: m.command = CMD_NONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ void ModChannel::Reset(ResetFlags resetMask, const CSoundFile &sndFile, CHANNELI
|
|||
prevNoteOffset = 0;
|
||||
lastZxxParam = 0xFF;
|
||||
isFirstTick = false;
|
||||
triggerNote = false;
|
||||
isPreviewNote = false;
|
||||
rowCommand.Clear();
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ struct ModChannel
|
|||
int32 newLeftVol, newRightVol;
|
||||
int32 nRealVolume, nRealPan;
|
||||
int32 nVolume, nPan, nFadeOutVol;
|
||||
int32 nPeriod; // Frequency in Hz if !CSoundFile::PeriodsAreFrequencies() or using custom tuning, 4x Amiga periods otherwise
|
||||
int32 nPeriod; // Frequency in Hz if CSoundFile::PeriodsAreFrequencies() or using custom tuning, 4x Amiga periods otherwise
|
||||
int32 nC5Speed, nPortamentoDest;
|
||||
int32 cachedPeriod, glissandoPeriod;
|
||||
int32 nCalcVolume; // Calculated channel volume, 14-Bit (without global volume, pre-amp etc applied) - for MIDI macros
|
||||
|
@ -117,8 +117,9 @@ struct ModChannel
|
|||
uint8 nEFxSpeed, nEFxDelay; // memory for Invert Loop (EFx, .MOD only)
|
||||
uint8 nNoteSlideCounter, nNoteSlideSpeed, nNoteSlideStep; // IMF / PTM Note Slide
|
||||
uint8 lastZxxParam; // Memory for \xx slides
|
||||
bool isFirstTick : 1;
|
||||
bool isPreviewNote : 1;
|
||||
bool isFirstTick : 1; // Execute tick-0 effects on this channel? (condition differs between formats due to Pattern Delay commands)
|
||||
bool triggerNote : 1; // Trigger note on this tick on this channel if there is one?
|
||||
bool isPreviewNote : 1; // Notes preview in editor
|
||||
|
||||
//-->Variables used to make user-definable tuning modes work with pattern effects.
|
||||
//If true, freq should be recalculated in ReadNote() on first tick.
|
||||
|
|
|
@ -649,8 +649,8 @@ public:
|
|||
|
||||
MPT_CONSTEXPR11_FUN FPInt() : v(0) { }
|
||||
MPT_CONSTEXPR11_FUN FPInt(T intPart, T fractPart) : v((intPart * fractFact) + (fractPart % fractFact)) { }
|
||||
explicit MPT_CONSTEXPR11_FUN FPInt(float f) : v(static_cast<T>(f * float(fractFact))) { }
|
||||
explicit MPT_CONSTEXPR11_FUN FPInt(double f) : v(static_cast<T>(f * double(fractFact))) { }
|
||||
explicit MPT_CONSTEXPR11_FUN FPInt(float f) : v(mpt::saturate_round<T>(f * float(fractFact))) { }
|
||||
explicit MPT_CONSTEXPR11_FUN FPInt(double f) : v(mpt::saturate_round<T>(f * double(fractFact))) { }
|
||||
|
||||
// Set integer and fractional part
|
||||
MPT_CONSTEXPR14_FUN FPInt<fractFact, T> &Set(T intPart, T fractPart = 0) { v = (intPart * fractFact) + (fractPart % fractFact); return *this; }
|
||||
|
|
|
@ -81,10 +81,10 @@ int CSoundFile::SetupChannelFilter(ModChannel &chn, bool bReset, int envModifier
|
|||
// Filtering is only ever done in IT if either cutoff is not full or if resonance is set.
|
||||
if(m_playBehaviour[kITFilterBehaviour] && resonance == 0 && computedCutoff >= 254)
|
||||
{
|
||||
if(chn.rowCommand.IsNote() && !chn.rowCommand.IsPortamento() && !chn.nMasterChn && chn.isFirstTick)
|
||||
if(chn.rowCommand.IsNote() && !chn.rowCommand.IsPortamento() && !chn.nMasterChn && chn.triggerNote)
|
||||
{
|
||||
// Z7F next to a note disables the filter, however in other cases this should not happen.
|
||||
// Test cases: filter-reset.it, filter-reset-carry.it, filter-reset-envelope.it, filter-nna.it
|
||||
// Test cases: filter-reset.it, filter-reset-carry.it, filter-reset-envelope.it, filter-nna.it, FilterResetPatDelay.it
|
||||
chn.dwFlags.reset(CHN_FILTER);
|
||||
}
|
||||
return -1;
|
||||
|
@ -148,7 +148,7 @@ int CSoundFile::SetupChannelFilter(ModChannel &chn, bool bReset, int envModifier
|
|||
#endif // MPT_INTMIXER
|
||||
break;
|
||||
}
|
||||
#undef FILTER_CONVERT
|
||||
#undef MPT_FILTER_CONVERT
|
||||
|
||||
if (bReset)
|
||||
{
|
||||
|
|
|
@ -2659,6 +2659,7 @@ bool CSoundFile::ProcessEffects()
|
|||
{
|
||||
chn.isFirstTick = tickCount == nStartTick;
|
||||
}
|
||||
chn.triggerNote = triggerNote;
|
||||
|
||||
// FT2 compatibility: Note + portamento + note delay = no portamento
|
||||
// Test case: PortaDelay.xm
|
||||
|
@ -5082,7 +5083,7 @@ void CSoundFile::ProcessMIDIMacro(CHANNELINDEX nChn, bool isSmooth, const char *
|
|||
} else if(macro[pos] == 'z')
|
||||
{
|
||||
// Zxx parameter
|
||||
data = param & 0x7F;
|
||||
data = param;
|
||||
if(isSmooth && chn.lastZxxParam < 0x80
|
||||
&& (outPos < 3 || out[outPos - 3] != 0xF0 || out[outPos - 2] < 0xF0))
|
||||
{
|
||||
|
|
|
@ -1908,6 +1908,8 @@ void CSoundFile::ProcessSampleAutoVibrato(ModChannel &chn, int &period, Tuning::
|
|||
void CSoundFile::ProcessRamping(ModChannel &chn) const
|
||||
{
|
||||
chn.leftRamp = chn.rightRamp = 0;
|
||||
LimitMax(chn.newLeftVol, int32_max >> VOLUMERAMPPRECISION);
|
||||
LimitMax(chn.newRightVol, int32_max >> VOLUMERAMPPRECISION);
|
||||
if(chn.dwFlags[CHN_VOLUMERAMP] && (chn.leftVol != chn.newLeftVol || chn.rightVol != chn.newRightVol))
|
||||
{
|
||||
const bool rampUp = (chn.newLeftVol > chn.leftVol) || (chn.newRightVol > chn.rightVol);
|
||||
|
@ -2509,7 +2511,7 @@ void CSoundFile::ProcessMacroOnChannel(CHANNELINDEX nChn)
|
|||
if(chn.rowCommand.param < 0x80)
|
||||
ProcessMIDIMacro(nChn, (chn.rowCommand.command == CMD_SMOOTHMIDI), m_MidiCfg.szMidiSFXExt[chn.nActiveMacro], chn.rowCommand.param);
|
||||
else
|
||||
ProcessMIDIMacro(nChn, (chn.rowCommand.command == CMD_SMOOTHMIDI), m_MidiCfg.szMidiZXXExt[(chn.rowCommand.param & 0x7F)], 0);
|
||||
ProcessMIDIMacro(nChn, (chn.rowCommand.command == CMD_SMOOTHMIDI), m_MidiCfg.szMidiZXXExt[(chn.rowCommand.param & 0x7F)], chn.rowCommand.param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,7 +262,8 @@ bool CPattern::SetName(const char *newName, size_t maxChars)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
m_PatternName = mpt::truncate(newName, maxChars);
|
||||
const auto nameEnd = std::find(newName, newName + maxChars, '\0');
|
||||
m_PatternName.assign(newName, nameEnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,7 @@ void CPatternContainer::ClearPatterns()
|
|||
|
||||
void CPatternContainer::DestroyPatterns()
|
||||
{
|
||||
for(PATTERNINDEX i = 0; i < m_Patterns.size(); i++)
|
||||
{
|
||||
Remove(i);
|
||||
}
|
||||
m_Patterns.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,7 +64,7 @@ PATTERNINDEX CPatternContainer::InsertAny(const ROWINDEX rows, bool respectQtyLi
|
|||
|
||||
bool CPatternContainer::Insert(const PATTERNINDEX index, const ROWINDEX rows)
|
||||
{
|
||||
if(rows > MAX_PATTERN_ROWS || rows == 0)
|
||||
if(rows > MAX_PATTERN_ROWS || rows == 0 || index >= PATTERNINDEX_INVALID)
|
||||
return false;
|
||||
if(IsValidPat(index))
|
||||
return false;
|
||||
|
|
|
@ -616,10 +616,11 @@ float I3DL2Reverb::CalcDecayCoeffs(int32 index)
|
|||
float c2 = 0.0f;
|
||||
|
||||
float c21 = (std::pow(c1, 2.0f - 2.0f / decayHFRatio) - 1.0f) / (1.0f - std::cos(hfRef));
|
||||
if(c21 != 0)
|
||||
if(c21 != 0 && std::isfinite(c21))
|
||||
{
|
||||
float c22 = -2.0f * c21 - 2.0f;
|
||||
float c23 = std::sqrt(c22 * c22 - c21 * c21 * 4.0f);
|
||||
float c23sq = c22 * c22 - c21 * c21 * 4.0f;
|
||||
float c23 = c23sq > 0.0f ? std::sqrt(c23sq) : 0.0f;
|
||||
c2 = (c23 - c22) / (c21 + c21);
|
||||
if(std::abs(c2) > 1.0f)
|
||||
c2 = (-c22 - c23) / (c21 + c21);
|
||||
|
|
|
@ -23,6 +23,10 @@ OPENMPT_NAMESPACE_BEGIN
|
|||
|
||||
namespace Tuning {
|
||||
|
||||
static RATIOTYPE SanitizeGroupRatio(RATIOTYPE ratio)
|
||||
{
|
||||
return std::clamp(std::abs(ratio), 1e-15f, 1e+07f);
|
||||
}
|
||||
|
||||
namespace CTuningS11n
|
||||
{
|
||||
|
@ -256,7 +260,12 @@ RATIOTYPE CTuning::GetRatio(const NOTEINDEXTYPE note) const
|
|||
{
|
||||
return s_DefaultFallbackRatio;
|
||||
}
|
||||
return m_RatioTable[note - m_NoteMin];
|
||||
const auto ratio = m_RatioTable[note - m_NoteMin];
|
||||
if(ratio <= 1e-15f)
|
||||
{
|
||||
return s_DefaultFallbackRatio;
|
||||
}
|
||||
return ratio;
|
||||
}
|
||||
|
||||
|
||||
|
@ -479,6 +488,17 @@ SerializationResult CTuning::InitDeserialize(std::istream &iStrm, mpt::Charset d
|
|||
UNOTEINDEXTYPE ratiotableSize = 0;
|
||||
ssb.ReadItem(ratiotableSize, "RTI4");
|
||||
|
||||
m_GroupRatio = SanitizeGroupRatio(m_GroupRatio);
|
||||
if(!std::isfinite(m_GroupRatio))
|
||||
{
|
||||
return SerializationResult::Failure;
|
||||
}
|
||||
for(auto ratio : m_RatioTable)
|
||||
{
|
||||
if(!std::isfinite(ratio))
|
||||
return SerializationResult::Failure;
|
||||
}
|
||||
|
||||
// If reader status is ok and m_NoteMin is somewhat reasonable, process data.
|
||||
if(!((ssb.GetStatus() & srlztn::SNT_FAILURE) == 0 && m_NoteMin >= -300 && m_NoteMin <= 300))
|
||||
{
|
||||
|
@ -682,6 +702,11 @@ SerializationResult CTuning::InitDeserializeOLD(std::istream &inStrm, mpt::Chars
|
|||
return SerializationResult::Failure;
|
||||
}
|
||||
}
|
||||
for(auto ratio : m_RatioTable)
|
||||
{
|
||||
if(!std::isfinite(ratio))
|
||||
return SerializationResult::Failure;
|
||||
}
|
||||
|
||||
//Fineratios
|
||||
if(version <= 2)
|
||||
|
@ -697,6 +722,11 @@ SerializationResult CTuning::InitDeserializeOLD(std::istream &inStrm, mpt::Chars
|
|||
return SerializationResult::Failure;
|
||||
}
|
||||
}
|
||||
for(auto ratio : m_RatioTableFine)
|
||||
{
|
||||
if(!std::isfinite(ratio))
|
||||
return SerializationResult::Failure;
|
||||
}
|
||||
m_FineStepCount = mpt::saturate_cast<USTEPINDEXTYPE>(m_RatioTableFine.size());
|
||||
|
||||
// m_NoteMin
|
||||
|
@ -720,8 +750,8 @@ SerializationResult CTuning::InitDeserializeOLD(std::istream &inStrm, mpt::Chars
|
|||
//m_GroupRatio
|
||||
IEEE754binary32LE groupratio = IEEE754binary32LE(0.0f);
|
||||
mpt::IO::Read(inStrm, groupratio);
|
||||
m_GroupRatio = groupratio;
|
||||
if(m_GroupRatio < 0)
|
||||
m_GroupRatio = SanitizeGroupRatio(groupratio);
|
||||
if(!std::isfinite(m_GroupRatio))
|
||||
{
|
||||
return SerializationResult::Failure;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue