Update libopenmpt to version 0.5.8

CQTexperiment
Christopher Snowhill 2021-04-11 17:23:22 -07:00
parent 7a0e007d08
commit 2925a37a81
33 changed files with 182 additions and 118 deletions

View File

@ -54,7 +54,7 @@
# ONLY_TEST=0 Only build the test suite.
# STRICT=0 Treat warnings as errors.
# MODERN=0 Pass more modern compiler options.
# STDCXX=c++14 C++ standard version (only for GCC and clang)
# STDCXX=c++17 C++ standard version (only for GCC and clang)
# CHECKED=0 Enable run-time assertions.
# CHECKED_ADDRESS=0 Enable address sanitizer
# CHECKED_UNDEFINED=0 Enable undefined behaviour sanitizer
@ -183,6 +183,8 @@ LDFLAGS := $(LDFLAGS)
LDLIBS := $(LDLIBS)
ARFLAGS := $(ARFLAGS)
PC_LIBS_PRIVATE := $(PC_LIBS_PRIVATE)
PREFIX := $(PREFIX)
ifeq ($(PREFIX),)
PREFIX := /usr/local
@ -405,7 +407,6 @@ endif
endif
PC_LIBS_PRIVATE :=
PC_LIBS_PRIVATE += $(CXXSTDLIB_PCLIBSPRIVATE)
ifeq ($(HACK_ARCHIVE_SUPPORT),1)
@ -728,7 +729,7 @@ CPPFLAGS += -DMPT_BUILD_HACK_ARCHIVE_SUPPORT
endif
CPPCHECK_FLAGS += -j $(NUMTHREADS)
CPPCHECK_FLAGS += --std=c99 --std=c++14
CPPCHECK_FLAGS += --std=c99 --std=c++17
CPPCHECK_FLAGS += --quiet
CPPCHECK_FLAGS += --enable=warning --inline-suppr --template='{file}:{line}: warning: {severity}: {message} [{id}]'
CPPCHECK_FLAGS += --suppress=missingIncludeSystem

View File

@ -1,4 +1,4 @@
MPT_SVNVERSION=14391
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.7
MPT_SVNDATE=2021-03-20T17:06:12.434258Z
MPT_SVNVERSION=14580
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.8
MPT_SVNDATE=2021-04-11T14:02:18.903044Z

View File

@ -13,9 +13,11 @@ CPPFLAGS += -DWIN32 -D_WIN32
CXXFLAGS += -municode -mconsole
CFLAGS += -municode -mconsole
LDFLAGS +=
LDLIBS += -lm -lrpcrt4 -lwinmm
LDLIBS += -lm -lole32 -lrpcrt4 -lwinmm
ARFLAGS := rcs
PC_LIBS_PRIVATE += -lole32 -lrpcrt4
CFLAGS_SILENT += -Wno-unused-parameter -Wno-unused-function -Wno-cast-qual -Wno-old-style-declaration -Wno-type-limits -Wno-unused-but-set-variable
EXESUFFIX=.exe

View File

@ -13,9 +13,11 @@ CPPFLAGS += -DWIN32 -D_WIN32 -DWIN64 -D_WIN64
CXXFLAGS += -municode -mconsole
CFLAGS += -municode -mconsole
LDFLAGS +=
LDLIBS += -lm -lrpcrt4 -lwinmm
LDLIBS += -lm -lole32 -lrpcrt4 -lwinmm
ARFLAGS := rcs
PC_LIBS_PRIVATE += -lole32 -lrpcrt4
CFLAGS_SILENT += -Wno-unused-parameter -Wno-unused-function -Wno-cast-qual -Wno-old-style-declaration -Wno-type-limits -Wno-unused-but-set-variable
EXESUFFIX=.exe

View File

@ -16,6 +16,8 @@ LDFLAGS +=
LDLIBS += -lm -lole32 -lwinmm
ARFLAGS := rcs
PC_LIBS_PRIVATE += -lole32 -lrpcrt4
CFLAGS_SILENT += -Wno-unused-parameter -Wno-unused-function -Wno-cast-qual -Wno-old-style-declaration -Wno-type-limits -Wno-unused-but-set-variable
EXESUFFIX=.exe

View File

@ -13,9 +13,11 @@ CPPFLAGS += -DWIN32 -D_WIN32 -DWINAPI_FAMILY=0x2 -D_WIN32_WINNT=0x0602
CXXFLAGS += -municode -mconsole
CFLAGS += -municode -mconsole
LDFLAGS +=
LDLIBS += -lm -lole32 -lwinmm
LDLIBS += -lm -lole32 -lrpcrt4 -lwinmm
ARFLAGS := rcs
PC_LIBS_PRIVATE += -lole32 -lrpcrt4
CFLAGS_SILENT += -Wno-unused-parameter -Wno-unused-function -Wno-cast-qual -Wno-old-style-declaration -Wno-type-limits -Wno-unused-but-set-variable
EXESUFFIX=.exe

View File

