libOpenMPT Legacy: Updated to version 0.5.17
Signed-off-by: Christopher Snowhill <kode54@gmail.com>CQTexperiment
parent
aa28b2beb1
commit
3815ba0baf
|
@ -1,4 +1,4 @@
|
|||
|
||||
MPT_SVNVERSION=16768
|
||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.16
|
||||
MPT_SVNDATE=2022-01-30T16:50:10.915999Z
|
||||
MPT_SVNVERSION=17112
|
||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.17
|
||||
MPT_SVNDATE=2022-03-13T14:51:00.976461Z
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
#pragma once
|
||||
#define OPENMPT_VERSION_SVNVERSION "16768"
|
||||
#define OPENMPT_VERSION_REVISION 16768
|
||||
#define OPENMPT_VERSION_SVNVERSION "17112"
|
||||
#define OPENMPT_VERSION_REVISION 17112
|
||||
#define OPENMPT_VERSION_DIRTY 0
|
||||
#define OPENMPT_VERSION_MIXEDREVISIONS 0
|
||||
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.16"
|
||||
#define OPENMPT_VERSION_DATE "2022-01-30T16:50:10.915999Z"
|
||||
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.5.17"
|
||||
#define OPENMPT_VERSION_DATE "2022-03-13T14:51:00.976461Z"
|
||||
#define OPENMPT_VERSION_IS_PACKAGE 1
|
||||
|
||||
|
|
|
@ -18,6 +18,6 @@ OPENMPT_NAMESPACE_BEGIN
|
|||
#define VER_MAJORMAJOR 1
|
||||
#define VER_MAJOR 29
|
||||
#define VER_MINOR 15
|
||||
#define VER_MINORMINOR 04
|
||||
#define VER_MINORMINOR 06
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
||||
|
|
|
@ -5,6 +5,21 @@ Changelog {#changelog}
|
|||
For fully detailed change log, please see the source repository directly. This
|
||||
is just a high-level summary.
|
||||
|
||||
### libopenmpt 0.5.17 (2022-03-13)
|
||||
|
||||
* [**Sec**] Possible out-of-bounds write in malformed IT / XM / MPTM files
|
||||
using the internal LFO plugin. (r17081)
|
||||
* [**Sec**] Possible out-of-bounds read when using Amiga BLEP interpolation
|
||||
with extremely high-pitched notes. (r17082)
|
||||
|
||||
* MO3: Pattern indices 254 / 255 were not treated as playable patterns even if
|
||||
the original file was a MOD / XM.
|
||||
* Correctly apply ST3-style effect memory when seeking in S3M files.
|
||||
* Command S (S3M / IT style) effect memory was not applied when seeking.
|
||||
|
||||
* FLAC: Update to v1.3.4 (2022-02-21).
|
||||
* pugixml: Update to v1.12.1 (2022-02-16).
|
||||
|
||||
### libopenmpt 0.5.16 (2022-01-30)
|
||||
|
||||
* [**Bug**] Possible hang with malformed DMF, DSM, MED and OKT files
|
||||
|
|
|
@ -127,12 +127,12 @@
|
|||
|
||||
/*! \defgroup libopenmpt_cpp libopenmpt C++ */
|
||||
|
||||
namespace openmpt {
|
||||
|
||||
/*! \addtogroup libopenmpt_cpp
|
||||
@{
|
||||
*/
|
||||
|
||||
namespace openmpt {
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4275)
|
||||
|
@ -1163,10 +1163,10 @@ public:
|
|||
|
||||
}; // class module
|
||||
|
||||
} // namespace openmpt
|
||||
|
||||
/*!
|
||||
@}
|
||||
*/
|
||||
|
||||
} // namespace openmpt
|
||||
|
||||
#endif // LIBOPENMPT_HPP
|
||||
|
|
|
@ -22,6 +22,14 @@
|
|||
#define LIBOPENMPT_CXX_API
|
||||
#undef LIBOPENMPT_CXX_API
|
||||
|
||||
/*!
|
||||
@}
|
||||
*/
|
||||
|
||||
/*! \addtogroup libopenmpt_c
|
||||
@{
|
||||
*/
|
||||
|
||||
/*! \brief Defined if libopenmpt/libopenmpt_stream_callbacks_buffer.h exists. */
|
||||
#define LIBOPENMPT_STREAM_CALLBACKS_BUFFER
|
||||
|
||||
|
@ -51,6 +59,14 @@
|
|||
*/
|
||||
#define LIBOPENMPT_STREAM_CALLBACKS_FILE
|
||||
|
||||
/*!
|
||||
@}
|
||||
*/
|
||||
|
||||
/*! \addtogroup libopenmpt
|
||||
@{
|
||||
*/
|
||||
|
||||
#if defined(__DOXYGEN__)
|
||||
|
||||
#define LIBOPENMPT_API_HELPER_EXPORT
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
|
||||
/*! \defgroup libopenmpt_ext_cpp libopenmpt_ext C++ */
|
||||
|
||||
namespace openmpt {
|
||||
|
||||
/*! \addtogroup libopenmpt_ext_cpp
|
||||
@{
|
||||
*/
|
||||
|
||||
namespace openmpt {
|
||||
|
||||
class module_ext_impl;
|
||||
|
||||
class LIBOPENMPT_CXX_API module_ext : public module {
|
||||
|
@ -77,8 +77,16 @@ public:
|
|||
|
||||
}; // class module_ext
|
||||
|
||||
/*!
|
||||
@}
|
||||
*/
|
||||
|
||||
namespace ext {
|
||||
|
||||
/*! \addtogroup libopenmpt_ext_cpp
|
||||
@{
|
||||
*/
|
||||
|
||||
#define LIBOPENMPT_DECLARE_EXT_CXX_INTERFACE(name) \
|
||||
static const char name ## _id [] = # name ; \
|
||||
class name; \
|
||||
|
@ -300,12 +308,12 @@ class interactive {
|
|||
#undef LIBOPENMPT_DECLARE_EXT_CXX_INTERFACE
|
||||
#undef LIBOPENMPT_EXT_CXX_INTERFACE
|
||||
|
||||
} // namespace ext
|
||||
|
||||
} // namespace openmpt
|
||||
|
||||
/*!
|
||||
@}
|
||||
*/
|
||||
|
||||
} // namespace ext
|
||||
|
||||
} // namespace openmpt
|
||||
|
||||
#endif // LIBOPENMPT_EXT_HPP
|
||||
|
|
|
@ -34,12 +34,20 @@
|
|||
#include "soundlib/mod_specifications.h"
|
||||
#include "soundlib/AudioReadTarget.h"
|
||||
|
||||
#if MPT_OS_WINDOWS && MPT_OS_WINDOWS_WINRT
|
||||
#include <windows.h>
|
||||
#endif // MPT_OS_WINDOWS && MPT_OS_WINDOWS_WINRT
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
#if !defined(MPT_BUILD_SILENCE_LIBOPENMPT_CONFIGURATION_WARNINGS)
|
||||
|
||||
#if MPT_OS_WINDOWS && MPT_OS_WINDOWS_WINRT
|
||||
#if defined(_WIN32_WINNT)
|
||||
#if defined(NTDDI_VERSION)
|
||||
#if (NTDDI_VERSION < 0x06020000)
|
||||
MPT_WARNING("Warning: libopenmpt for WinRT is built with reduced functionality. Please #define NTDDI_VERSION 0x0602000.")
|
||||
#endif
|
||||
#elif defined(_WIN32_WINNT)
|
||||
#if (_WIN32_WINNT < 0x0602)
|
||||
MPT_WARNING("Warning: libopenmpt for WinRT is built with reduced functionality. Please #define _WIN32_WINNT 0x0602.")
|
||||
#endif // _WIN32_WINNT
|
||||
|
|
|
@ -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 16
|
||||
#define OPENMPT_API_VERSION_PATCH 17
|
||||
/*! \brief libopenmpt pre-release tag */
|
||||
#define OPENMPT_API_VERSION_PREREL ""
|
||||
/*! \brief libopenmpt pre-release flag */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
LIBOPENMPT_VERSION_MAJOR=0
|
||||
LIBOPENMPT_VERSION_MINOR=5
|
||||
LIBOPENMPT_VERSION_PATCH=16
|
||||
LIBOPENMPT_VERSION_PATCH=17
|
||||
LIBOPENMPT_VERSION_PREREL=
|
||||
|
||||
LIBOPENMPT_LTVER_CURRENT=2
|
||||
LIBOPENMPT_LTVER_REVISION=16
|
||||
LIBOPENMPT_LTVER_REVISION=17
|
||||
LIBOPENMPT_LTVER_AGE=2
|
||||
|
|
|
@ -41,9 +41,7 @@ typedef IntToFloatTraits<2, 2, mixsample_t, int16, -int16_min> Int16SToFloatS;
|
|||
template<class Traits>
|
||||
struct LinearInterpolation
|
||||
{
|
||||
MPT_FORCEINLINE void Start(const ModChannel &, const CResampler &) { }
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
MPT_FORCEINLINE LinearInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
|
||||
{
|
||||
|
@ -64,8 +62,7 @@ struct LinearInterpolation
|
|||
template<class Traits>
|
||||
struct FastSincInterpolation
|
||||
{
|
||||
MPT_FORCEINLINE void Start(const ModChannel &, const CResampler &) { }
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
MPT_FORCEINLINE FastSincInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
|
||||
{
|
||||
|
@ -89,14 +86,12 @@ struct PolyphaseInterpolation
|
|||
{
|
||||
const typename Traits::output_t *sinc;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn, const CResampler &resampler)
|
||||
MPT_FORCEINLINE PolyphaseInterpolation(const ModChannel &chn, const CResampler &resampler, unsigned int)
|
||||
{
|
||||
sinc = (((chn.increment > SamplePosition(0x130000000ll)) || (chn.increment < -SamplePosition(-0x130000000ll))) ?
|
||||
(((chn.increment > SamplePosition(0x180000000ll)) || (chn.increment < SamplePosition(-0x180000000ll))) ? resampler.gDownsample2x : resampler.gDownsample13x) : resampler.gKaiserSinc);
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
|
||||
{
|
||||
static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
|
||||
|
@ -123,13 +118,11 @@ struct FIRFilterInterpolation
|
|||
{
|
||||
const typename Traits::output_t *WFIRlut;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &, const CResampler &resampler)
|
||||
MPT_FORCEINLINE FIRFilterInterpolation(const ModChannel &, const CResampler &resampler, unsigned int)
|
||||
{
|
||||
WFIRlut = resampler.m_WindowedFIR.lut;
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const uint32 posLo)
|
||||
{
|
||||
static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
|
||||
|
@ -159,30 +152,30 @@ struct NoRamp
|
|||
{
|
||||
typename Traits::output_t lVol, rVol;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn)
|
||||
MPT_FORCEINLINE NoRamp(const ModChannel &chn)
|
||||
{
|
||||
lVol = static_cast<Traits::output_t>(chn.leftVol) * (1.0f / 4096.0f);
|
||||
rVol = static_cast<Traits::output_t>(chn.rightVol) * (1.0f / 4096.0f);
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
};
|
||||
|
||||
|
||||
struct Ramp
|
||||
{
|
||||
ModChannel &channel;
|
||||
int32 lRamp, rRamp;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn)
|
||||
MPT_FORCEINLINE Ramp(ModChannel &chn)
|
||||
: channel{chn}
|
||||
{
|
||||
lRamp = chn.rampLeftVol;
|
||||
rRamp = chn.rampRightVol;
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(ModChannel &chn)
|
||||
MPT_FORCEINLINE ~Ramp()
|
||||
{
|
||||
chn.rampLeftVol = lRamp; chn.leftVol = lRamp >> VOLUMERAMPPRECISION;
|
||||
chn.rampRightVol = rRamp; chn.rightVol = rRamp >> VOLUMERAMPPRECISION;
|
||||
channel.rampLeftVol = lRamp; channel.leftVol = lRamp >> VOLUMERAMPPRECISION;
|
||||
channel.rampRightVol = rRamp; channel.rightVol = rRamp >> VOLUMERAMPPRECISION;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -259,8 +252,7 @@ struct MixStereoRamp : public Ramp
|
|||
template<class Traits>
|
||||
struct NoFilter
|
||||
{
|
||||
MPT_FORCEINLINE void Start(const ModChannel &) { }
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
MPT_FORCEINLINE NoFilter(const ModChannel &) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &, const ModChannel &) { }
|
||||
};
|
||||
|
@ -270,10 +262,12 @@ struct NoFilter
|
|||
template<class Traits>
|
||||
struct ResonantFilter
|
||||
{
|
||||
ModChannel &channel;
|
||||
// Filter history
|
||||
typename Traits::output_t fy[Traits::numChannelsIn][2];
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn)
|
||||
MPT_FORCEINLINE ResonantFilter(ModChannel &chn)
|
||||
: channel{chn}
|
||||
{
|
||||
for(int i = 0; i < Traits::numChannelsIn; i++)
|
||||
{
|
||||
|
@ -282,12 +276,12 @@ struct ResonantFilter
|
|||
}
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(ModChannel &chn)
|
||||
MPT_FORCEINLINE ~ResonantFilter(ModChannel &chn)
|
||||
{
|
||||
for(int i = 0; i < Traits::numChannelsIn; i++)
|
||||
{
|
||||
chn.nFilter_Y[i][0] = fy[i][0];
|
||||
chn.nFilter_Y[i][1] = fy[i][1];
|
||||
channel.nFilter_Y[i][0] = fy[i][0];
|
||||
channel.nFilter_Y[i][1] = fy[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,23 +50,34 @@ template<class Traits>
|
|||
struct AmigaBlepInterpolation
|
||||
{
|
||||
SamplePosition subIncrement;
|
||||
Paula::State *paula;
|
||||
const Paula::BlepArray *WinSincIntegral;
|
||||
int numSteps;
|
||||
Paula::State &paula;
|
||||
const Paula::BlepArray &WinSincIntegral;
|
||||
const int numSteps;
|
||||
unsigned int remainingSamples = 0;
|
||||
|
||||
MPT_FORCEINLINE void Start(ModChannel &chn, const CResampler &resampler)
|
||||
MPT_FORCEINLINE AmigaBlepInterpolation(ModChannel &chn, const CResampler &resampler, unsigned int numSamples)
|
||||
: paula{chn.paulaState}
|
||||
, WinSincIntegral{resampler.blepTables.GetAmigaTable(resampler.m_Settings.emulateAmiga, chn.dwFlags[CHN_AMIGAFILTER])}
|
||||
, numSteps{chn.paulaState.numSteps}
|
||||
{
|
||||
paula = &chn.paulaState;
|
||||
numSteps = paula->numSteps;
|
||||
WinSincIntegral = &resampler.blepTables.GetAmigaTable(resampler.m_Settings.emulateAmiga, chn.dwFlags[CHN_AMIGAFILTER]);
|
||||
if(numSteps)
|
||||
{
|
||||
subIncrement = chn.increment / numSteps;
|
||||
// May we read past the start or end of sample if we do partial sample increments?
|
||||
// If that's the case, don't apply any sub increments on the source sample if we reached the last output sample
|
||||
// Note that this should only happen with notes well outside the Amiga note range, e.g. in software-mixed formats like MED
|
||||
const int32 targetPos = (chn.position + chn.increment * numSamples).GetInt();
|
||||
if(static_cast<SmpLength>(targetPos) > chn.nLength)
|
||||
remainingSamples = numSamples;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
|
||||
{
|
||||
if(--remainingSamples == 0)
|
||||
subIncrement = {};
|
||||
|
||||
SamplePosition pos(0, posLo);
|
||||
// First, process steps of full length (one Amiga clock interval)
|
||||
for(int step = numSteps; step > 0; step--)
|
||||
|
@ -75,26 +86,26 @@ struct AmigaBlepInterpolation
|
|||
int32 posInt = pos.GetInt() * Traits::numChannelsIn;
|
||||
for(int32 i = 0; i < Traits::numChannelsIn; i++)
|
||||
inSample += Traits::Convert(inBuffer[posInt + i]);
|
||||
paula->InputSample(static_cast<int16>(inSample / (4 * Traits::numChannelsIn)));
|
||||
paula->Clock(Paula::MINIMUM_INTERVAL);
|
||||
paula.InputSample(static_cast<int16>(inSample / (4 * Traits::numChannelsIn)));
|
||||
paula.Clock(Paula::MINIMUM_INTERVAL);
|
||||
pos += subIncrement;
|
||||
}
|
||||
paula->remainder += paula->stepRemainder;
|
||||
paula.remainder += paula.stepRemainder;
|
||||
|
||||
// Now, process any remaining integer clock amount < MINIMUM_INTERVAL
|
||||
uint32 remainClocks = paula->remainder.GetInt();
|
||||
uint32 remainClocks = paula.remainder.GetInt();
|
||||
if(remainClocks)
|
||||
{
|
||||
typename Traits::output_t inSample = 0;
|
||||
int32 posInt = pos.GetInt() * Traits::numChannelsIn;
|
||||
for(int32 i = 0; i < Traits::numChannelsIn; i++)
|
||||
inSample += Traits::Convert(inBuffer[posInt + i]);
|
||||
paula->InputSample(static_cast<int16>(inSample / (4 * Traits::numChannelsIn)));
|
||||
paula->Clock(remainClocks);
|
||||
paula->remainder.RemoveInt();
|
||||
paula.InputSample(static_cast<int16>(inSample / (4 * Traits::numChannelsIn)));
|
||||
paula.Clock(remainClocks);
|
||||
paula.remainder.RemoveInt();
|
||||
}
|
||||
|
||||
auto out = paula->OutputSample(*WinSincIntegral);
|
||||
auto out = paula.OutputSample(WinSincIntegral);
|
||||
for(int i = 0; i < Traits::numChannelsOut; i++)
|
||||
outSample[i] = out;
|
||||
}
|
||||
|
@ -104,9 +115,7 @@ struct AmigaBlepInterpolation
|
|||
template<class Traits>
|
||||
struct LinearInterpolation
|
||||
{
|
||||
MPT_FORCEINLINE void Start(const ModChannel &, const CResampler &) { }
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
MPT_FORCEINLINE LinearInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
|
||||
{
|
||||
|
@ -127,8 +136,7 @@ struct LinearInterpolation
|
|||
template<class Traits>
|
||||
struct FastSincInterpolation
|
||||
{
|
||||
MPT_FORCEINLINE void Start(const ModChannel &, const CResampler &) { }
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
MPT_FORCEINLINE FastSincInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
|
||||
{
|
||||
|
@ -152,7 +160,7 @@ struct PolyphaseInterpolation
|
|||
{
|
||||
const SINC_TYPE *sinc;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn, const CResampler &resampler)
|
||||
MPT_FORCEINLINE PolyphaseInterpolation(const ModChannel &chn, const CResampler &resampler, unsigned int)
|
||||
{
|
||||
#ifdef MODPLUG_TRACKER
|
||||
// Otherwise causes "warning C4100: 'resampler' : unreferenced formal parameter"
|
||||
|
@ -164,8 +172,6 @@ struct PolyphaseInterpolation
|
|||
(((chn.increment > SamplePosition(0x180000000ll)) || (chn.increment < SamplePosition(-0x180000000ll))) ? resampler.gDownsample2x : resampler.gDownsample13x) : resampler.gKaiserSinc);
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
|
||||
{
|
||||
static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
|
||||
|
@ -192,13 +198,11 @@ struct FIRFilterInterpolation
|
|||
{
|
||||
const int16 *WFIRlut;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &, const CResampler &resampler)
|
||||
MPT_FORCEINLINE FIRFilterInterpolation(const ModChannel &, const CResampler &resampler, unsigned int)
|
||||
{
|
||||
WFIRlut = resampler.m_WindowedFIR.lut;
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const MPT_RESTRICT inBuffer, const uint32 posLo)
|
||||
{
|
||||
static_assert(static_cast<int>(Traits::numChannelsIn) <= static_cast<int>(Traits::numChannelsOut), "Too many input channels");
|
||||
|
@ -230,30 +234,30 @@ struct NoRamp
|
|||
{
|
||||
typename Traits::output_t lVol, rVol;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn)
|
||||
MPT_FORCEINLINE NoRamp(const ModChannel &chn)
|
||||
{
|
||||
lVol = chn.leftVol;
|
||||
rVol = chn.rightVol;
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
};
|
||||
|
||||
|
||||
struct Ramp
|
||||
{
|
||||
ModChannel &channel;
|
||||
int32 lRamp, rRamp;
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn)
|
||||
MPT_FORCEINLINE Ramp(ModChannel &chn)
|
||||
: channel{chn}
|
||||
{
|
||||
lRamp = chn.rampLeftVol;
|
||||
rRamp = chn.rampRightVol;
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(ModChannel &chn)
|
||||
MPT_FORCEINLINE ~Ramp()
|
||||
{
|
||||
chn.rampLeftVol = lRamp; chn.leftVol = lRamp >> VOLUMERAMPPRECISION;
|
||||
chn.rampRightVol = rRamp; chn.rightVol = rRamp >> VOLUMERAMPPRECISION;
|
||||
channel.rampLeftVol = lRamp; channel.leftVol = lRamp >> VOLUMERAMPPRECISION;
|
||||
channel.rampRightVol = rRamp; channel.rightVol = rRamp >> VOLUMERAMPPRECISION;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -331,8 +335,7 @@ struct MixStereoRamp : public Ramp
|
|||
template<class Traits>
|
||||
struct NoFilter
|
||||
{
|
||||
MPT_FORCEINLINE void Start(const ModChannel &) { }
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
MPT_FORCEINLINE NoFilter(const ModChannel &) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (const typename Traits::outbuf_t &, const ModChannel &) { }
|
||||
};
|
||||
|
@ -342,10 +345,12 @@ struct NoFilter
|
|||
template<class Traits>
|
||||
struct ResonantFilter
|
||||
{
|
||||
ModChannel &channel;
|
||||
// Filter history
|
||||
typename Traits::output_t fy[Traits::numChannelsIn][2];
|
||||
|
||||
MPT_FORCEINLINE void Start(const ModChannel &chn)
|
||||
MPT_FORCEINLINE ResonantFilter(ModChannel &chn)
|
||||
: channel{chn}
|
||||
{
|
||||
for(int i = 0; i < Traits::numChannelsIn; i++)
|
||||
{
|
||||
|
@ -354,12 +359,12 @@ struct ResonantFilter
|
|||
}
|
||||
}
|
||||
|
||||
MPT_FORCEINLINE void End(ModChannel &chn)
|
||||
MPT_FORCEINLINE ~ResonantFilter()
|
||||
{
|
||||
for(int i = 0; i < Traits::numChannelsIn; i++)
|
||||
{
|
||||
chn.nFilter_Y[i][0] = fy[i][0];
|
||||
chn.nFilter_Y[i][1] = fy[i][1];
|
||||
channel.nFilter_Y[i][0] = fy[i][0];
|
||||
channel.nFilter_Y[i][1] = fy[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,7 @@ struct MixerTraits
|
|||
template<class Traits>
|
||||
struct NoInterpolation
|
||||
{
|
||||
MPT_FORCEINLINE void Start(const ModChannel &, const CResampler &) { }
|
||||
MPT_FORCEINLINE void End(const ModChannel &) { }
|
||||
MPT_FORCEINLINE NoInterpolation(const ModChannel &, const CResampler &, unsigned int) { }
|
||||
|
||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const typename Traits::input_t * const inBuffer, const int32)
|
||||
{
|
||||
|
@ -72,14 +71,9 @@ static void SampleLoop(ModChannel &chn, const CResampler &resampler, typename Tr
|
|||
ModChannel &c = chn;
|
||||
const typename Traits::input_t * MPT_RESTRICT inSample = static_cast<const typename Traits::input_t *>(c.pCurrentSample);
|
||||
|
||||
InterpolationFunc interpolate;
|
||||
FilterFunc filter;
|
||||
MixFunc mix;
|
||||
|
||||
// Do initialisation if necessary
|
||||
interpolate.Start(c, resampler);
|
||||
filter.Start(c);
|
||||
mix.Start(c);
|
||||
InterpolationFunc interpolate{c, resampler, numSamples};
|
||||
FilterFunc filter{c};
|
||||
MixFunc mix{c};
|
||||
|
||||
unsigned int samples = numSamples;
|
||||
SamplePosition smpPos = c.position; // Fixed-point sample position
|
||||
|
@ -96,10 +90,6 @@ static void SampleLoop(ModChannel &chn, const CResampler &resampler, typename Tr
|
|||
smpPos += increment;
|
||||
}
|
||||
|
||||
mix.End(c);
|
||||
filter.End(c);
|
||||
interpolate.End(c);
|
||||
|
||||
c.position = smpPos;
|
||||
}
|
||||
|
||||
|
|
|
@ -500,6 +500,10 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
|
|||
break;
|
||||
|
||||
case CMD_S3MCMDEX:
|
||||
if(!chn.rowCommand.param && (GetType() & (MOD_TYPE_S3M | MOD_TYPE_IT | MOD_TYPE_MPT)))
|
||||
chn.rowCommand.param = chn.nOldCmdEx;
|
||||
else
|
||||
chn.nOldCmdEx = static_cast<ModCommand::PARAM>(chn.rowCommand.param);
|
||||
if((p->param & 0xF0) == 0x60)
|
||||
{
|
||||
// Fine Pattern Delay
|
||||
|
@ -958,6 +962,11 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_playBehaviour[kST3EffectMemory] && param != 0)
|
||||
{
|
||||
UpdateS3MEffectMemory(chn, param);
|
||||
}
|
||||
}
|
||||
|
||||
// Interpret F00 effect in XM files as "stop song"
|
||||
|
@ -3439,10 +3448,6 @@ bool CSoundFile::ProcessEffects()
|
|||
|
||||
// S3M/IT Sxx Extended Commands
|
||||
case CMD_S3MCMDEX:
|
||||
if(m_playBehaviour[kST3EffectMemory] && param == 0)
|
||||
{
|
||||
param = chn.nArpeggio; // S00 uses the last non-zero effect parameter as memory, like other effects including Arpeggio, so we "borrow" our memory there.
|
||||
}
|
||||
ExtendedS3MCommands(nChn, static_cast<ModCommand::PARAM>(param));
|
||||
break;
|
||||
|
||||
|
@ -3702,9 +3707,9 @@ void CSoundFile::UpdateS3MEffectMemory(ModChannel &chn, ModCommand::PARAM param)
|
|||
chn.nTremorParam = param; // Ixy
|
||||
chn.nArpeggio = param; // Jxy
|
||||
chn.nRetrigParam = param; // Qxy
|
||||
chn.nTremoloDepth = (param & 0x0F) << 2; // Rxy
|
||||
chn.nTremoloSpeed = (param >> 4) & 0x0F; // Rxy
|
||||
// Sxy is not handled here.
|
||||
chn.nTremoloDepth = (param & 0x0F) << 2; // Rxy
|
||||
chn.nTremoloSpeed = (param >> 4) & 0x0F; // Rxy
|
||||
chn.nOldCmdEx = param; // Sxy
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ void LFOPlugin::Process(float *pOutL, float *pOutR, uint32 numFrames)
|
|||
if(m_outputToCC)
|
||||
{
|
||||
plugin->MidiSend(MIDIEvents::CC(static_cast<MIDIEvents::MidiCC>(m_outputParam & 0x7F), static_cast<uint8>((m_outputParam >> 8) & 0x0F), mpt::saturate_round<uint8>(value * 127.0f)));
|
||||
} else
|
||||
} else if(m_outputParam >= 0)
|
||||
{
|
||||
plugin->SetParameter(m_outputParam, static_cast<PlugParamValue>(value));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue