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

View File

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

View File

@ -13,9 +13,11 @@ CPPFLAGS += -DWIN32 -D_WIN32
CXXFLAGS += -municode -mconsole CXXFLAGS += -municode -mconsole
CFLAGS += -municode -mconsole CFLAGS += -municode -mconsole
LDFLAGS += LDFLAGS +=
LDLIBS += -lm -lrpcrt4 -lwinmm LDLIBS += -lm -lole32 -lrpcrt4 -lwinmm
ARFLAGS := rcs 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 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 EXESUFFIX=.exe

View File

@ -13,9 +13,11 @@ CPPFLAGS += -DWIN32 -D_WIN32 -DWIN64 -D_WIN64
CXXFLAGS += -municode -mconsole CXXFLAGS += -municode -mconsole
CFLAGS += -municode -mconsole CFLAGS += -municode -mconsole
LDFLAGS += LDFLAGS +=
LDLIBS += -lm -lrpcrt4 -lwinmm LDLIBS += -lm -lole32 -lrpcrt4 -lwinmm
ARFLAGS := rcs 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 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 EXESUFFIX=.exe

View File

@ -16,6 +16,8 @@ LDFLAGS +=
LDLIBS += -lm -lole32 -lwinmm LDLIBS += -lm -lole32 -lwinmm
ARFLAGS := rcs 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 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 EXESUFFIX=.exe

View File

@ -13,9 +13,11 @@ CPPFLAGS += -DWIN32 -D_WIN32 -DWINAPI_FAMILY=0x2 -D_WIN32_WINNT=0x0602
CXXFLAGS += -municode -mconsole CXXFLAGS += -municode -mconsole
CFLAGS += -municode -mconsole CFLAGS += -municode -mconsole
LDFLAGS += LDFLAGS +=
LDLIBS += -lm -lole32 -lwinmm LDLIBS += -lm -lole32 -lrpcrt4 -lwinmm
ARFLAGS := rcs 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 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 EXESUFFIX=.exe

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#define OPENMPT_VERSION_SVNVERSION "14391" #define OPENMPT_VERSION_SVNVERSION "14580"
#define OPENMPT_VERSION_REVISION 14391 #define OPENMPT_VERSION_REVISION 14580
#define OPENMPT_VERSION_DIRTY 0 #define OPENMPT_VERSION_DIRTY 0
#define OPENMPT_VERSION_MIXEDREVISIONS 0 #define OPENMPT_VERSION_MIXEDREVISIONS 0
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.7" #define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.8"
#define OPENMPT_VERSION_DATE "2021-03-20T17:06:12.434258Z" #define OPENMPT_VERSION_DATE "2021-04-11T14:02:18.903044Z"
#define OPENMPT_VERSION_IS_PACKAGE 1 #define OPENMPT_VERSION_IS_PACKAGE 1

View File

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

View File

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

View File

@ -45,6 +45,7 @@ extern uint32 RealProcSupport;
extern uint32 ProcSupport; extern uint32 ProcSupport;
extern char ProcVendorID[16+1]; extern char ProcVendorID[16+1];
extern char ProcBrandID[4*4*3+1]; extern char ProcBrandID[4*4*3+1];
extern uint32 ProcRawCPUID;
extern uint16 ProcFamily; extern uint16 ProcFamily;
extern uint8 ProcModel; extern uint8 ProcModel;
extern uint8 ProcStepping; 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. // Version definitions. The only thing that needs to be changed when changing version number.
#define VER_MAJORMAJOR 1 #define VER_MAJORMAJOR 1
#define VER_MAJOR 29 #define VER_MAJOR 29
#define VER_MINOR 08 #define VER_MINOR 09
#define VER_MINORMINOR 03 #define VER_MINORMINOR 00
OPENMPT_NAMESPACE_END OPENMPT_NAMESPACE_END

View File

@ -5,6 +5,27 @@ Changelog {#changelog}
For fully detailed change log, please see the source repository directly. This For fully detailed change log, please see the source repository directly. This
is just a high-level summary. 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) ### libopenmpt 0.5.7 (2021-03-20)
* [**Sec**] Possible null-pointer dereference read caused by a sequence of * [**Sec**] Possible null-pointer dereference read caused by a sequence of