@ -1,10 +1,10 @@
#pragma once
#define OPENMPT_VERSION_SVNVERSION "14391"
#define OPENMPT_VERSION_REVISION 14391
#define OPENMPT_VERSION_SVNVERSION "14580"
#define OPENMPT_VERSION_REVISION 14580
#define OPENMPT_VERSION_DIRTY 0
#define OPENMPT_VERSION_MIXEDREVISIONS 0
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.7"
#define OPENMPT_VERSION_DATE "2021-03-20T17:06:12.434258Z"
#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_IS_PACKAGE 1

View File

@ -199,8 +199,8 @@ static_assert(alignof(std::byte) == 1);
namespace mpt {
constexpr int arch_bits = sizeof(void*) * 8;
constexpr std::size_t pointer_size = sizeof(void*);
inline constexpr int arch_bits = sizeof(void*) * 8;
inline constexpr std::size_t pointer_size = sizeof(void*);
} // namespace mpt
static_assert(mpt::arch_bits == static_cast<int>(mpt::pointer_size) * 8);

View File

@ -24,6 +24,7 @@ uint32 RealProcSupport = 0;
uint32 ProcSupport = 0;
char ProcVendorID[16+1] = "";
char ProcBrandID[4*4*3+1] = "";
uint32 ProcRawCPUID = 0;
uint16 ProcFamily = 0;
uint8 ProcModel = 0;
uint8 ProcStepping = 0;
@ -104,6 +105,7 @@ void InitProcSupport()
ProcSupport = 0;
mpt::String::WriteAutoBuf(ProcVendorID) = "";
mpt::String::WriteAutoBuf(ProcBrandID) = "";
ProcRawCPUID = 0;
ProcFamily = 0;
ProcModel = 0;
ProcStepping = 0;
@ -118,6 +120,7 @@ void InitProcSupport()
if(VendorString.a >= 0x00000001u)
{
cpuid_result StandardFeatureFlags = cpuid(0x00000001u);
ProcRawCPUID = StandardFeatureFlags.a;
uint32 Stepping = (StandardFeatureFlags.a >> 0) & 0x0f;
uint32 BaseModel = (StandardFeatureFlags.a >> 4) & 0x0f;
uint32 BaseFamily = (StandardFeatureFlags.a >> 8) & 0x0f;
@ -181,6 +184,7 @@ void InitProcSupport()
ProcSupport = 0;
mpt::String::WriteAutoBuf(ProcVendorID) = "";
mpt::String::WriteAutoBuf(ProcBrandID) = "";
ProcRawCPUID = 0;
ProcFamily = 0;
ProcModel = 0;
ProcStepping = 0;

View File

@ -45,6 +45,7 @@ extern uint32 RealProcSupport;
extern uint32 ProcSupport;
extern char ProcVendorID[16+1];
extern char ProcBrandID[4*4*3+1];
extern uint32 ProcRawCPUID;
extern uint16 ProcFamily;
extern uint8 ProcModel;
extern uint8 ProcStepping;

View File

@ -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 08
#define VER_MINORMINOR 03
#define VER_MINOR 09
#define VER_MINORMINOR 00
OPENMPT_NAMESPACE_END

View File

@ -5,6 +5,27 @@ Changelog {#changelog}
For fully detailed change log, please see the source repository directly. This
is just a high-level summary.
### libopenmpt 0.5.8 (2021-04-11)
* [**Sec**] Possible null-pointer dereference read caused by a sequence of
`openmpt::module::read`, `openmpt::module::set_position_order_row` pointing
to an invalid pattern, and another `openmpt::module::read` call. To trigger
the crash, pattern 0 must not exist in the file and the tick speed before
the position jump must be lower than the initial speed of the module.
(r14530)
* [**Bug**] `libopenmpt.pc` did not list required system libraries `ole32.lib`
and `rpcrt4.lib` on Windows in `Libs.Private` field for static builds.
* [**Bug**] libopenmpt 0.5.7 broke seeking in some subsongs.
* The built-in LFO plugin did not load the correct initial LFO frequency.
* IT command S7x (instrument control) is now supported when seeking with
sample sync enabled.
* libopenmpt_ext `play_note` was cutting of channels even when there were
plenty of free channels to use.
* mpg123: Update to v1.26.5 (2021-03-22).
### libopenmpt 0.5.7 (2021-03-20)
* [**Sec**] Possible null-pointer dereference read caused by a sequence of

View File

@ -38,6 +38,8 @@
#include "libopenmpt.hpp"
#include "libopenmpt_plugin_settings.hpp"
#include "libopenmpt_plugin_gui.hpp"
#include "svn_version.h"
@ -62,6 +64,8 @@ static const char * in_openmpt_string = "in_openmpt " OPENMPT_API_VERSION_STRING
#include <iterator>
#include <sstream>
#include <cstring>
#define BPS 16
#define WINAMP_DSP_HEADROOM_FACTOR 2

View File

@ -194,6 +194,7 @@ class interactive {
//! Gets the current module pitch factor
/*!
\return The current pitch factor.
\throws openmpt::exception Throws an exception derived from openmpt::exception if the pitch is outside the specified range.
\sa openmpt::ext::interactive::set_pitch_factor
*/
virtual double get_pitch_factor( ) const = 0;
@ -283,7 +284,7 @@ class interactive {
//! Stop the note playing on the specified channel
/*!
\param channel The channel on which the note should be stopped.
\param channel The channel on which the note should be stopped. This is the value returned by a previous play_note call.
\throws openmpt::exception Throws an exception derived from openmpt::exception if the channel index is invalid.
\sa openmpt::ext::interactive::play_note
*/

View File

@ -256,19 +256,9 @@ namespace openmpt {
}
// Find a free channel
CHANNELINDEX free_channel = MAX_CHANNELS - 1;
// Search for available channel
for(CHANNELINDEX i = MAX_CHANNELS - 1; i >= get_num_channels(); i--)
{
const ModChannel &chn = m_sndFile->m_PlayState.Chn[i];
if ( chn.nLength == 0 ) {
free_channel = i;
break;
} else if ( chn.dwFlags[CHN_NOTEFADE] ) {
// We can probably still do better than this.
free_channel = i;
}
}
CHANNELINDEX free_channel = m_sndFile->GetNNAChannel( CHANNELINDEX_INVALID );
if ( free_channel == CHANNELINDEX_INVALID )
free_channel = MAX_CHANNELS - 1;
ModChannel &chn = m_sndFile->m_PlayState.Chn[free_channel];
chn.Reset(ModChannel::resetTotal, *m_sndFile, CHANNELINDEX_INVALID);

View File

@ -1110,7 +1110,7 @@ double module_impl::set_position_seconds( double seconds ) {
GetLengthType t = m_sndFile->GetLength( m_ctl_seek_sync_samples ? eAdjustSamplePositions : eAdjust, GetLengthTarget( seconds ).StartPos( static_cast<SEQUENCEINDEX>( subsong->sequence ), static_cast<ORDERINDEX>( subsong->start_order ), static_cast<ROWINDEX>( subsong->start_row ) ) ).back();
m_sndFile->m_PlayState.m_nNextOrder = m_sndFile->m_PlayState.m_nCurrentOrder = t.targetReached ? t.lastOrder : t.endOrder;
m_sndFile->m_PlayState.m_nNextRow = t.targetReached ? t.lastRow : t.endRow;
m_sndFile->m_PlayState.m_nTickCount = Util::MaxValueOfType(m_sndFile->m_PlayState.m_nTickCount) - 1;
m_sndFile->m_PlayState.m_nTickCount = CSoundFile::TICKS_ROW_FINISHED;
m_currentPositionSeconds = base_seconds + t.duration;
return m_currentPositionSeconds;
}
@ -1129,6 +1129,7 @@ double module_impl::set_position_order_row( std::int32_t order, std::int32_t row
m_sndFile->m_PlayState.m_nCurrentOrder = static_cast<ORDERINDEX>( order );
m_sndFile->SetCurrentOrder( static_cast<ORDERINDEX>( order ) );
m_sndFile->m_PlayState.m_nNextRow = static_cast<ROWINDEX>( row );
m_sndFile->m_PlayState.m_nTickCount = CSoundFile::TICKS_ROW_FINISHED;
m_currentPositionSeconds = m_sndFile->GetLength( m_ctl_seek_sync_samples ? eAdjustSamplePositions : eAdjust, GetLengthTarget( static_cast<ORDERINDEX>( order ), static_cast<ROWINDEX>( row ) ) ).back().duration;
return m_currentPositionSeconds;
}

View File

@ -10,7 +10,9 @@
#ifndef LIBOPENMPT_PLUGIN_SETTINGS_HPP
#define LIBOPENMPT_PLUGIN_SETTINGS_HPP
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <string>

View File

@ -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 7
#define OPENMPT_API_VERSION_PATCH 8
/*! \brief libopenmpt pre-release tag */
#define OPENMPT_API_VERSION_PREREL ""
/*! \brief libopenmpt pre-release flag */

View File

@ -1,8 +1,8 @@
LIBOPENMPT_VERSION_MAJOR=0
LIBOPENMPT_VERSION_MINOR=5
LIBOPENMPT_VERSION_PATCH=7
LIBOPENMPT_VERSION_PATCH=8
LIBOPENMPT_VERSION_PREREL=
LIBOPENMPT_LTVER_CURRENT=2
LIBOPENMPT_LTVER_REVISION=7
LIBOPENMPT_LTVER_REVISION=8
LIBOPENMPT_LTVER_AGE=2

View File

@ -38,10 +38,13 @@
#endif // _MSC_VER
#include <cctype>
#include <cstring>
#include "libopenmpt.hpp"
#include "libopenmpt_ext.hpp"
#include "libopenmpt_plugin_settings.hpp"
#include "libopenmpt_plugin_gui.hpp"
#include "svn_version.h"

View File

@ -538,6 +538,8 @@ bool CSoundFile::ReadMT2(FileReader &file, ModLoadingFlags loadFlags)
for(ROWINDEX r = 0; r < fillRows; r++)
{
m += GetNumChannels();
// cppcheck false-positive
// cppcheck-suppress selfAssignment
*m = orig;
}
}

View File

@ -27,7 +27,7 @@ using mixsample_t = AudioSampleFloat;
enum { MIXING_ATTENUATION = MixSampleIntTraits::mix_headroom_bits() };
enum { MIXING_FRACTIONAL_BITS = MixSampleIntTraits::mix_fractional_bits() };
constexpr float MIXING_SCALEF = MixSampleIntTraits::mix_scale<float>();
inline constexpr float MIXING_SCALEF = MixSampleIntTraits::mix_scale<float>();
#ifdef MPT_INTMIXER
static_assert(sizeof(mixsample_t) == 4);

View File

@ -160,4 +160,32 @@ void ModChannel::RecalcTuningFreq(Tuning::RATIOTYPE vibratoFactor, Tuning::NOTEI
}
// IT command S73-S7E
void ModChannel::InstrumentControl(uint8 param, const CSoundFile &sndFile)
{
param &= 0x0F;
switch(param)
{
case 0x3: nNNA = NNA_NOTECUT; break;
case 0x4: nNNA = NNA_CONTINUE; break;
case 0x5: nNNA = NNA_NOTEOFF; break;
case 0x6: nNNA = NNA_NOTEFADE; break;
case 0x7: VolEnv.flags.reset(ENV_ENABLED); break;
case 0x8: VolEnv.flags.set(ENV_ENABLED); break;
case 0x9: PanEnv.flags.reset(ENV_ENABLED); break;
case 0xA: PanEnv.flags.set(ENV_ENABLED); break;
case 0xB: PitchEnv.flags.reset(ENV_ENABLED); break;
case 0xC: PitchEnv.flags.set(ENV_ENABLED); break;
case 0xD: // S7D: Enable pitch envelope, force to play as pitch envelope
case 0xE: // S7E: Enable pitch envelope, force to play as filter envelope
if(sndFile.GetType() == MOD_TYPE_MPT)
{
PitchEnv.flags.set(ENV_ENABLED);
PitchEnv.flags.set(ENV_FILTER, param != 0xD);
}
break;
}
}
OPENMPT_NAMESPACE_END

View File

@ -196,6 +196,9 @@ struct ModChannel
void SetInstrumentPan(int32 pan, const CSoundFile &sndFile);
void RecalcTuningFreq(Tuning::RATIOTYPE vibratoFactor, Tuning::NOTEINDEXTYPE arpeggioSteps, const CSoundFile &sndFile);
// IT command S73-S7E
void InstrumentControl(uint8 param, const CSoundFile &sndFile);
};

View File

@ -20,10 +20,10 @@ OPENMPT_NAMESPACE_BEGIN
namespace Paula
{
constexpr int PAULA_HZ = 3546895;
constexpr int MINIMUM_INTERVAL = 4; // Tradeoff between quality and speed (lower = less aliasing)
constexpr int BLEP_SCALE = 17; // TODO: Should be 1 for float mixer
constexpr int BLEP_SIZE = 2048;
inline constexpr int PAULA_HZ = 3546895;
inline constexpr int MINIMUM_INTERVAL = 4; // Tradeoff between quality and speed (lower = less aliasing)
inline constexpr int BLEP_SCALE = 17; // TODO: Should be 1 for float mixer
inline constexpr int BLEP_SIZE = 2048;
using BlepArray = std::array<mixsample_t, BLEP_SIZE>;

View File

@ -425,7 +425,7 @@ struct SFZRegion
Read(value, loopStart, SmpLength(0), MAX_SAMPLE_LENGTH);
else if(key == "loop_end" || key == "loopend")
Read(value, loopEnd, SmpLength(0), MAX_SAMPLE_LENGTH);
else if(key == "loop_crossfade")
else if(key == "loop_crossfade" || key == "loopcrossfade")
Read(value, loopCrossfade, 0.0, DBL_MAX);
else if(key == "loop_mode" || key == "loopmode")
{
@ -685,7 +685,7 @@ bool CSoundFile::ReadSFZInstrument(INSTRUMENTINDEX nInstr, FileReader &file)
break;
}
const std::string key = mpt::ToLowerCaseAscii(s.substr(0, keyEnd));
if(key == "sample" || key == "default_path" || SFZStartsWith(key, "label_cc") || SFZStartsWith(key, "region_label"))
if(key == "sample" || key == "default_path" || SFZStartsWith(key, "label_cc") || SFZStartsWith(key, "label_key") || SFZStartsWith(key, "region_label"))
{
// Sample / CC name may contain spaces...
charsRead = s.find_first_of("=\t<", valueStart);
@ -1064,8 +1064,10 @@ bool CSoundFile::SaveSFZInstrument(INSTRUMENTINDEX nInstr, std::ostream &f, cons
if(ins == nullptr)
return false;
const mpt::PathString sampleBaseName = filename.GetFileName();
const mpt::PathString sampleDirName = sampleBaseName + P_("/");
// Creating directory names with trailing spaces or dots is a bad idea, as they are difficult to remove in Windows.
const mpt::RawPathString whitespaceDirName = PL_(" \n\r\t.");
const mpt::PathString sampleBaseName = mpt::PathString::FromNative(mpt::String::Trim(filename.GetFileName().AsNative(), whitespaceDirName));
const mpt::PathString sampleDirName = (sampleBaseName.empty() ? P_("Samples") : sampleBaseName) + P_("/");
const mpt::PathString sampleBasePath = filename.GetPath() + sampleDirName;
if(!sampleBasePath.IsDirectory() && !::CreateDirectory(sampleBasePath.AsNative().c_str(), nullptr))
return false;
@ -1161,7 +1163,7 @@ bool CSoundFile::SaveSFZInstrument(INSTRUMENTINDEX nInstr, std::ostream &f, cons
}
numSamples++;
mpt::PathString sampleName = sampleBasePath + sampleBaseName + P_(" ") + mpt::PathString::FromUnicode(mpt::ufmt::val(numSamples));
mpt::PathString sampleName = sampleBasePath + (sampleBaseName.empty() ? P_("Sample") : sampleBaseName) + P_(" ") + mpt::PathString::FromUnicode(mpt::ufmt::val(numSamples));
if(isAdlib)
sampleName += P_(".s3i");
else if(useFLACsamples)

View File

@ -20,39 +20,39 @@ OPENMPT_NAMESPACE_BEGIN
using ROWINDEX = uint32;
const ROWINDEX ROWINDEX_INVALID = uint32_max;
inline constexpr ROWINDEX ROWINDEX_INVALID = uint32_max;
using CHANNELINDEX = uint16;
const CHANNELINDEX CHANNELINDEX_INVALID = uint16_max;
inline constexpr CHANNELINDEX CHANNELINDEX_INVALID = uint16_max;
using ORDERINDEX = uint16;
const ORDERINDEX ORDERINDEX_INVALID = uint16_max;
const ORDERINDEX ORDERINDEX_MAX = uint16_max - 1;
inline constexpr ORDERINDEX ORDERINDEX_INVALID = uint16_max;
inline constexpr ORDERINDEX ORDERINDEX_MAX = uint16_max - 1;
using PATTERNINDEX = uint16;
const PATTERNINDEX PATTERNINDEX_INVALID = uint16_max;
inline constexpr PATTERNINDEX PATTERNINDEX_INVALID = uint16_max;
using PLUGINDEX = uint8;
const PLUGINDEX PLUGINDEX_INVALID = uint8_max;
inline constexpr PLUGINDEX PLUGINDEX_INVALID = uint8_max;
using SAMPLEINDEX = uint16;
const SAMPLEINDEX SAMPLEINDEX_INVALID = uint16_max;
inline constexpr SAMPLEINDEX SAMPLEINDEX_INVALID = uint16_max;
using INSTRUMENTINDEX = uint16;
const INSTRUMENTINDEX INSTRUMENTINDEX_INVALID = uint16_max;
inline constexpr INSTRUMENTINDEX INSTRUMENTINDEX_INVALID = uint16_max;
using SEQUENCEINDEX = uint8;
const SEQUENCEINDEX SEQUENCEINDEX_INVALID = uint8_max;
inline constexpr SEQUENCEINDEX SEQUENCEINDEX_INVALID = uint8_max;
using SmpLength = uint32;
const SmpLength MAX_SAMPLE_LENGTH = 0x10000000; // Sample length in frames. Sample size in bytes can be more than this (= 256 MB).
inline constexpr SmpLength MAX_SAMPLE_LENGTH = 0x10000000; // Sample length in frames. Sample size in bytes can be more than this (= 256 MB).
const ROWINDEX MAX_PATTERN_ROWS = 1024;
const ORDERINDEX MAX_ORDERS = ORDERINDEX_MAX + 1;
const PATTERNINDEX MAX_PATTERNS = 4000;
const SAMPLEINDEX MAX_SAMPLES = 4000;
const INSTRUMENTINDEX MAX_INSTRUMENTS = 256;
const PLUGINDEX MAX_MIXPLUGINS = 250;
inline constexpr ROWINDEX MAX_PATTERN_ROWS = 1024;
inline constexpr ORDERINDEX MAX_ORDERS = ORDERINDEX_MAX + 1;
inline constexpr PATTERNINDEX MAX_PATTERNS = 4000;
inline constexpr SAMPLEINDEX MAX_SAMPLES = 4000;
inline constexpr INSTRUMENTINDEX MAX_INSTRUMENTS = 256;
inline constexpr PLUGINDEX MAX_MIXPLUGINS = 250;
const SEQUENCEINDEX MAX_SEQUENCES = 50;
inline constexpr SEQUENCEINDEX MAX_SEQUENCES = 50;
const CHANNELINDEX MAX_BASECHANNELS = 127; // Maximum pattern channels.
const CHANNELINDEX MAX_CHANNELS = 256; // Maximum number of mixing channels.
inline constexpr CHANNELINDEX MAX_BASECHANNELS = 127; // Maximum pattern channels.
inline constexpr CHANNELINDEX MAX_CHANNELS = 256; // Maximum number of mixing channels.
enum { FREQ_FRACBITS = 4 }; // Number of fractional bits in return value of CSoundFile::GetFreqFromPeriod()
@ -323,22 +323,22 @@ enum class AmigaFilter
Unfiltered = 3,
};
static inline std::array<ResamplingMode, 5> AllModes() noexcept { return { { SRCMODE_NEAREST, SRCMODE_LINEAR, SRCMODE_CUBIC, SRCMODE_SINC8, SRCMODE_SINC8LP } }; }
inline std::array<ResamplingMode, 5> AllModes() noexcept { return { { SRCMODE_NEAREST, SRCMODE_LINEAR, SRCMODE_CUBIC, SRCMODE_SINC8, SRCMODE_SINC8LP } }; }
static inline std::array<ResamplingMode, 6> AllModesWithDefault() noexcept { return { { SRCMODE_NEAREST, SRCMODE_LINEAR, SRCMODE_CUBIC, SRCMODE_SINC8, SRCMODE_SINC8LP, SRCMODE_DEFAULT } }; }
inline std::array<ResamplingMode, 6> AllModesWithDefault() noexcept { return { { SRCMODE_NEAREST, SRCMODE_LINEAR, SRCMODE_CUBIC, SRCMODE_SINC8, SRCMODE_SINC8LP, SRCMODE_DEFAULT } }; }
static constexpr ResamplingMode Default() noexcept { return SRCMODE_SINC8LP; }
constexpr ResamplingMode Default() noexcept { return SRCMODE_SINC8LP; }
static constexpr bool IsKnownMode(int mode) noexcept { return (mode >= 0) && (mode < SRCMODE_DEFAULT); }
constexpr bool IsKnownMode(int mode) noexcept { return (mode >= 0) && (mode < SRCMODE_DEFAULT); }
static constexpr ResamplingMode ToKnownMode(int mode) noexcept
constexpr ResamplingMode ToKnownMode(int mode) noexcept
{
return Resampling::IsKnownMode(mode) ? static_cast<ResamplingMode>(mode)
: (mode == SRCMODE_AMIGA) ? SRCMODE_LINEAR
: Resampling::Default();
}
static constexpr int Length(ResamplingMode mode) noexcept
constexpr int Length(ResamplingMode mode) noexcept
{
return mode == SRCMODE_NEAREST ? 1
: mode == SRCMODE_LINEAR ? 2
@ -348,11 +348,11 @@ static constexpr int Length(ResamplingMode mode) noexcept
: 0;
}
static constexpr bool HasAA(ResamplingMode mode) noexcept { return (mode == SRCMODE_SINC8LP); }
constexpr bool HasAA(ResamplingMode mode) noexcept { return (mode == SRCMODE_SINC8LP); }
static constexpr ResamplingMode AddAA(ResamplingMode mode) noexcept { return (mode == SRCMODE_SINC8) ? SRCMODE_SINC8LP : mode; }
constexpr ResamplingMode AddAA(ResamplingMode mode) noexcept { return (mode == SRCMODE_SINC8) ? SRCMODE_SINC8LP : mode; }
static constexpr ResamplingMode RemoveAA(ResamplingMode mode) noexcept { return (mode == SRCMODE_SINC8LP) ? SRCMODE_SINC8 : mode; }
constexpr ResamplingMode RemoveAA(ResamplingMode mode) noexcept { return (mode == SRCMODE_SINC8LP) ? SRCMODE_SINC8 : mode; }
}

View File

@ -258,14 +258,10 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
RowVisitor visitedRows(*this, sequence);
// If sequence starts with some non-existent patterns, find a better start
while(target.startOrder < orderList.size() && !orderList.IsValidPat(target.startOrder))
{
ORDERINDEX startOrder = target.startOrder;
ROWINDEX startRow = target.startRow;
if(visitedRows.GetFirstUnvisitedRow(startOrder, startRow, true))
{
target.startOrder = startOrder;
target.startRow = startRow;
}
target.startOrder++;
target.startRow = 0;
}
retval.startRow = playState.m_nNextRow = playState.m_nRow = target.startRow;
retval.startOrder = playState.m_nNextOrder = playState.m_nCurrentOrder = target.startOrder;
@ -1153,12 +1149,12 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
if(m.param == 0x9E)
{
// Play forward
memory.RenderChannel(nChn, oldTickDuration); // Re-sync what we've got so far
memory.RenderChannel(nChn, oldTickDuration); // Re-sync what we've got so far
chn.dwFlags.reset(CHN_PINGPONGFLAG);
} else if(m.param == 0x9F)
{
// Reverse
memory.RenderChannel(nChn, oldTickDuration); // Re-sync what we've got so far
memory.RenderChannel(nChn, oldTickDuration); // Re-sync what we've got so far
chn.dwFlags.set(CHN_PINGPONGFLAG);
if(!chn.position.GetInt() && chn.nLength && (m.IsNote() || !chn.dwFlags[CHN_LOOP]))
{
@ -1166,8 +1162,8 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
}
} else if((m.param & 0xF0) == 0x70)
{
// TODO
//ExtendedS3MCommands(nChn, param);
if(m.param >= 0x73)
chn.InstrumentControl(m.param, *this);
}
break;
}
@ -1305,7 +1301,7 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
m_PlayState.ResetGlobalVolumeRamping();
m_PlayState.m_nNextRow = m_PlayState.m_nRow;
m_PlayState.m_nFrameDelay = m_PlayState.m_nPatternDelay = 0;
m_PlayState.m_nTickCount = Util::MaxValueOfType(m_PlayState.m_nTickCount) - 1;
m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
m_PlayState.m_bPositionChanged = true;
if(m_opl != nullptr)
m_opl->Reset();
@ -3713,10 +3709,19 @@ void CSoundFile::UpdateS3MEffectMemory(ModChannel &chn, ModCommand::PARAM param)
// Calculate full parameter for effects that support parameter extension at the given pattern location.
// maxCommands sets the maximum number of XParam commands to look at for this effect
// isExtended returns if the command is actually using any XParam extensions.
// extendedRows returns how many extended rows are used (i.e. a value of 0 means the command is not extended).
uint32 CSoundFile::CalculateXParam(PATTERNINDEX pat, ROWINDEX row, CHANNELINDEX chn, bool *isExtended) const
{
if(isExtended != nullptr) *isExtended = false;
if(!Patterns.IsValidPat(pat))
{
#ifdef MPT_BUILD_FUZZER
// Ending up in this situation implies a logic error
std::abort();
#else
return 0;
#endif
}
ROWINDEX maxCommands = 4;
const ModCommand *m = Patterns[pat].GetpModCommand(row, chn);
uint32 val = m->param;
@ -4817,23 +4822,8 @@ void CSoundFile::ExtendedS3MCommands(CHANNELINDEX nChn, ModCommand::PARAM param)
}
}
break;
case 3: chn.nNNA = NNA_NOTECUT; break;
case 4: chn.nNNA = NNA_CONTINUE; break;
case 5: chn.nNNA = NNA_NOTEOFF; break;
case 6: chn.nNNA = NNA_NOTEFADE; break;
case 7: chn.VolEnv.flags.reset(ENV_ENABLED); break;
case 8: chn.VolEnv.flags.set(ENV_ENABLED); break;
case 9: chn.PanEnv.flags.reset(ENV_ENABLED); break;
case 10: chn.PanEnv.flags.set(ENV_ENABLED); break;
case 11: chn.PitchEnv.flags.reset(ENV_ENABLED); break;
case 12: chn.PitchEnv.flags.set(ENV_ENABLED); break;
case 13: // S7D: Enable pitch envelope, force to play as pitch envelope
case 14: // S7E: Enable pitch envelope, force to play as filter envelope
if(GetType() == MOD_TYPE_MPT)
{
chn.PitchEnv.flags.set(ENV_ENABLED);
chn.PitchEnv.flags.set(ENV_FILTER, param != 13);
}
default: // S73-S7E
chn.InstrumentControl(param, *this);
break;
}
break;

