summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cowgill <jcowgill@debian.org>2019-08-11 11:03:35 +0100
committerJames Cowgill <jcowgill@debian.org>2019-08-11 11:03:35 +0100
commit82a10402597fc04f54a939d3edaf673315ea87a1 (patch)
treec4d7d7a8cc41a6a4ef6b83557738ce7d4e34ea51
parentdc825bfd49ccba2594b05f2926234839182ed70b (diff)
New upstream version 0.4.6
-rw-r--r--common/CompilerDetect.h10
-rw-r--r--common/mptAlloc.cpp8
-rw-r--r--common/mptIO.h22
-rw-r--r--common/mptStringFormat.cpp13
-rw-r--r--common/mptStringFormat.h3
-rw-r--r--common/versionNumber.h2
-rwxr-xr-xconfigure26
-rw-r--r--configure.ac8
-rw-r--r--examples/libopenmpt_example_cxx.cpp15
-rw-r--r--libopenmpt/dox/changelog.md16
-rw-r--r--libopenmpt/libopenmpt_version.h2
-rw-r--r--libopenmpt/libopenmpt_version.mk4
-rw-r--r--man/openmpt123.12
-rw-r--r--soundlib/Dither.cpp5
-rw-r--r--soundlib/Load_it.cpp21
-rw-r--r--soundlib/Load_mod.cpp73
-rw-r--r--soundlib/ModChannel.cpp4
-rw-r--r--soundlib/Snd_fx.cpp3
-rw-r--r--soundlib/Sndfile.h4
-rw-r--r--soundlib/modcommand.cpp6
-rw-r--r--test/test.cpp84
21 files changed, 240 insertions, 91 deletions
diff --git a/common/CompilerDetect.h b/common/CompilerDetect.h
index 0e7e366..3b3dbec 100644
--- a/common/CompilerDetect.h
+++ b/common/CompilerDetect.h
@@ -58,7 +58,9 @@
#elif defined(_MSC_VER)
#define MPT_COMPILER_MSVC 1
-#if (_MSC_VER >= 1921)
+#if (_MSC_VER >= 1922)
+#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,2)
+#elif (_MSC_VER >= 1921)
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,1)
#elif (_MSC_VER >= 1920)
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,0)
@@ -309,3 +311,9 @@
#define MPT_COMPILER_QUIRK_MSVC_STRINGSTREAM
#endif
+#if MPT_CXX_AT_LEAST(17)
+#if MPT_COMPILER_MSVC || MPT_GCC_BEFORE(8,1,0) || MPT_CLANG_BEFORE(5,0,0) || (MPT_COMPILER_GCC && defined(__GLIBCXX__) && (defined(__MINGW32__) || defined(__MINGW64__))) || (MPT_COMPILER_CLANG && defined(__GLIBCXX__)) || (MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) || MPT_OS_OPENBSD || MPT_OS_EMSCRIPTEN || (defined(__clang__) && defined(_MSC_VER))
+#define MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC
+#endif
+#endif
+
diff --git a/common/mptAlloc.cpp b/common/mptAlloc.cpp
index 362bd12..3eae6f3 100644
--- a/common/mptAlloc.cpp
+++ b/common/mptAlloc.cpp
@@ -56,7 +56,7 @@ void* align(std::size_t alignment, std::size_t size, void* &ptr, std::size_t &sp
aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::size_t alignment)
{
- #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_GCC && defined(__GLIBCXX__) && (defined(__MINGW32__) || defined(__MINGW64__))) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) && !MPT_OS_EMSCRIPTEN
+ #if MPT_CXX_AT_LEAST(17) && !defined(MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC)
std::size_t space = count * size;
void* mem = std::aligned_alloc(alignment, space);
if(!mem)
@@ -64,7 +64,7 @@ aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::
MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
}
return aligned_raw_memory{mem, mem};
- #elif MPT_COMPILER_MSVC
+ #elif MPT_COMPILER_MSVC || (defined(__clang__) && defined(_MSC_VER))
std::size_t space = count * size;
void* mem = _aligned_malloc(space, alignment);
if(!mem)
@@ -103,9 +103,9 @@ aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::
void aligned_free(aligned_raw_memory raw)
{
- #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_GCC && defined(__GLIBCXX__) && (defined(__MINGW32__) || defined(__MINGW64__))) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) && !MPT_OS_EMSCRIPTEN
+ #if MPT_CXX_AT_LEAST(17) && !defined(MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC)
std::free(raw.mem);
- #elif MPT_COMPILER_MSVC
+ #elif MPT_COMPILER_MSVC || (defined(__clang__) && defined(_MSC_VER))
_aligned_free(raw.mem);
#else
std::free(raw.mem);
diff --git a/common/mptIO.h b/common/mptIO.h
index d6b059a..24825bd 100644
--- a/common/mptIO.h
+++ b/common/mptIO.h
@@ -74,16 +74,16 @@ bool Flush(std::ostream & f);
template <typename Tfile> class WriteBuffer;
template <typename Tfile> bool IsValid(WriteBuffer<Tfile> & f) { return IsValid(f.file()); }
-template <typename Tfile> IO::Offset TellRead(WriteBuffer<Tfile> & f) { return TellRead(f.file()); }
-template <typename Tfile> IO::Offset TellWrite(WriteBuffer<Tfile> & f) { return TellWrite(f.file()); }
-template <typename Tfile> bool SeekBegin(WriteBuffer<Tfile> & f) { return SeekBegin(f.file()); }
-template <typename Tfile> bool SeekEnd(WriteBuffer<Tfile> & f) { return SeekEnd(f.file()); }
-template <typename Tfile> bool SeekAbsolute(WriteBuffer<Tfile> & f, IO::Offset pos) { return SeekAbsolute(f.file(), pos); }
-template <typename Tfile> bool SeekRelative(WriteBuffer<Tfile> & f, IO::Offset off) { return SeekRelative(f.file(), off); }
-template <typename Tfile> IO::Offset ReadRawImpl(WriteBuffer<Tfile> & f, mpt::byte * data, std::size_t size) { return ReadRawImpl(f.file(), data, size); }
+template <typename Tfile> IO::Offset TellRead(WriteBuffer<Tfile> & f) { f.FlushLocal(); return TellRead(f.file()); }
+template <typename Tfile> IO::Offset TellWrite(WriteBuffer<Tfile> & f) { return TellWrite(f.file()) + f.GetCurrentSize(); }
+template <typename Tfile> bool SeekBegin(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekBegin(f.file()); }
+template <typename Tfile> bool SeekEnd(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekEnd(f.file()); }
+template <typename Tfile> bool SeekAbsolute(WriteBuffer<Tfile> & f, IO::Offset pos) { return f.FlushLocal(); SeekAbsolute(f.file(), pos); }
+template <typename Tfile> bool SeekRelative(WriteBuffer<Tfile> & f, IO::Offset off) { return f.FlushLocal(); SeekRelative(f.file(), off); }
+template <typename Tfile> IO::Offset ReadRawImpl(WriteBuffer<Tfile> & f, mpt::byte * data, std::size_t size) { f.FlushLocal(); return ReadRawImpl(f.file(), data, size); }
template <typename Tfile> bool WriteRawImpl(WriteBuffer<Tfile> & f, const mpt::byte * data, std::size_t size) { return f.Write(mpt::as_span(data, size)); }
-template <typename Tfile> bool IsEof(WriteBuffer<Tfile> & f) { return IsEof(f.file()); }
-template <typename Tfile> bool Flush(WriteBuffer<Tfile> & f) { return Flush(f.file()); }
+template <typename Tfile> bool IsEof(WriteBuffer<Tfile> & f) { f.FlushLocal(); return IsEof(f.file()); }
+template <typename Tfile> bool Flush(WriteBuffer<Tfile> & f) { f.FlushLocal(); return Flush(f.file()); }
@@ -627,6 +627,10 @@ public:
{
return size == buffer.size();
}
+ inline std::size_t GetCurrentSize() const
+ {
+ return size;
+ }
inline bool Write(mpt::const_byte_span data)
{
bool result = true;
diff --git a/common/mptStringFormat.cpp b/common/mptStringFormat.cpp
index f77ef17..a8f92ae 100644
--- a/common/mptStringFormat.cpp
+++ b/common/mptStringFormat.cpp
@@ -17,7 +17,20 @@
#endif
#if MPT_FORMAT_CXX17_INT
+#if MPT_MSVC_AT_LEAST(2019,0) && MPT_MSVC_BEFORE(2019,2)
+#if !(defined(UNICODE) || defined(_UNICODE))
+// work-around https://developercommunity.visualstudio.com/content/problem/629849/mfc-headers-conflict-with-c17-charconv-header-in-m.html
+#pragma push_macro("_M2")
+#undef _M2
+#endif
+#endif
#include <charconv>
+#if MPT_MSVC_AT_LEAST(2019,0) && MPT_MSVC_BEFORE(2019,2)
+#if !(defined(UNICODE) || defined(_UNICODE))
+// work-around https://developercommunity.visualstudio.com/content/problem/629849/mfc-headers-conflict-with-c17-charconv-header-in-m.html
+#pragma pop_macro("_M2")
+#endif
+#endif
#endif // MPT_FORMAT_CXX17_INT
#include <iomanip>
#include <locale>
diff --git a/common/mptStringFormat.h b/common/mptStringFormat.h
index 56a5d6e..2ddad8e 100644
--- a/common/mptStringFormat.h
+++ b/common/mptStringFormat.h
@@ -88,9 +88,6 @@ MPT_DEPRECATED std::string ToString(const wchar_t & x); // deprecated to catch p
MPT_DEPRECATED std::string ToString(const mpt::ustring & x); // Unknown encoding.
#endif
#if defined(_MFC_VER)
-MPT_DEPRECATED std::string ToString(const mpt::ustring & x); // Unknown encoding.
-#endif
-#if defined(_MFC_VER)
MPT_DEPRECATED std::string ToString(const CString & x);
#endif
std::string ToString(const bool & x);
diff --git a/common/versionNumber.h b/common/versionNumber.h
index 62f7a9c..03a5400 100644
--- a/common/versionNumber.h
+++ b/common/versionNumber.h
@@ -20,7 +20,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 28
-#define VER_MINOR 05
+#define VER_MINOR 06
#define VER_MINORMINOR 00
//Numerical value of the version.
diff --git a/configure b/configure
index 83faeb6..0325c56 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libopenmpt 0.4.5+release.autotools.
+# Generated by GNU Autoconf 2.69 for libopenmpt 0.4.6+release.autotools.
#
# Report bugs to <https://bugs.openmpt.org/>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libopenmpt'
PACKAGE_TARNAME='libopenmpt'
-PACKAGE_VERSION='0.4.5+release.autotools'
-PACKAGE_STRING='libopenmpt 0.4.5+release.autotools'
+PACKAGE_VERSION='0.4.6+release.autotools'
+PACKAGE_STRING='libopenmpt 0.4.6+release.autotools'
PACKAGE_BUGREPORT='https://bugs.openmpt.org/'
PACKAGE_URL='https://lib.openmpt.org/'
@@ -1485,7 +1485,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures libopenmpt 0.4.5+release.autotools to adapt to many kinds of systems.
+\`configure' configures libopenmpt 0.4.6+release.autotools to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1556,7 +1556,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of libopenmpt 0.4.5+release.autotools:";;
+ short | recursive ) echo "Configuration of libopenmpt 0.4.6+release.autotools:";;
esac
cat <<\_ACEOF
@@ -1756,7 +1756,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-libopenmpt configure 0.4.5+release.autotools
+libopenmpt configure 0.4.6+release.autotools
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2246,7 +2246,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by libopenmpt $as_me 0.4.5+release.autotools, which was
+It was created by libopenmpt $as_me 0.4.6+release.autotools, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3117,7 +3117,7 @@ fi
# Define the identity of the package.
PACKAGE='libopenmpt'
- VERSION='0.4.5+release.autotools'
+ VERSION='0.4.6+release.autotools'
cat >>confdefs.h <<_ACEOF
@@ -17281,13 +17281,13 @@ LIBOPENMPT_LTVER_AGE=1
-$as_echo "#define MPT_SVNURL \"https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.5\"" >>confdefs.h
+$as_echo "#define MPT_SVNURL \"https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.6\"" >>confdefs.h
-$as_echo "#define MPT_SVNVERSION \"11626\"" >>confdefs.h
+$as_echo "#define MPT_SVNVERSION \"11911\"" >>confdefs.h
-$as_echo "#define MPT_SVNDATE \"2019-05-27T06:47:50.022790Z\"" >>confdefs.h
+$as_echo "#define MPT_SVNDATE \"2019-08-10T16:17:06.209813Z\"" >>confdefs.h
$as_echo "#define MPT_PACKAGE true" >>confdefs.h
@@ -23527,7 +23527,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by libopenmpt $as_me 0.4.5+release.autotools, which was
+This file was extended by libopenmpt $as_me 0.4.6+release.autotools, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -23594,7 +23594,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-libopenmpt config.status 0.4.5+release.autotools
+libopenmpt config.status 0.4.6+release.autotools
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 697c124..3bb702f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([libopenmpt], [0.4.5+release.autotools], [https://bugs.openmpt.org/], [libopenmpt], [https://lib.openmpt.org/])
+AC_INIT([libopenmpt], [0.4.6+release.autotools], [https://bugs.openmpt.org/], [libopenmpt], [https://lib.openmpt.org/])
AC_PREREQ([2.68])
AC_CONFIG_MACRO_DIR([m4])
@@ -27,9 +27,9 @@ AC_SUBST([LIBOPENMPT_LTVER_CURRENT])
AC_SUBST([LIBOPENMPT_LTVER_REVISION])
AC_SUBST([LIBOPENMPT_LTVER_AGE])
-AC_DEFINE([MPT_SVNURL], ["https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.5"], [svn version])
-AC_DEFINE([MPT_SVNVERSION], ["11626"], [svn version])
-AC_DEFINE([MPT_SVNDATE], ["2019-05-27T06:47:50.022790Z"], [svn date])
+AC_DEFINE([MPT_SVNURL], ["https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.6"], [svn version])
+AC_DEFINE([MPT_SVNVERSION], ["11911"], [svn version])
+AC_DEFINE([MPT_SVNDATE], ["2019-08-10T16:17:06.209813Z"], [svn date])
AC_DEFINE([MPT_PACKAGE], [true], [is package])
diff --git a/examples/libopenmpt_example_cxx.cpp b/examples/libopenmpt_example_cxx.cpp
index d08b2d3..b3eb4e7 100644
--- a/examples/libopenmpt_example_cxx.cpp
+++ b/examples/libopenmpt_example_cxx.cpp
@@ -20,7 +20,22 @@
#include <libopenmpt/libopenmpt.hpp>
+#if (__cplusplus >= 201103L)
+#if defined(__clang__)
+#if ((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 40000)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
+#endif
+#endif
+#endif
#include <portaudiocpp/PortAudioCpp.hxx>
+#if (__cplusplus >= 201103L)
+#if defined(__clang__)
+#if ((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 40000)
+#pragma clang diagnostic pop
+#endif
+#endif
+#endif
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
#if defined( __GNUC__ )
diff --git a/libopenmpt/dox/changelog.md b/libopenmpt/dox/changelog.md
index 8aee41c..1eb1677 100644
--- a/libopenmpt/dox/changelog.md
+++ b/libopenmpt/dox/changelog.md
@@ -5,6 +5,22 @@ Changelog {#changelog}
For fully detailed change log, please see the source repository directly. This
is just a high-level summary.
+### libopenmpt 0.4.6 (2019-08-10)
+
+ * [**Bug**] Compilation fix for OpenBSD.
+ * [**Bug**] Compilation fix for NO_PLUGINS being defined.
+
+ * in_openmpt: Correct documentation. `openmpt-mpg123.dll` must be placed into
+ the Winamp directory.
+
+ * Detect IT files unpacked with early UNMO3 versions.
+
+ * mpg123: Update to v1.25.11 (2019-07-18).
+ * minimp3: Update to commit 977514a6dfc4960d819a103f43b358e58ac6c28f
+ (2019-07-24).
+ * miniz: Update to v2.1.0 (2019-05-05).
+ * stb_vorbis: Update to v1.17 (2019-08-09).
+
### libopenmpt 0.4.5 (2019-05-27)
* [**Sec**] Possible crash during playback due out-of-bounds read in XM and
diff --git a/libopenmpt/libopenmpt_version.h b/libopenmpt/libopenmpt_version.h
index 787d442..0d319f6 100644
--- a/libopenmpt/libopenmpt_version.h
+++ b/libopenmpt/libopenmpt_version.h
@@ -19,7 +19,7 @@
/*! \brief libopenmpt minor version number */
#define OPENMPT_API_VERSION_MINOR 4
/*! \brief libopenmpt patch version number */
-#define OPENMPT_API_VERSION_PATCH 5
+#define OPENMPT_API_VERSION_PATCH 6
/*! \brief libopenmpt pre-release tag */
#define OPENMPT_API_VERSION_PREREL ""
/*! \brief libopenmpt pre-release flag */
diff --git a/libopenmpt/libopenmpt_version.mk b/libopenmpt/libopenmpt_version.mk
index 6bcc6d8..fce55bb 100644
--- a/libopenmpt/libopenmpt_version.mk
+++ b/libopenmpt/libopenmpt_version.mk
@@ -1,8 +1,8 @@
LIBOPENMPT_VERSION_MAJOR=0
LIBOPENMPT_VERSION_MINOR=4
-LIBOPENMPT_VERSION_PATCH=5
+LIBOPENMPT_VERSION_PATCH=6
LIBOPENMPT_VERSION_PREREL=
LIBOPENMPT_LTVER_CURRENT=1
-LIBOPENMPT_LTVER_REVISION=5
+LIBOPENMPT_LTVER_REVISION=6
LIBOPENMPT_LTVER_AGE=1
diff --git a/man/openmpt123.1 b/man/openmpt123.1
index a23663f..b1d9bc3 100644
--- a/man/openmpt123.1
+++ b/man/openmpt123.1
@@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4.
-.TH OPENMPT123 "1" "May 2019" "openmpt123 v0.4.5" "User Commands"
+.TH OPENMPT123 "1" "August 2019" "openmpt123 v0.4.6" "User Commands"
.SH NAME
openmpt123 - command line module music player based on libopenmpt
.SH SYNOPSIS
diff --git a/soundlib/Dither.cpp b/soundlib/Dither.cpp
index c09bcc4..697065d 100644
--- a/soundlib/Dither.cpp
+++ b/soundlib/Dither.cpp
@@ -61,7 +61,8 @@ void X86_Dither(int32 *pBuffer, uint32 nSamples, uint32 nBits, DitherModPlugStat
mov ecx, nBits // ecx = number of bits of noise
mov edi, gDitherA // Noise generation
mov ebx, gDitherB
- add ecx, MIXING_ATTENUATION+1
+ add ecx, MIXING_ATTENUATION
+ add ecx, 1
push ebp
mov ebp, eax
noiseloop:
@@ -117,7 +118,7 @@ static void C_Dither(int32 *pBuffer, std::size_t count, uint32 nBits, DitherModP
while(count--)
{
- *pBuffer += dither_rand(a, b) >> (nBits + MIXING_ATTENUATION + 1);
+ *pBuffer += mpt::rshift_signed(dither_rand(a, b), (nBits + MIXING_ATTENUATION + 1));
pBuffer++;
}
diff --git a/soundlib/Load_it.cpp b/soundlib/Load_it.cpp
index 223dc6e..c98400a 100644
--- a/soundlib/Load_it.cpp
+++ b/soundlib/Load_it.cpp
@@ -594,23 +594,25 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags)
uint32 minPtr = Util::MaxValueOfType(minPtr);
for(uint32 pos : insPos)
{
- if(pos > 0) minPtr = std::min(minPtr, pos);
+ if(pos > 0 && pos < minPtr) minPtr = pos;
}
for(uint32 pos : smpPos)
{
- if(pos > 0) minPtr = std::min(minPtr, pos);
+ if(pos > 0 && pos < minPtr) minPtr = pos;
}
for(uint32 pos : patPos)
{
- if(pos > 0) minPtr = std::min(minPtr, pos);
+ if(pos > 0 && pos < minPtr) minPtr = pos;
}
if(fileHeader.special & ITFileHeader::embedSongMessage)
{
minPtr = std::min<uint32>(minPtr, fileHeader.msgoffset);
}
- const bool possiblyUNMO3 = fileHeader.cmwt == 0x0214 && fileHeader.cwtv == 0x0214 && fileHeader.highlight_major == 0 && fileHeader.highlight_minor == 0
- && fileHeader.pwd == 0 && fileHeader.reserved == 0 && (fileHeader.flags & (ITFileHeader::useMIDIPitchController | ITFileHeader::reqEmbeddedMIDIConfig)) == 0;
+ const bool possiblyUNMO3 = fileHeader.cmwt == 0x0214 && (fileHeader.cwtv == 0x0214 || fileHeader.cwtv == 0)
+ && fileHeader.highlight_major == 0 && fileHeader.highlight_minor == 0
+ && fileHeader.pwd == 0 && fileHeader.reserved == 0
+ && (fileHeader.flags & (ITFileHeader::useMIDIPitchController | ITFileHeader::reqEmbeddedMIDIConfig)) == 0;
if(possiblyUNMO3 && fileHeader.insnum == 0 && fileHeader.smpnum > 0 && file.GetPosition() + 4 * smpPos.size() + 2 <= minPtr)
{
@@ -634,6 +636,11 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags)
}
}
+ if(possiblyUNMO3 && fileHeader.cwtv == 0)
+ {
+ madeWithTracker = U_("UNMO3 v0/1");
+ }
+
// Reading IT Edit History Info
// This is only supposed to be present if bit 1 of the special flags is set.
// However, old versions of Schism and probably other trackers always set this bit
@@ -1170,7 +1177,7 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags)
&& m_nSamples > 0 && !strcmp(Samples[1].filename, "XXXXXXXX.YYY"))
{
madeWithTracker = U_("CheeseTracker");
- } else if(fileHeader.cwtv == 0)
+ } else if(fileHeader.cwtv == 0 && madeWithTracker.empty())
{
madeWithTracker = U_("Unknown");
} else if(fileHeader.cmwt < 0x0300 && madeWithTracker.empty())
@@ -1629,7 +1636,7 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c
uint32 len = 0;
// Maximum 7 bytes per cell, plus end of row marker, so this buffer is always large enough to cover one row.
uint8 buf[7 * MAX_BASECHANNELS + 1];
- const ModCommand *m = Patterns[pat].GetRow(row);
+ const ModCommand *m = Patterns[pat].GetpModCommand(row, 0);
for(CHANNELINDEX ch = 0; ch < maxChannels; ch++, m++)
{
diff --git a/soundlib/Load_mod.cpp b/soundlib/Load_mod.cpp
index 073fd7b..43d5976 100644
--- a/soundlib/Load_mod.cpp
+++ b/soundlib/Load_mod.cpp
@@ -456,14 +456,14 @@ struct PT36IffChunk
// IFF chunk names
enum ChunkIdentifiers
{
- idVERS = MagicBE("VERS"),
- idINFO = MagicBE("INFO"),
- idCMNT = MagicBE("CMNT"),
- idPTDT = MagicBE("PTDT"),
+ idVERS = MagicBE("VERS"),
+ idINFO = MagicBE("INFO"),
+ idCMNT = MagicBE("CMNT"),
+ idPTDT = MagicBE("PTDT"),
};
- uint32be signature; // IFF chunk name
- uint32be chunksize; // chunk size without header
+ uint32be signature; // IFF chunk name
+ uint32be chunksize; // chunk size without header
};
MPT_BINARY_STRUCT(PT36IffChunk, 8)
@@ -521,9 +521,9 @@ static uint32 ReadSample(FileReader &file, MODSampleHeader &sampleHeader, ModSam
// 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, bool checkForWOW)
{
- 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)
- PATTERNINDEX numPatternsIllegal = 0; // Total number of patterns in file, also counting in "invalid" pattern indexes >= 128
+ 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)
+ PATTERNINDEX numPatternsIllegal = 0; // Total number of patterns in file, also counting in "invalid" pattern indexes >= 128
for(ORDERINDEX ord = 0; ord < 128; ord++)
{
@@ -893,7 +893,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
pat /= 2u;
}
}
-
+
// Restart position sanity checks
realOrders--;
Order().SetRestartPos(fileHeader.restartPos);
@@ -918,7 +918,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
// is the maximum possible sample pre-amp without getting distortion (Compatible mix levels given).
// The more channels we have, the less likely it is that all of them are used at the same time, though, so cap at 32...
m_nSamplePreAmp = Clamp(256 / m_nChannels, 32, 128);
- m_SongFlags.reset(); // SONG_ISAMIGA will be set conditionally
+ m_SongFlags.reset(); // SONG_ISAMIGA will be set conditionally
// Setup channel pan positions and volume
SetupMODPanning();
@@ -930,10 +930,10 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
// - Detect 7-bit panning.
bool onlyAmigaNotes = true;
bool fix7BitPanning = false;
- uint8 maxPanning = 0; // For detecting 8xx-as-sync
+ uint8 maxPanning = 0; // For detecting 8xx-as-sync
if(!isNoiseTracker)
{
- bool leftPanning = false, extendedPanning = false; // For detecting 800-880 panning
+ bool leftPanning = false, extendedPanning = false; // For detecting 800-880 panning
isNoiseTracker = isMdKd;
for(PATTERNINDEX pat = 0; pat < numPatterns; pat++)
{
@@ -963,7 +963,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
extendedPanning = true;
} else if(m.command == 0x0E && (m.param & 0xF0) == 0x80)
{
- maxPanning = std::max<uint8>(maxPanning, m.param << 4);
+ maxPanning = std::max<uint8>(maxPanning, (m.param & 0x0F) << 4);
}
}
}
@@ -1342,7 +1342,6 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders)
totalSampleLen += sampleHeader.length;
allVolumes |= sampleHeader.volume;
-
}
// Reject any files with no (or only silent) samples at all, as this might just be a random binary file (e.g. ID3 tags with tons of padding)
@@ -1364,7 +1363,7 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders)
{
return false;
}
-
+
// No playable song, and lots of null values => most likely a sparse binary file but not a module
if(fileHeaders.fileHeader.restartPos == 0 && fileHeaders.fileHeader.numOrders == 0 && maxPattern == 0)
{
@@ -2095,7 +2094,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags)
}
// First chunk includes "MODL" magic in size
iffHead.chunksize -= 4;
-
+
do
{
// All chunk sizes include chunk header
@@ -2104,7 +2103,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags)
{
return true;
}
-
+
FileReader chunk = file.ReadChunk(iffHead.chunksize);
if(!chunk.IsValid())
{
@@ -2120,15 +2119,15 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags)
chunk.ReadString<mpt::String::maybeNullTerminated>(version, mpt::CharsetISO8859_1, iffHead.chunksize - 6);
}
break;
-
+
case PT36IffChunk::idINFO:
infoOk = chunk.ReadStruct(info);
break;
-
+
case PT36IffChunk::idCMNT:
commentChunk = chunk;
break;
-
+
case PT36IffChunk::idPTDT:
ok = ReadMOD(chunk, loadFlags);
break;
@@ -2139,7 +2138,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags)
{
version = U_("3.6");
}
-
+
// both an info chunk and a module are required
if(ok && infoOk)
{
@@ -2149,10 +2148,10 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags)
m_nSamplePreAmp = std::min<uint16>(64, info.volume);
if(info.tempo != 0 && !vblank)
m_nDefaultTempo.Set(info.tempo);
-
+
if(info.name[0])
mpt::String::Read<mpt::String::maybeNullTerminated>(m_songName, info.name);
-
+
if(IsInRange(info.dateMonth, 1, 12) && IsInRange(info.dateDay, 1, 31) && IsInRange(info.dateHour, 0, 23)
&& IsInRange(info.dateMinute, 0, 59) && IsInRange(info.dateSecond, 0, 59))
{
@@ -2179,14 +2178,14 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags)
m_songMessage.ReadFixedLineLength(commentChunk, commentChunk.BytesLeft(), 40, 0);
}
}
-
+
m_modFormat.madeWithTracker = U_("ProTracker ") + version;
}
m_SongFlags.set(SONG_PT_MODE);
m_playBehaviour.set(kMODIgnorePanning);
m_playBehaviour.set(kMODOneShotLoops);
m_playBehaviour.set(kMODSampleSwap);
-
+
return ok;
}
@@ -2290,6 +2289,7 @@ bool CSoundFile::SaveMod(std::ostream &f) const
mpt::IO::Write(f, modMagic);
// Write patterns
+ bool invalidInstruments = false;
std::vector<uint8> events;
for(PATTERNINDEX pat = 0; pat < writePatterns; pat++)
{
@@ -2314,7 +2314,7 @@ bool CSoundFile::SaveMod(std::ostream &f) const
events.resize(writeChannels * 4);
size_t eventByte = 0;
- for(CHANNELINDEX chn = 0; chn < writeChannels; chn++)
+ for(CHANNELINDEX chn = 0; chn < writeChannels; chn++, eventByte += 4)
{
ModCommand &m = rowBase[chn];
uint8 command = m.command, param = m.param;
@@ -2334,17 +2334,24 @@ bool CSoundFile::SaveMod(std::ostream &f) const
period = ProTrackerPeriodTable[m.note - 24 - NOTE_MIN];
}
- uint8 instr = (m.instr <= 31) ? m.instr : 0;
+ const uint8 instr = (m.instr > 31) ? 0 : m.instr;
+ if(m.instr > 31)
+ invalidInstruments = true;
- events[eventByte++] = ((period >> 8) & 0x0F) | (instr & 0x10);
- events[eventByte++] = period & 0xFF;
- events[eventByte++] = ((instr & 0x0F) << 4) | (command & 0x0F);
- events[eventByte++] = param;
+ events[eventByte + 0] = ((period >> 8) & 0x0F) | (instr & 0x10);
+ events[eventByte + 1] = period & 0xFF;
+ events[eventByte + 2] = ((instr & 0x0F) << 4) | (command & 0x0F);
+ events[eventByte + 3] = param;
}
- mpt::IO::WriteRaw(f, mpt::as_span(events.data(), eventByte));
+ mpt::IO::WriteRaw(f, mpt::as_span(events));
}
}
+ if(invalidInstruments)
+ {
+ AddToLog("Warning: This track references sample slots higher than 31. Such samples cannot be saved in the MOD format, and thus the notes will not sound correct. Use the Cleanup tool to rearrange and remove unused samples.");
+ }
+
//Check for unsaved patterns
for(PATTERNINDEX pat = writePatterns; pat < Patterns.Size(); pat++)
{
diff --git a/soundlib/ModChannel.cpp b/soundlib/ModChannel.cpp
index 2aeed18..66ae13d 100644
--- a/soundlib/ModChannel.cpp
+++ b/soundlib/ModChannel.cpp
@@ -122,9 +122,9 @@ ModCommand::NOTE ModChannel::GetPluginNote(bool realNoteMapping) const
// If an arpeggio is playing, this definitely the last playing note, which may be different from the arpeggio base note stored in nNote.
return nArpeggioLastNote;
}
- ModCommand::NOTE plugNote = nNote;
+ ModCommand::NOTE plugNote = mpt::saturate_cast<ModCommand::NOTE>(nNote - nTranspose);
// Caution: When in compatible mode, ModChannel::nNote stores the "real" note, not the mapped note!
- if(realNoteMapping && pModInstrument != nullptr && plugNote >= NOTE_MIN && plugNote < (MPT_ARRAY_COUNT(pModInstrument->NoteMap) + NOTE_MIN))
+ if(realNoteMapping && pModInstrument != nullptr && plugNote >= NOTE_MIN && plugNote < (mpt::size(pModInstrument->NoteMap) + NOTE_MIN))
{
plugNote = pModInstrument->NoteMap[plugNote - NOTE_MIN];
}
diff --git a/soundlib/Snd_fx.cpp b/soundlib/Snd_fx.cpp
index 2da930a..8681d48 100644
--- a/soundlib/Snd_fx.cpp
+++ b/soundlib/Snd_fx.cpp
@@ -25,6 +25,7 @@
#include "modsmp_ctrl.h" // For updating the loop wraparound data with the invert loop effect
#include "plugins/PlugInterface.h"
#include "OPL.h"
+#include "MIDIEvents.h"
OPENMPT_NAMESPACE_BEGIN
@@ -83,7 +84,9 @@ public:
void Reset()
{
+#ifndef NO_PLUGINS
plugParams.clear();
+#endif
elapsedTime = 0.0;
state->m_lTotalSampleCount = 0;
state->m_nMusicSpeed = sndFile.m_nDefaultSpeed;
diff --git a/soundlib/Sndfile.h b/soundlib/Sndfile.h
index e3f5f95..5b55043 100644
--- a/soundlib/Sndfile.h
+++ b/soundlib/Sndfile.h
@@ -64,9 +64,9 @@ OPENMPT_NAMESPACE_BEGIN
// MODULAR ModInstrument FIELD ACCESS : body content in InstrumentExtensions.cpp
// -----------------------------------------------------------------------------
#ifndef MODPLUG_NO_FILESAVE
-extern void WriteInstrumentHeaderStructOrField(ModInstrument * input, std::ostream &file, uint32 only_this_code = -1 /* -1 for all */, uint16 fixedsize = 0);
+void WriteInstrumentHeaderStructOrField(ModInstrument * input, std::ostream &file, uint32 only_this_code = -1 /* -1 for all */, uint16 fixedsize = 0);
#endif // !MODPLUG_NO_FILESAVE
-extern bool ReadInstrumentHeaderField(ModInstrument * input, uint32 fcode, uint16 fsize, FileReader &file);
+bool ReadInstrumentHeaderField(ModInstrument * input, uint32 fcode, uint16 fsize, FileReader &file);
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
diff --git a/soundlib/modcommand.cpp b/soundlib/modcommand.cpp
index 4d11e00..1c9217d 100644
--- a/soundlib/modcommand.cpp
+++ b/soundlib/modcommand.cpp
@@ -179,7 +179,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd
param = 0x91;
} else
{
- param = std::min<PARAM>(param << 1, 0xFF);
+ param = mpt::saturate_cast<PARAM>(param * 2u);
}
}
} // End if(command == CMD_PANNING8)
@@ -515,7 +515,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd
param = (param & 0xF0) | std::min<PARAM>((param & 0x0F) * 2u, 15);
break;
case CMD_GLOBALVOLUME:
- param = std::min<PARAM>(0x80, param * 2u);
+ param = std::min<PARAM>(0x40, param) * 2u;
break;
}
} // End if(oldTypeIsIT_MPT && newTypeIsXM)
@@ -776,7 +776,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd
if(newTypeIsIT_MPT)
{
// Convert some commands which behave differently or don't exist
- if(command == CMD_NONE) switch(volcmd)
+ if(!oldTypeIsIT_MPT && command == CMD_NONE) switch(volcmd)
{
case VOLCMD_PANSLIDELEFT:
command = CMD_PANNINGSLIDE;
diff --git a/test/test.cpp b/test/test.cpp
index 540a200..39b2c2d 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -32,6 +32,7 @@
#include "../soundlib/ITCompression.h"
#include "../soundlib/tuningcollection.h"
#include "../soundlib/tuning.h"
+#include "../soundlib/Dither.h"
#ifdef MODPLUG_TRACKER
#include "../mptrack/Mptrack.h"
#include "../mptrack/Moddoc.h"
@@ -1494,9 +1495,10 @@ static MPT_NOINLINE void TestMisc2()
{
VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull).ToUString(), U_("2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32"));
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
- VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), "2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32"_uuid);
- VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToGUID(L"{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}")));
- VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToCLSID(L"{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}")));
+ constexpr mpt::UUID uuid_tmp = "2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32"_uuid;
+ VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), uuid_tmp);
+ VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToGUID(_T("{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}"))));
+ VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToCLSID(_T("{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}"))));
#endif
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
@@ -4714,6 +4716,82 @@ static MPT_NOINLINE void TestSampleConversion()
VERIFY_EQUAL_NONCONT(signed8[3], 0);
}
+ // Dither
+ {
+ std::vector<mixsample_t> buffer(64);
+ Dither dither(mpt::global_random_device());
+ dither.SetMode(DitherModPlug);
+ dither.Process(buffer.data(), 64, 1, 16);
+ std::vector<mixsample_t> expected = {
+ 727,
+ -557,
+ -552,
+ -727,
+ 439,
+ 405,
+ 703,
+ -337,
+ 235,
+ -776,
+ -458,
+ 905,
+ -110,
+ 158,
+ 374,
+ -362,
+ 283,
+ 306,
+ 710,
+ 304,
+ -608,
+ 536,
+ -501,
+ -593,
+ -349,
+ 812,
+ 916,
+ 53,
+ -953,
+ 881,
+ -236,
+ -20,
+ -623,
+ -895,
+ -302,
+ -415,
+ 899,
+ -948,
+ -766,
+ -186,
+ -390,
+ -169,
+ 253,
+ -622,
+ -769,
+ -1001,
+ 1019,
+ 787,
+ -239,
+ 718,
+ -423,
+ 988,
+ -91,
+ 763,
+ -933,
+ -510,
+ 484,
+ 794,
+ -340,
+ 552,
+ 866,
+ -608,
+ 35,
+ 395};
+ for(std::size_t i = 0; i < 64; ++i)
+ {
+ VERIFY_EQUAL_QUIET_NONCONT(buffer[i], expected[i]);
+ }
+ }
}