View File

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

View File

@ -194,6 +194,7 @@ class interactive {
//! Gets the current module pitch factor //! Gets the current module pitch factor
/*! /*!
\return The current 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 \sa openmpt::ext::interactive::set_pitch_factor
*/ */
virtual double get_pitch_factor( ) const = 0; virtual double get_pitch_factor( ) const = 0;
@ -283,7 +284,7 @@ class interactive {
//! Stop the note playing on the specified channel //! 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. \throws openmpt::exception Throws an exception derived from openmpt::exception if the channel index is invalid.
\sa openmpt::ext::interactive::play_note \sa openmpt::ext::interactive::play_note
*/ */

View File

@ -256,19 +256,9 @@ namespace openmpt {
} }
// Find a free channel // Find a free channel
CHANNELINDEX free_channel = MAX_CHANNELS - 1; CHANNELINDEX free_channel = m_sndFile->GetNNAChannel( CHANNELINDEX_INVALID );
// Search for available channel if ( free_channel == CHANNELINDEX_INVALID )
for(CHANNELINDEX i = MAX_CHANNELS - 1; i >= get_num_channels(); i--) free_channel = MAX_CHANNELS - 1;
{
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;
}
}
ModChannel &chn = m_sndFile->m_PlayState.Chn[free_channel]; ModChannel &chn = m_sndFile->m_PlayState.Chn[free_channel];
chn.Reset(ModChannel::resetTotal, *m_sndFile, CHANNELINDEX_INVALID); chn.Reset(ModChannel::resetTotal, *m_sndFile, CHANNELINDEX_INVALID);

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(); 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_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_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; m_currentPositionSeconds = base_seconds + t.duration;
return m_currentPositionSeconds; 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->m_PlayState.m_nCurrentOrder = static_cast<ORDERINDEX>( order );
m_sndFile->SetCurrentOrder( 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_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; 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; return m_currentPositionSeconds;
} }

View File

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

View File