View File

@ -561,7 +561,7 @@ bool CSoundFile::Create(FileReader file, ModLoadingFlags loadFlags)
m_PlayState.m_nPattern = 0;
m_PlayState.m_nBufferCount = 0;
m_PlayState.m_dBufferDiff = 0;
m_PlayState.m_nTickCount = m_PlayState.m_nMusicSpeed;
m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
m_PlayState.m_nNextRow = 0;
m_PlayState.m_nRow = 0;
m_PlayState.m_nPatternDelay = 0;
@ -785,7 +785,7 @@ void CSoundFile::ResetPlayPos()
m_PlayState.m_nNextOrder = 0;
m_PlayState.m_nNextRow = 0;
m_PlayState.m_nTickCount = m_PlayState.m_nMusicSpeed;
m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
m_PlayState.m_nBufferCount = 0;
m_PlayState.m_nPatternDelay = 0;
m_PlayState.m_nFrameDelay = 0;
@ -833,7 +833,7 @@ void CSoundFile::SetCurrentOrder(ORDERINDEX nOrder)
m_PlayState.m_nNextOrder = nOrder;
m_PlayState.m_nRow = m_PlayState.m_nNextRow = 0;
m_PlayState.m_nPattern = 0;
m_PlayState.m_nTickCount = m_PlayState.m_nMusicSpeed;
m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
m_PlayState.m_nBufferCount = 0;
m_PlayState.m_nPatternDelay = 0;
m_PlayState.m_nFrameDelay = 0;
@ -963,7 +963,7 @@ void CSoundFile::LoopPattern(PATTERNINDEX nPat, ROWINDEX nRow)
if(nRow >= Patterns[nPat].GetNumRows()) nRow = 0;
m_PlayState.m_nPattern = nPat;
m_PlayState.m_nRow = m_PlayState.m_nNextRow = nRow;
m_PlayState.m_nTickCount = m_PlayState.m_nMusicSpeed;
m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
m_PlayState.m_nPatternDelay = 0;
m_PlayState.m_nFrameDelay = 0;
m_PlayState.m_nNextPatStartRow = 0;
@ -979,7 +979,7 @@ void CSoundFile::DontLoopPattern(PATTERNINDEX nPat, ROWINDEX nRow)
if(nRow >= Patterns[nPat].GetNumRows()) nRow = 0;
m_PlayState.m_nPattern = nPat;
m_PlayState.m_nRow = m_PlayState.m_nNextRow = nRow;
m_PlayState.m_nTickCount = m_PlayState.m_nMusicSpeed;
m_PlayState.m_nTickCount = TICKS_ROW_FINISHED;
m_PlayState.m_nPatternDelay = 0;
m_PlayState.m_nFrameDelay = 0;
m_PlayState.m_nBufferCount = 0;

View File

@ -411,6 +411,8 @@ public:
using samplecount_t = uint32; // Number of rendered samples
static constexpr uint32 TICKS_ROW_FINISHED = uint32_max - 1u;
public: // for Editing
#ifdef MODPLUG_TRACKER
CModDoc *m_pModDoc = nullptr; // Can be a null pointer for example when previewing samples from the treeview.
@ -1190,8 +1192,8 @@ inline IMixPlugin* CSoundFile::GetInstrumentPlugin(INSTRUMENTINDEX instr) const
#define FADESONGDELAY 100
static MPT_CONSTEXPR11_FUN int8 MOD2XMFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) << 4); }
static MPT_CONSTEXPR11_FUN int8 XM2MODFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) >> 4); }
MPT_CONSTEXPR11_FUN int8 MOD2XMFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) << 4); }
MPT_CONSTEXPR11_FUN int8 XM2MODFineTune(int v) { return static_cast<int8>(static_cast<uint8>(v) >> 4); }
// Read instrument property with 'code' and 'size' from 'file' to instrument 'pIns'.
void ReadInstrumentExtensionField(ModInstrument* pIns, const uint32 code, const uint16 size, FileReader &file);

View File

@ -362,6 +362,7 @@ void LFOPlugin::SetChunk(const ChunkData &chunk, bool)
m_bypassed = data.bypassed != 0;
m_outputToCC = data.outputToCC != 0;
m_oneshot = data.loopMode != 0;
RecalculateFrequency();
}
}