@ -19,7 +19,7 @@
/*! \brief libopenmpt minor version number */ /*! \brief libopenmpt minor version number */
#define OPENMPT_API_VERSION_MINOR 5 #define OPENMPT_API_VERSION_MINOR 5
/*! \brief libopenmpt patch version number */ /*! \brief libopenmpt patch version number */
#define OPENMPT_API_VERSION_PATCH 7 #define OPENMPT_API_VERSION_PATCH 8
/*! \brief libopenmpt pre-release tag */ /*! \brief libopenmpt pre-release tag */
#define OPENMPT_API_VERSION_PREREL "" #define OPENMPT_API_VERSION_PREREL ""
/*! \brief libopenmpt pre-release flag */ /*! \brief libopenmpt pre-release flag */

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@ using mixsample_t = AudioSampleFloat;
enum { MIXING_ATTENUATION = MixSampleIntTraits::mix_headroom_bits() }; enum { MIXING_ATTENUATION = MixSampleIntTraits::mix_headroom_bits() };
enum { MIXING_FRACTIONAL_BITS = MixSampleIntTraits::mix_fractional_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 #ifdef MPT_INTMIXER
static_assert(sizeof(mixsample_t) == 4); 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 OPENMPT_NAMESPACE_END

View File

@ -196,6 +196,9 @@ struct ModChannel
void SetInstrumentPan(int32 pan, const CSoundFile &sndFile); void SetInstrumentPan(int32 pan, const CSoundFile &sndFile);
void RecalcTuningFreq(Tuning::RATIOTYPE vibratoFactor, Tuning::NOTEINDEXTYPE arpeggioSteps, 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 namespace Paula
{ {
constexpr int PAULA_HZ = 3546895; inline constexpr int PAULA_HZ = 3546895;
constexpr int MINIMUM_INTERVAL = 4; // Tradeoff between quality and speed (lower = less aliasing) inline 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 inline constexpr int BLEP_SCALE = 17; // TODO: Should be 1 for float mixer
constexpr int BLEP_SIZE = 2048; inline constexpr int BLEP_SIZE = 2048;
using BlepArray = std::array<mixsample_t, BLEP_SIZE>; using BlepArray = std::array<mixsample_t, BLEP_SIZE>;

View File

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

View File

@ -20,39 +20,39 @@ OPENMPT_NAMESPACE_BEGIN
using ROWINDEX = uint32; using ROWINDEX = uint32;
const ROWINDEX ROWINDEX_INVALID = uint32_max; inline constexpr ROWINDEX ROWINDEX_INVALID = uint32_max;
using CHANNELINDEX = uint16; using CHANNELINDEX = uint16;
const CHANNELINDEX CHANNELINDEX_INVALID = uint16_max; inline constexpr CHANNELINDEX CHANNELINDEX_INVALID = uint16_max;
using ORDERINDEX = uint16; using ORDERINDEX = uint16;
const ORDERINDEX ORDERINDEX_INVALID = uint16_max; inline constexpr ORDERINDEX ORDERINDEX_INVALID = uint16_max;
const ORDERINDEX ORDERINDEX_MAX = uint16_max - 1; inline constexpr ORDERINDEX ORDERINDEX_MAX = uint16_max - 1;
using PATTERNINDEX = uint16; using PATTERNINDEX = uint16;
const PATTERNINDEX PATTERNINDEX_INVALID = uint16_max; inline constexpr PATTERNINDEX PATTERNINDEX_INVALID = uint16_max;
using PLUGINDEX = uint8; using PLUGINDEX = uint8;
const PLUGINDEX PLUGINDEX_INVALID = uint8_max; inline constexpr PLUGINDEX PLUGINDEX_INVALID = uint8_max;
using SAMPLEINDEX = uint16; using SAMPLEINDEX = uint16;
const SAMPLEINDEX SAMPLEINDEX_INVALID = uint16_max; inline constexpr SAMPLEINDEX SAMPLEINDEX_INVALID = uint16_max;
using INSTRUMENTINDEX = uint16; using INSTRUMENTINDEX = uint16;
const INSTRUMENTINDEX INSTRUMENTINDEX_INVALID = uint16_max; inline constexpr INSTRUMENTINDEX INSTRUMENTINDEX_INVALID = uint16_max;
using SEQUENCEINDEX = uint8; using SEQUENCEINDEX = uint8;
const SEQUENCEINDEX SEQUENCEINDEX_INVALID = uint8_max; inline constexpr SEQUENCEINDEX SEQUENCEINDEX_INVALID = uint8_max;
using SmpLength = uint32; 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; inline constexpr ROWINDEX MAX_PATTERN_ROWS = 1024;
const ORDERINDEX MAX_ORDERS = ORDERINDEX_MAX + 1; inline constexpr ORDERINDEX MAX_ORDERS = ORDERINDEX_MAX + 1;
const PATTERNINDEX MAX_PATTERNS = 4000; inline constexpr PATTERNINDEX MAX_PATTERNS = 4000;
const SAMPLEINDEX MAX_SAMPLES = 4000; inline constexpr SAMPLEINDEX MAX_SAMPLES = 4000;
const INSTRUMENTINDEX MAX_INSTRUMENTS = 256; inline constexpr INSTRUMENTINDEX MAX_INSTRUMENTS = 256;
const PLUGINDEX MAX_MIXPLUGINS = 250; 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. inline constexpr CHANNELINDEX MAX_BASECHANNELS = 127; // Maximum pattern channels.
const CHANNELINDEX MAX_CHANNELS = 256; // Maximum number of mixing 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() enum { FREQ_FRACBITS = 4 }; // Number of fractional bits in return value of CSoundFile::GetFreqFromPeriod()
@ -323,22 +323,22 @@ enum class AmigaFilter
Unfiltered = 3, 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) return Resampling::IsKnownMode(mode) ? static_cast<ResamplingMode>(mode)
: (mode == SRCMODE_AMIGA) ? SRCMODE_LINEAR : (mode == SRCMODE_AMIGA) ? SRCMODE_LINEAR
: Resampling::Default(); : Resampling::Default();
} }
static constexpr int Length(ResamplingMode mode) noexcept constexpr int Length(ResamplingMode mode) noexcept
{ {
return mode == SRCMODE_NEAREST ? 1 return mode == SRCMODE_NEAREST ? 1
: mode == SRCMODE_LINEAR ? 2 : mode == SRCMODE_LINEAR ? 2
@ -348,11 +348,11 @@ static constexpr int Length(ResamplingMode mode) noexcept
: 0; : 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); RowVisitor visitedRows(*this, sequence);
// If sequence starts with some non-existent patterns, find a better start // 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; target.startOrder++;
ROWINDEX startRow = target.startRow; target.startRow = 0;
if(visitedRows.GetFirstUnvisitedRow(startOrder, startRow, true))
{
target.startOrder = startOrder;
target.startRow = startRow;
}
} }
retval.startRow = playState.m_nNextRow = playState.m_nRow = target.startRow; retval.startRow = playState.m_nNextRow = playState.m_nRow = target.startRow;
retval.startOrder = playState.m_nNextOrder = playState.m_nCurrentOrder = target.startOrder; retval.startOrder = playState.m_nNextOrder = playState.m_nCurrentOrder = target.startOrder;
@ -1166,8 +1162,8 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
} }
} else if((m.param & 0xF0) == 0x70) } else if((m.param & 0xF0) == 0x70)
{ {
// TODO if(m.param >= 0x73)
//ExtendedS3MCommands(nChn, param); chn.InstrumentControl(m.param, *this);
} }
break; break;
} }
@ -1305,7 +1301,7 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
m_PlayState.ResetGlobalVolumeRamping(); m_PlayState.ResetGlobalVolumeRamping();
m_PlayState.m_nNextRow = m_PlayState.m_nRow; m_PlayState.m_nNextRow = m_PlayState.m_nRow;
m_PlayState.m_nFrameDelay = m_PlayState.m_nPatternDelay = 0; 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; m_PlayState.m_bPositionChanged = true;
if(m_opl != nullptr) if(m_opl != nullptr)
m_opl->Reset(); 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. // 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 // 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 uint32 CSoundFile::CalculateXParam(PATTERNINDEX pat, ROWINDEX row, CHANNELINDEX chn, bool *isExtended) const
{ {
if(isExtended != nullptr) *isExtended = false; 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; ROWINDEX maxCommands = 4;
const ModCommand *m = Patterns[pat].GetpModCommand(row, chn); const ModCommand *m = Patterns[pat].GetpModCommand(row, chn);
uint32 val = m->param; uint32 val = m->param;
@ -4817,23 +4822,8 @@ void CSoundFile::ExtendedS3MCommands(CHANNELINDEX nChn, ModCommand::PARAM param)
} }
} }
break; break;
case 3: chn.nNNA = NNA_NOTECUT; break; default: // S73-S7E
case 4: chn.nNNA = NNA_CONTINUE; break; chn.InstrumentControl(param, *this);
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);
}
break; break;
} }
break; break;

View File

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

View File

@ -411,6 +411,8 @@ public:
using samplecount_t = uint32; // Number of rendered samples using samplecount_t = uint32; // Number of rendered samples
static constexpr uint32 TICKS_ROW_FINISHED = uint32_max - 1u;
public: // for Editing public: // for Editing
#ifdef MODPLUG_TRACKER #ifdef MODPLUG_TRACKER
CModDoc *m_pModDoc = nullptr; // Can be a null pointer for example when previewing samples from the treeview. 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 #define FADESONGDELAY 100
static MPT_CONSTEXPR11_FUN int8 MOD2XMFineTune(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); }
static MPT_CONSTEXPR11_FUN int8 XM2MODFineTune(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'. // Read instrument property with 'code' and 'size' from 'file' to instrument 'pIns'.
void ReadInstrumentExtensionField(ModInstrument* pIns, const uint32 code, const uint16 size, FileReader &file); 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_bypassed = data.bypassed != 0;
m_outputToCC = data.outputToCC != 0; m_outputToCC = data.outputToCC != 0;
m_oneshot = data.loopMode != 0; m_oneshot = data.loopMode != 0;
RecalculateFrequency();
} }
} }

View File

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

View File

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