View File

@ -15,7 +15,7 @@
OPENMPT_NAMESPACE_BEGIN
#ifndef NO_VST
static constexpr const char *VstOpCodes[] =
inline constexpr const char *VstOpCodes[] =
{
"effOpen",
"effClose",

View File

@ -50,14 +50,14 @@ struct NoteRange
// Derived from old IsStepCountRangeSufficient(), this is actually a more
// sensible value than what was calculated in earlier versions.
static constexpr STEPINDEXTYPE FINESTEPCOUNT_MAX = 0xffff;
inline constexpr STEPINDEXTYPE FINESTEPCOUNT_MAX = 0xffff;
static constexpr auto NOTEINDEXTYPE_MIN = std::numeric_limits<NOTEINDEXTYPE>::min();
static constexpr auto NOTEINDEXTYPE_MAX = std::numeric_limits<NOTEINDEXTYPE>::max();
static constexpr auto UNOTEINDEXTYPE_MAX = std::numeric_limits<UNOTEINDEXTYPE>::max();
static constexpr auto STEPINDEXTYPE_MIN = std::numeric_limits<STEPINDEXTYPE>::min();
static constexpr auto STEPINDEXTYPE_MAX = std::numeric_limits<STEPINDEXTYPE>::max();
static constexpr auto USTEPINDEXTYPE_MAX = std::numeric_limits<USTEPINDEXTYPE>::max();
inline constexpr auto NOTEINDEXTYPE_MIN = std::numeric_limits<NOTEINDEXTYPE>::min();
inline constexpr auto NOTEINDEXTYPE_MAX = std::numeric_limits<NOTEINDEXTYPE>::max();
inline constexpr auto UNOTEINDEXTYPE_MAX = std::numeric_limits<UNOTEINDEXTYPE>::max();
inline constexpr auto STEPINDEXTYPE_MIN = std::numeric_limits<STEPINDEXTYPE>::min();
inline constexpr auto STEPINDEXTYPE_MAX = std::numeric_limits<STEPINDEXTYPE>::max();
inline constexpr auto USTEPINDEXTYPE_MAX = std::numeric_limits<USTEPINDEXTYPE>::max();
enum class Type : uint16