libOpenMPT: Updated to version 0.8.2

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-08-04 17:31:38 -07:00
parent b9ced57d5f
commit ecfbee6f53
35 changed files with 348 additions and 99 deletions

View file

@ -360,6 +360,9 @@ endif
ifeq ($(UNAME_S),OpenBSD)
HOST_FLAVOUR=OPENBSD
endif
ifeq ($(UNAME_S),DragonFly)
HOST_FLAVOUR=DRAGONFLY
endif
ifeq ($(UNAME_S),Haiku)
HOST_FLAVOUR=HAIKU
endif
@ -408,6 +411,8 @@ TAR_C=tar -c -N
else
TAR_C=tar -c -F pax -N
endif
else ifeq ($(findstring DragonFly,$(UNAME_S)),DragonFly)
TAR_C=tar -c --format pax --numeric-owner --uname "" --gname "" --uid 0 --gid 0
else ifeq ($(findstring BSD,$(UNAME_S)),BSD)
TAR_C=tar -c --format pax --numeric-owner --uname "" --gname "" --uid 0 --gid 0
else

View file

@ -1,4 +1,4 @@
MPT_SVNVERSION=23497
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.1
MPT_SVNDATE=2025-06-14T13:04:39.042416Z
MPT_SVNVERSION=23826
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.2
MPT_SVNDATE=2025-07-19T10:45:24.126020Z

View file

@ -53,6 +53,13 @@ LDLIBS_PLATFORM=-lc++ -lc
include build/make/config-clang.mk
MPT_COMPILER_NOALLOCAH=1
else ifeq ($(HOST_FLAVOUR),DRAGONFLY)
NO_PORTAUDIOCPP?=1
NO_PULSEAUDIO?=1
include build/make/config-gcc.mk
MPT_COMPILER_NOALLOCAH=1
else ifeq ($(HOST_FLAVOUR),HAIKU)
NO_PULSEAUDIO?=1

View file

@ -1,10 +1,10 @@
#pragma once
#define OPENMPT_VERSION_SVNVERSION "23497"
#define OPENMPT_VERSION_REVISION 23497
#define OPENMPT_VERSION_SVNVERSION "23826"
#define OPENMPT_VERSION_REVISION 23826
#define OPENMPT_VERSION_DIRTY 0
#define OPENMPT_VERSION_MIXEDREVISIONS 0
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.1"
#define OPENMPT_VERSION_DATE "2025-06-14T13:04:39.042416Z"
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.2"
#define OPENMPT_VERSION_DATE "2025-07-19T10:45:24.126020Z"
#define OPENMPT_VERSION_IS_PACKAGE 1

View file

@ -364,6 +364,7 @@
54F2D0191B80C78B8982EE59 /* algorithm.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = algorithm.hpp; path = ../../src/mpt/base/algorithm.hpp; sourceTree = "<group>"; };
55356226EAAC215859487866 /* span.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = span.hpp; path = ../../src/mpt/audio/span.hpp; sourceTree = "<group>"; };
55C6E46D9A1589DFDC3CC2AD /* Dlsbank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Dlsbank.cpp; path = ../../soundlib/Dlsbank.cpp; sourceTree = "<group>"; };
55E9D1C649E91B38CED43006 /* feature_fence.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = feature_fence.hpp; path = ../../src/mpt/arch/feature_fence.hpp; sourceTree = "<group>"; };
55EF6B83EC187D75AD7ED9C3 /* tests_endian_int24.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = tests_endian_int24.hpp; path = ../../src/mpt/endian/tests/tests_endian_int24.hpp; sourceTree = "<group>"; };
5609DBF3C331EA65C4C4DA33 /* utility.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = utility.hpp; path = ../../src/mpt/base/utility.hpp; sourceTree = "<group>"; };
567D9E616834DE53DDA2CCA1 /* InstrumentExtensions.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentExtensions.cpp; path = ../../soundlib/InstrumentExtensions.cpp; sourceTree = "<group>"; };
@ -1517,6 +1518,7 @@
isa = PBXGroup;
children = (
09573FAA7A79E09C30408DEA /* arch.hpp */,
55E9D1C649E91B38CED43006 /* feature_fence.hpp */,
1197459E05968F108A81A3DE /* feature_flags.hpp */,
473316F00DC10E627BC33530 /* x86_amd64.hpp */,
);

View file

@ -364,6 +364,7 @@
54F2D0191B80C78B8982EE59 /* algorithm.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = algorithm.hpp; path = ../../src/mpt/base/algorithm.hpp; sourceTree = "<group>"; };
55356226EAAC215859487866 /* span.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = span.hpp; path = ../../src/mpt/audio/span.hpp; sourceTree = "<group>"; };
55C6E46D9A1589DFDC3CC2AD /* Dlsbank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Dlsbank.cpp; path = ../../soundlib/Dlsbank.cpp; sourceTree = "<group>"; };
55E9D1C649E91B38CED43006 /* feature_fence.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = feature_fence.hpp; path = ../../src/mpt/arch/feature_fence.hpp; sourceTree = "<group>"; };
55EF6B83EC187D75AD7ED9C3 /* tests_endian_int24.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = tests_endian_int24.hpp; path = ../../src/mpt/endian/tests/tests_endian_int24.hpp; sourceTree = "<group>"; };
5609DBF3C331EA65C4C4DA33 /* utility.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = utility.hpp; path = ../../src/mpt/base/utility.hpp; sourceTree = "<group>"; };
567D9E616834DE53DDA2CCA1 /* InstrumentExtensions.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentExtensions.cpp; path = ../../soundlib/InstrumentExtensions.cpp; sourceTree = "<group>"; };
@ -1517,6 +1518,7 @@
isa = PBXGroup;
children = (
09573FAA7A79E09C30408DEA /* arch.hpp */,
55E9D1C649E91B38CED43006 /* feature_fence.hpp */,
1197459E05968F108A81A3DE /* feature_flags.hpp */,
473316F00DC10E627BC33530 /* x86_amd64.hpp */,
);

View file

@ -12,12 +12,15 @@
#include "openmpt/all/BuildSettings.hpp"
#include "mptString.h"
#include "mpt/io/io.hpp"
#include "mpt/io/io_stdstream.hpp"
#include "mptString.h"
#ifdef MPT_WITH_ZLIB
#include <ctime>
#include <zlib.h>
OPENMPT_NAMESPACE_BEGIN
@ -25,15 +28,31 @@ OPENMPT_NAMESPACE_BEGIN
inline void WriteGzip(std::ostream &output, std::string &outData, const mpt::ustring &fileName)
{
z_stream strm{};
int zlib_errc = Z_OK;
strm.avail_in = static_cast<uInt>(outData.size());
strm.next_in = reinterpret_cast<Bytef *>(outData.data());
if(deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 | 16, 9, Z_DEFAULT_STRATEGY) != Z_OK)
throw std::runtime_error{"zlib init failed"};
zlib_errc = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 | 16, 9, Z_DEFAULT_STRATEGY);
if(zlib_errc == Z_MEM_ERROR)
{
mpt::throw_out_of_memory();
} else if(zlib_errc < Z_OK)
{
throw std::runtime_error{"zlib: deflateInit2() failed"};
}
gz_header gzHeader{};
gzHeader.time = static_cast<uLong>(time(nullptr));
gzHeader.time = static_cast<uLong>(std::time(nullptr));
std::string filenameISO = mpt::ToCharset(mpt::Charset::ISO8859_1, fileName);
gzHeader.name = reinterpret_cast<Bytef *>(filenameISO.data());
deflateSetHeader(&strm, &gzHeader);
zlib_errc = deflateSetHeader(&strm, &gzHeader);
if(zlib_errc == Z_MEM_ERROR)
{
deflateEnd(&strm);
mpt::throw_out_of_memory();
} else if(zlib_errc < Z_OK)
{
deflateEnd(&strm);
throw std::runtime_error{"zlib: deflateSetHeader() failed"};
}
try
{
do
@ -41,15 +60,33 @@ inline void WriteGzip(std::ostream &output, std::string &outData, const mpt::ust
std::array<Bytef, mpt::IO::BUFFERSIZE_TINY> buffer;
strm.avail_out = static_cast<uInt>(buffer.size());
strm.next_out = buffer.data();
deflate(&strm, Z_FINISH);
zlib_errc = deflate(&strm, Z_FINISH);
if(zlib_errc == Z_BUF_ERROR)
{
// expected
} else if(zlib_errc == Z_MEM_ERROR)
{
mpt::throw_out_of_memory();
} else if(zlib_errc < Z_OK)
{
throw std::runtime_error{"zlib: deflate() failed"};
}
mpt::IO::WritePartial(output, buffer, buffer.size() - strm.avail_out);
} while(strm.avail_out == 0);
} catch(mpt::out_of_memory e)
{
deflateEnd(&strm);
mpt::rethrow_out_of_memory(e);
} catch(const std::exception &)
{
deflateEnd(&strm);
throw;
} catch(...)
{
deflateEnd(&strm);
throw;
}
deflateEnd(&strm);
}
OPENMPT_NAMESPACE_END

View file

@ -42,7 +42,7 @@ OPENMPT_NAMESPACE_BEGIN
#ifdef SSB_LOGGING
#define SSB_LOG(x) MPT_LOG_GLOBAL(LogDebug, "serialization", x)
#define SSB_LOG(x) MPT_LOG_GLOBAL(LogDebug, "serialization", (x))
#else
#define SSB_LOG(x) do { } while(0)
#endif

View file

@ -15,5 +15,5 @@
// Version definitions. The only thing that needs to be changed when changing version number.
#define VER_MAJORMAJOR 1
#define VER_MAJOR 32
#define VER_MINOR 01
#define VER_MINORMINOR 04
#define VER_MINOR 03
#define VER_MINORMINOR 00

View file

@ -21,7 +21,7 @@
/*! \brief libopenmpt minor version number */
#define OPENMPT_API_VERSION_MINOR 8
/*! \brief libopenmpt patch version number */
#define OPENMPT_API_VERSION_PATCH 1
#define OPENMPT_API_VERSION_PATCH 2
/*! \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=8
LIBOPENMPT_VERSION_PATCH=1
LIBOPENMPT_VERSION_PATCH=2
LIBOPENMPT_VERSION_PREREL=
LIBOPENMPT_LTVER_CURRENT=5
LIBOPENMPT_LTVER_REVISION=1
LIBOPENMPT_LTVER_REVISION=2
LIBOPENMPT_LTVER_AGE=5

View file

@ -38,6 +38,25 @@ static const char * const license =
#include "openmpt123_config.hpp"
#include "mpt/base/detect_compiler.hpp"
#if MPT_COMPILER_GCC
#ifdef MPT_COMPILER_SETTING_QUIRK_GCC_BROKEN_IPA
// See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115049>.
#if MPT_GCC_BEFORE(9, 0, 0)
// Earlier GCC get confused about setting a global function attribute.
// We need to check for 9.0 instead of 9.1 because of
// <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1028580>.
// It also gets confused when setting global optimization -O1,
// so we have no way of fixing GCC 8 or earlier.
//#pragma GCC optimize("O1")
#else
#pragma GCC optimize("no-ipa-ra")
#endif
#endif // MPT_COMPILER_SETTING_QUIRK_GCC_BROKEN_IPA
#endif // MPT_COMPILER_GCC
#include "mpt/base/detect_os.hpp"
#include "mpt/base/detect_quirks.hpp"

View file

@ -19,7 +19,7 @@
#include "mpt/base/saturate_round.hpp"
#include <algorithm>
#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS)
#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD)
#include <thread>
#endif
@ -71,7 +71,7 @@ public:
FLAC__stream_encoder_set_bits_per_sample( encoder, flags.use_float ? 24 : 16 );
FLAC__stream_encoder_set_sample_rate( encoder, flags.samplerate );
FLAC__stream_encoder_set_compression_level( encoder, 8 );
#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS)
#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD)
std::uint32_t threads = static_cast<std::uint32_t>(std::max(std::thread::hardware_concurrency(), static_cast<unsigned int>(1)));
// Work-around <https://github.com/xiph/flac/issues/823>.
//FLAC__stream_encoder_set_num_threads( encoder, threads );

View file

@ -90,7 +90,7 @@ public:
switch (new_mode) {
case FILE_mode::text:
fflush( file );
#if defined(UNICODE)
#if defined(UNICODE) && MPT_LIBC_MS_AT_LEAST(MPT_LIBC_MS_VER_UCRT)
old_mode = _setmode( _fileno( file ), _O_U8TEXT );
#else
old_mode = _setmode( _fileno( file ), _O_TEXT );

View file

@ -102,6 +102,7 @@ void CEQ::ProcessTemplate(TMixSample *frontBuffer, TMixSample *rearBuffer, std::
unsigned int old_csr = 0;
if(CPU::HasFeatureSet(CPU::feature::sse) && CPU::HasModesEnabled(CPU::mode::xmm128sse))
{
mpt::arch::feature_fence_aquire();
old_csr = _mm_getcsr();
_mm_setcsr((old_csr & ~(_MM_DENORMALS_ZERO_MASK | _MM_FLUSH_ZERO_MASK)) | _MM_DENORMALS_ZERO_ON | _MM_FLUSH_ZERO_ON);
}
@ -124,6 +125,7 @@ void CEQ::ProcessTemplate(TMixSample *frontBuffer, TMixSample *rearBuffer, std::
if(CPU::HasFeatureSet(CPU::feature::sse) && CPU::HasModesEnabled(CPU::mode::xmm128sse))
{
_mm_setcsr(old_csr);
mpt::arch::feature_fence_release();
}
#endif
}

View file

@ -159,7 +159,7 @@ const REFLECTIONPRESET gReflectionsPreset[ENVIRONMENT_NUMREFLECTIONS] =
// Implementation
//
MPT_FORCEINLINE int32 ftol(float f) { return static_cast<int32>(f); }
static MPT_FORCEINLINE int32 ftol(float f) { return static_cast<int32>(f); }
static void I3dl2_to_Generic(
const SNDMIX_REVERB_PROPERTIES *pReverb,
@ -597,6 +597,7 @@ void CReverb::ReverbProcessPostFiltering1x(const int32 * MPT_RESTRICT pRvb, int3
#if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2)
if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse))
{
mpt::arch::feature_fence_guard arch_feature_guard;
__m128i nDCRRvb_Y1 = Load64SSE(gnDCRRvb_Y1);
__m128i nDCRRvb_X1 = Load64SSE(gnDCRRvb_X1);
__m128i in = _mm_set1_epi32(0);
@ -659,6 +660,7 @@ void CReverb::ReverbDCRemoval(int32 * MPT_RESTRICT pBuffer, uint32 nSamples)
#if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2)
if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse))
{
mpt::arch::feature_fence_guard arch_feature_guard;
__m128i nDCRRvb_Y1 = Load64SSE(gnDCRRvb_Y1);
__m128i nDCRRvb_X1 = Load64SSE(gnDCRRvb_X1);
while(nSamples--)
@ -724,6 +726,7 @@ void CReverb::ProcessPreDelay(SWRvbRefDelay * MPT_RESTRICT pPreDelay, const int3
#if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2)
if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse))
{
mpt::arch::feature_fence_guard arch_feature_guard;
__m128i coeffs = _mm_cvtsi32_si128(pPreDelay->nCoeffs.lr);
__m128i history = _mm_cvtsi32_si128(pPreDelay->History.lr);
__m128i preDifCoeffs = _mm_cvtsi32_si128(pPreDelay->nPreDifCoeffs.lr);
@ -796,6 +799,7 @@ void CReverb::ProcessReflections(SWRvbRefDelay * MPT_RESTRICT pPreDelay, LR16 *
#if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2)
if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse))
{
mpt::arch::feature_fence_guard arch_feature_guard;
union
{
__m128i xmm;
@ -891,6 +895,7 @@ void CReverb::ProcessLateReverb(SWLateReverb * MPT_RESTRICT pReverb, LR16 * MPT_
#if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2)
if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse))
{
mpt::arch::feature_fence_guard arch_feature_guard;
int delayPos = pReverb->nDelayPos & RVBDLY_MASK;
__m128i rvbOutGains = Load64SSE(pReverb->RvbOutGains);
__m128i difCoeffs = Load64SSE(pReverb->nDifCoeffs);

View file

@ -97,7 +97,7 @@ struct MixLoopState
// Check how many samples can be rendered without encountering loop or sample end, and also update loop position / direction
MPT_FORCEINLINE uint32 GetSampleCount(ModChannel &chn, uint32 nSamples) const
{
int32 nLoopStart = chn.dwFlags[CHN_LOOP] ? chn.nLoopStart : 0;
const int32 nLoopStart = chn.dwFlags[CHN_LOOP] ? chn.nLoopStart : 0;
SamplePosition nInc = chn.increment;
if(nSamples <= 0 || nInc.IsZero() || !chn.nLength || !samplePointer)
@ -227,35 +227,24 @@ struct MixLoopState
{
if(nPosInt >= lookaheadStart)
{
#if 0
const uint32 oldCount = nSmpCount;
// When going backwards - we can only go back up to lookaheadStart.
// When going forwards - read through the whole pre-computed wrap-around buffer if possible.
// TODO: ProTracker sample swapping needs hard cut at sample end.
int32 samplesToRead = nInc.IsNegative()
? (nPosInt - lookaheadStart)
//: 2 * InterpolationMaxLookahead - (nPosInt - mixLoopState.lookaheadStart);
: (chn.nLoopEnd - nPosInt);
//LimitMax(samplesToRead, chn.nLoopEnd - chn.nLoopStart);
nSmpCount = SamplesToBufferLength(samplesToRead, chn);
Limit(nSmpCount, 1u, oldCount);
#else
if (nInc.IsNegative())
if(nInc.IsNegative())
{
nSmpCount = DistanceToBufferLength(SamplePosition(lookaheadStart, 0), nPos, nInv);
} else
chn.pCurrentSample = lookaheadPointer;
} else if(nPosInt <= chn.nLoopEnd)
{
nSmpCount = DistanceToBufferLength(nPos, SamplePosition(chn.nLoopEnd, 0), nInv);
chn.pCurrentSample = lookaheadPointer;
} else
{
nSmpCount = DistanceToBufferLength(nPos, SamplePosition(chn.nLength, 0), nInv);
}
#endif
chn.pCurrentSample = lookaheadPointer;
checkDest = false;
} else if(chn.dwFlags[CHN_WRAPPED_LOOP] && isAtLoopStart)
{
// We just restarted the loop, so interpolate correctly after wrapping around
nSmpCount = DistanceToBufferLength(nPos, SamplePosition(nLoopStart + InterpolationLookaheadBufferSize, 0), nInv);
chn.pCurrentSample = lookaheadPointer + (chn.nLoopEnd - nLoopStart) * chn.pModSample->GetBytesPerSample();
chn.pCurrentSample = lookaheadPointer + (chn.nLength - nLoopStart) * chn.pModSample->GetBytesPerSample();
checkDest = false;
} else if(nInc.IsPositive() && static_cast<SmpLength>(nPosDest) >= lookaheadStart && nSmpCount > 1)
{
@ -325,12 +314,45 @@ void CSoundFile::CreateStereoMix(int count)
}
std::pair<mixsample_t *, mixsample_t *> CSoundFile::GetChannelOffsets(const ModChannel &chn, CHANNELINDEX channel)
{
mixsample_t *pOfsR = &m_dryROfsVol;
mixsample_t *pOfsL = &m_dryLOfsVol;
#ifndef NO_REVERB
if(((m_MixerSettings.DSPMask & SNDDSP_REVERB) && !chn.dwFlags[CHN_NOREVERB]) || chn.dwFlags[CHN_REVERB])
{
pOfsR = &m_RvbROfsVol;
pOfsL = &m_RvbLOfsVol;
}
#endif
if(chn.dwFlags[CHN_SURROUND] && m_MixerSettings.gnChannels > 2)
{
pOfsR = &m_surroundROfsVol;
pOfsL = &m_surroundLOfsVol;
}
// Look for plugins associated with this implicit tracker channel.
#ifndef NO_PLUGINS
const PLUGINDEX mixPlugin = GetBestPlugin(chn, channel, PrioritiseInstrument, RespectMutes);
if((mixPlugin > 0) && (mixPlugin <= MAX_MIXPLUGINS) && m_MixPlugins[mixPlugin - 1].pMixPlugin != nullptr)
{
// Render into plugin buffer instead of global buffer
SNDMIXPLUGINSTATE &mixState = m_MixPlugins[mixPlugin - 1].pMixPlugin->m_MixState;
if(mixState.pMixBuffer)
{
pOfsR = &mixState.nVolDecayR;
pOfsL = &mixState.nVolDecayL;
}
}
#endif // NO_PLUGINS
return std::make_pair(pOfsL, pOfsR);
}
bool CSoundFile::MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bool doMix)
{
if(chn.pCurrentSample || chn.nLOfs || chn.nROfs)
{
mixsample_t *pOfsR = &m_dryROfsVol;
mixsample_t *pOfsL = &m_dryLOfsVol;
auto [pOfsL, pOfsR] = GetChannelOffsets(chn, channel);
uint32 functionNdx = MixFuncTable::ResamplingModeToMixFlags(static_cast<ResamplingMode>(chn.resamplingMode));
if(chn.dwFlags[CHN_16BIT]) functionNdx |= MixFuncTable::ndx16Bit;
@ -345,15 +367,11 @@ bool CSoundFile::MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bo
{
m_Reverb.TouchReverbSendBuffer(ReverbSendBuffer, m_RvbROfsVol, m_RvbLOfsVol, count);
pbuffer = ReverbSendBuffer;
pOfsR = &m_RvbROfsVol;
pOfsL = &m_RvbLOfsVol;
}
#endif
if(chn.dwFlags[CHN_SURROUND] && m_MixerSettings.gnChannels > 2)
{
pbuffer = MixRearBuffer;
pOfsR = &m_surroundROfsVol;
pOfsL = &m_surroundLOfsVol;
}
// Look for plugins associated with this implicit tracker channel.
@ -366,8 +384,6 @@ bool CSoundFile::MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bo
if (mixState.pMixBuffer)
{
pbuffer = mixState.pMixBuffer;
pOfsR = &mixState.nVolDecayR;
pOfsL = &mixState.nVolDecayL;
if (!(mixState.dwFlags & SNDMIXPLUGINSTATE::psfMixReady))
{
StereoFill(pbuffer, count, *pOfsR, *pOfsL);

View file

@ -83,8 +83,9 @@ struct FCFileHeader
return false;
static constexpr uint32 MAX_FC_SIZE = 0x8'0000; // According to manual: Sample memory allocated = 100,000 bytes
if(sequenceSize % sizeof(FCPlaylistEntry) > 1 // Some files have a mysterious extra byte
|| sequenceSize < sizeof(FCPlaylistEntry) || sequenceSize > 256 * 13
const uint32 seqSize = SequenceSize();
if(seqSize % sizeof(FCPlaylistEntry) > 1 // Some files have a mysterious extra byte
|| seqSize < sizeof(FCPlaylistEntry) || seqSize > 256 * 13
|| patternsSize % 64u || !patternsSize || patternsSize > 64 * 256 || patternsOffset > MAX_FC_SIZE
|| freqSequenceSize % 64u || !freqSequenceSize || freqSequenceSize > 64 * 256 || freqSequenceOffset > MAX_FC_SIZE
|| volSequenceSize % 64u || !volSequenceSize || volSequenceSize > 64 * 256 || volSequenceOffset > MAX_FC_SIZE
@ -102,12 +103,22 @@ struct FCFileHeader
ORDERINDEX NumOrders() const
{
return static_cast<ORDERINDEX>(sequenceSize / sizeof(FCPlaylistEntry));
return static_cast<ORDERINDEX>(SequenceSize() / sizeof(FCPlaylistEntry));
}
uint32 GetHeaderMinimumAdditionalSize() const
{
return sequenceSize + (IsFC14() ? 80 : 0);
return SequenceSize() + (IsFC14() ? 80 : 0);
}
uint32 SequenceSize() const
{
// A broken copy of cult.smod has a sequence size of 0 but the sequence data is actually in the place where it's supposed to be
if(sequenceSize > 0)
return sequenceSize;
if(const uint32 headerSize = IsFC14() ? 180 : 100; patternsOffset > headerSize)
return patternsOffset - headerSize;
return 0;
}
};

View file

@ -357,8 +357,8 @@ std::string MIDIMacroConfig::Macro::NormalizedString() const
{
std::string sanitizedMacro = *this;
std::string::size_type pos;
while((pos = sanitizedMacro.find_first_not_of("0123456789ABCDEFabchmnopsuvxyz")) != std::string::npos)
std::string::size_type pos = 0;
while((pos = sanitizedMacro.find_first_not_of("0123456789ABCDEFabchmnopsuvxyz", pos)) != std::string::npos)
{
sanitizedMacro.erase(pos, 1);
}

View file

@ -21,7 +21,7 @@ OPENMPT_NAMESPACE_BEGIN
ModSequence::ModSequence(CSoundFile &sndFile)
: m_sndFile(sndFile)
: m_sndFile{sndFile}
{
}
@ -33,6 +33,8 @@ ModSequence& ModSequence::operator=(const ModSequence &other)
std::vector<PATTERNINDEX>::assign(other.begin(), other.end());
m_name = other.m_name;
m_restartPos = other.m_restartPos;
m_defaultTempo = other.m_defaultTempo;
m_defaultSpeed = other.m_defaultSpeed;
return *this;
}
@ -41,7 +43,9 @@ bool ModSequence::operator== (const ModSequence &other) const noexcept
{
return static_cast<const std::vector<PATTERNINDEX> &>(*this) == other
&& m_name == other.m_name
&& m_restartPos == other.m_restartPos;
&& m_restartPos == other.m_restartPos
&& m_defaultTempo == other.m_defaultTempo
&& m_defaultSpeed == other.m_defaultSpeed;
}

View file

@ -35,9 +35,11 @@
//#include "mpt/crc/crc.hpp"
#include "OggStream.h"
#include <algorithm>
#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS)
#ifdef MPT_WITH_FLAC
#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD)
#include <thread>
#endif
#endif
#ifdef MPT_WITH_OGG
#if MPT_COMPILER_CLANG
#pragma clang diagnostic push
@ -698,7 +700,7 @@ bool CSoundFile::SaveFLACSample(SAMPLEINDEX nSample, std::ostream &f) const
FLAC__stream_encoder_set_metadata(encoder, metadata.data(), numBlocks);
#ifdef MODPLUG_TRACKER
FLAC__stream_encoder_set_compression_level(encoder, TrackerSettings::Instance().m_FLACCompressionLevel);
#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS)
#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD)
uint32 threads = TrackerSettings::Instance().m_FLACMultithreading ? static_cast<uint32>(std::max(std::thread::hardware_concurrency(), static_cast<unsigned int>(1))) : static_cast<uint32>(1);
// Work-around <https://github.com/xiph/flac/issues/823>.
//FLAC__stream_encoder_set_num_threads(encoder, threads);

View file

@ -618,6 +618,7 @@ enum PlayBehaviour
kITCarryAfterNoteOff, // Envelope Carry continues to function as normal even after note-off
kFT2OffsetMemoryRequiresNote, // Offset memory is only updated when offset command is next to a note
kITNoteCutWithPorta, // Note Cut (SCx) resets note frequency and interacts with tone portamento with row delay
kITVolColNoSlidePropagation, // Don't propagate volume command c/d parameter to regular command D memory
// Add new play behaviours here.

View file

@ -1312,7 +1312,9 @@ std::vector<GetLengthType> CSoundFile::GetLength(enmGetLengthResetMode adjustMod
for(uint32 i = 0; i < numTicks; i++)
{
chn.isFirstTick = (i == 0);
VolumeSlide(chn, vol);
// IT Compatibility: Volume column volume slides must not propagate their memory to the regular effect column
// Test case: VolColNoSlideMemoryPropagation.it
VolumeSlide(chn, vol, m_playBehaviour[kITVolColNoSlidePropagation]);
}
}
break;
@ -3077,6 +3079,8 @@ bool CSoundFile::ProcessEffects()
// Instrument Change ?
if(instr)
{
auto [oldChnOfsL, oldChnOfsR] = GetChannelOffsets(chn, nChn);
const ModSample *oldSample = chn.pModSample;
//const ModInstrument *oldInstrument = chn.pModInstrument;
@ -3101,8 +3105,8 @@ bool CSoundFile::ProcessEffects()
// When swapping samples without explicit note change (e.g. during portamento), avoid clicks at end of sample (as there won't be an NNA channel to fade the sample out)
if(oldSample != nullptr && oldSample != chn.pModSample)
{
m_dryLOfsVol += chn.nLOfs;
m_dryROfsVol += chn.nROfs;
*oldChnOfsL += chn.nLOfs;
*oldChnOfsR += chn.nROfs;
chn.nLOfs = 0;
chn.nROfs = 0;
}
@ -3296,7 +3300,9 @@ bool CSoundFile::ProcessEffects()
{
chn.nOldVolParam = vol;
}
VolumeSlide(chn, static_cast<ModCommand::PARAM>(volcmd == VOLCMD_VOLSLIDEUP ? (vol << 4) : vol));
// IT Compatibility: Volume column volume slides must not propagate their memory to the regular effect column
// Test case: VolColNoSlideMemoryPropagation.it
VolumeSlide(chn, static_cast<ModCommand::PARAM>(volcmd == VOLCMD_VOLSLIDEUP ? (vol << 4) : vol), m_playBehaviour[kITVolColNoSlidePropagation]);
break;
case VOLCMD_FINEVOLUP:
@ -4833,12 +4839,15 @@ void CSoundFile::VolumeDownETX(const PlayState &playState, ModChannel &chn, ModC
}
void CSoundFile::VolumeSlide(ModChannel &chn, ModCommand::PARAM param) const
void CSoundFile::VolumeSlide(ModChannel &chn, ModCommand::PARAM param, bool volCol) const
{
if (param)
chn.nOldVolumeSlide = param;
else
param = chn.nOldVolumeSlide;
if(!volCol)
{
if(param)
chn.nOldVolumeSlide = param;
else
param = chn.nOldVolumeSlide;
}
if((GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_DIGI | MOD_TYPE_STP | MOD_TYPE_DTM)))
{
@ -5689,6 +5698,8 @@ void CSoundFile::ProcessSampleOffset(ModChannel &chn, CHANNELINDEX nChn, const P
void CSoundFile::SampleOffset(ModChannel &chn, SmpLength param) const
{
LimitMax(param, MAX_SAMPLE_LENGTH);
// ST3 compatibility: Instrument-less note recalls previous note's offset
// Test case: OxxMemory.s3m
if(m_playBehaviour[kST3OffsetWithoutInstrument] || GetType() == MOD_TYPE_MED)
@ -6285,6 +6296,9 @@ void CSoundFile::SetTempo(PlayState &playState, TEMPO param, bool setFromUI) con
} else if(param < minTempo && !playState.m_flags[SONG_FIRSTTICK])
{
// Tempo Slide
// Very old MPT versions (last confirmed version: 1.09.066) add/subtract the param only on the first tick.
// Newer MPT versions (first confirmed version: 1.09.090), add/subtract the param multiplied by 2 only on the first tick.
// In SVN r26, the behaviour was adjusted to match Impulse Tracker. This change is part of OpenMPT 1.17 RC1 but not the MPT Wild pre-beta.
TEMPO tempDiff(param.GetInt() & 0x0F, 0);
if((param.GetInt() & 0xF0) == 0x10)
playState.m_nMusicTempo += tempDiff;

View file

@ -1228,6 +1228,7 @@ PlayBehaviourSet CSoundFile::GetSupportedPlaybackBehaviour(MODTYPE type)
playBehaviour.set(kITDoublePortamentoSlides);
playBehaviour.set(kITCarryAfterNoteOff);
playBehaviour.set(kITNoteCutWithPorta);
playBehaviour.set(kITVolColNoSlidePropagation);
break;
case MOD_TYPE_XM:

View file

@ -989,6 +989,7 @@ public:
private:
void CreateStereoMix(int count);
bool MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bool doMix);
std::pair<mixsample_t *, mixsample_t *> GetChannelOffsets(const ModChannel &chn, CHANNELINDEX channel);
public:
bool FadeSong(uint32 msec);
private:
@ -1109,7 +1110,7 @@ protected:
void FineVibrato(ModChannel &chn, uint32 param) const;
void AutoVolumeSlide(ModChannel &chn, ModCommand::PARAM param) const;
void VolumeDownETX(const PlayState &playState, ModChannel &chn, ModCommand::PARAM param) const;
void VolumeSlide(ModChannel &chn, ModCommand::PARAM param) const;
void VolumeSlide(ModChannel &chn, ModCommand::PARAM param, bool volCol = false) const;
void PanningSlide(ModChannel &chn, ModCommand::PARAM param, bool memory = true) const;
void ChannelVolSlide(ModChannel &chn, ModCommand::PARAM param) const;
void ChannelVolumeDownWithDuration(ModChannel &chn, uint16 param = uint16_max) const;

View file

@ -604,6 +604,7 @@ void CSoundFile::UpgradeModule()
{ kITDoublePortamentoSlides, MPT_V("1.32.00.27") },
{ kITCarryAfterNoteOff, MPT_V("1.32.00.40") },
{ kITNoteCutWithPorta, MPT_V("1.32.01.02") },
{ kITVolColNoSlidePropagation, MPT_V("1.32.02.03") },
};
for(const auto &b : behaviours)

View file

@ -1017,33 +1017,68 @@ bool CSoundFile::ReadJ2B(FileReader &file, ModLoadingFlags loadFlags)
// Header is valid, now unpack the RIFF AM file using inflate
z_stream strm{};
if(inflateInit(&strm) != Z_OK)
int zlib_errc = Z_OK;
zlib_errc = inflateInit(&strm);
if(zlib_errc == Z_MEM_ERROR)
{
mpt::throw_out_of_memory();
} else if(zlib_errc < Z_OK)
{
return false;
}
uint32 remainRead = fileHeader.packedLength, remainWrite = fileHeader.unpackedLength, totalWritten = 0;
uint32 crc = 0;
std::vector<Bytef> amFileData(remainWrite);
std::vector<Bytef> amFileData;
int retVal = Z_OK;
while(remainRead && remainWrite && retVal != Z_STREAM_END)
try
{
Bytef buffer[mpt::IO::BUFFERSIZE_TINY];
uint32 readSize = std::min(static_cast<uint32>(sizeof(buffer)), remainRead);
file.ReadRaw(mpt::span(buffer, readSize));
crc = static_cast<uint32>(crc32(crc, buffer, readSize));
strm.avail_in = readSize;
strm.next_in = buffer;
do
amFileData.resize(remainWrite);
while(remainRead && remainWrite && retVal != Z_STREAM_END)
{
strm.avail_out = remainWrite;
strm.next_out = amFileData.data() + totalWritten;
retVal = inflate(&strm, Z_NO_FLUSH);
uint32 written = remainWrite - strm.avail_out;
totalWritten += written;
remainWrite -= written;
} while(remainWrite && strm.avail_out == 0);
Bytef buffer[mpt::IO::BUFFERSIZE_TINY];
uint32 readSize = std::min(static_cast<uint32>(sizeof(buffer)), remainRead);
file.ReadRaw(mpt::span(buffer, readSize));
crc = static_cast<uint32>(crc32(crc, buffer, readSize));
remainRead -= readSize;
strm.avail_in = readSize;
strm.next_in = buffer;
do
{
strm.avail_out = remainWrite;
strm.next_out = amFileData.data() + totalWritten;
zlib_errc = inflate(&strm, Z_NO_FLUSH);
if(zlib_errc == Z_BUF_ERROR)
{
// expected
} else if(zlib_errc == Z_MEM_ERROR)
{
mpt::throw_out_of_memory();
} else if(zlib_errc < Z_OK)
{
inflateEnd(&strm);
return false;
}
retVal = zlib_errc;
uint32 written = remainWrite - strm.avail_out;
totalWritten += written;
remainWrite -= written;
} while(remainWrite && strm.avail_out == 0);
remainRead -= readSize;
}
} catch(mpt::out_of_memory e)
{
inflateEnd(&strm);
mpt::rethrow_out_of_memory(e);
} catch(const std::exception &)
{
inflateEnd(&strm);
return false;
} catch(...)
{
inflateEnd(&strm);
return false;
}
inflateEnd(&strm);

View file

@ -4,6 +4,7 @@
#define MPT_ARCH_ARCH_HPP
#include "mpt/arch/feature_fence.hpp"
#include "mpt/arch/feature_flags.hpp"
#include "mpt/arch/x86_amd64.hpp"
#include "mpt/base/detect.hpp"

View file

@ -0,0 +1,57 @@
/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */
#ifndef MPT_ARCH_FEATURE_FENCE_HPP
#define MPT_ARCH_FEATURE_FENCE_HPP
#include "mpt/base/detect.hpp"
#include "mpt/base/macros.hpp"
#include "mpt/base/namespace.hpp"
#include <atomic>
namespace mpt {
inline namespace MPT_INLINE_NS {
namespace arch {
MPT_FORCEINLINE void feature_fence_aquire() noexcept {
std::atomic_signal_fence(std::memory_order_acquire);
}
MPT_FORCEINLINE void feature_fence_release() noexcept {
std::atomic_signal_fence(std::memory_order_release);
}
class feature_fence_guard {
public:
MPT_FORCEINLINE feature_fence_guard() noexcept {
mpt::arch::feature_fence_aquire();
}
MPT_FORCEINLINE ~feature_fence_guard() noexcept {
mpt::arch::feature_fence_release();
}
feature_fence_guard(feature_fence_guard &&) = delete;
feature_fence_guard(const feature_fence_guard &) = delete;
feature_fence_guard & operator=(feature_fence_guard &&) = delete;
feature_fence_guard & operator=(const feature_fence_guard &) = delete;
};
} // namespace arch
} // namespace MPT_INLINE_NS
} // namespace mpt
#endif // MPT_ARCH_FEATURE_FENCE_HPP

View file

@ -103,9 +103,17 @@
#if !MPT_PLATFORM_MULTITHREADED
#define MPT_LIBCXX_QUIRK_NO_STD_THREAD
#elif !MPT_COMPILER_GENERIC && MPT_OS_WINDOWS && MPT_LIBCXX_GNU && !defined(_GLIBCXX_HAS_GTHREADS)
#define MPT_LIBCXX_QUIRK_NO_STD_THREAD
#endif
#if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
#if MPT_WINNT_AT_LEAST(MPT_WIN_VISTA)
#define MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX
#define MPT_LIBCXX_QUIRK_COMPLEX_STD_MUTEX
#endif
#endif
@ -348,6 +356,10 @@
#if MPT_LIBCXX_GNU_BEFORE(13)
#define MPT_LIBCXX_QUIRK_CHRONO_DATE_NO_ZONED_TIME
#endif
#if MPT_LIBCXX_LLVM
// See <https://github.com/llvm/llvm-project/issues/99982>
#define MPT_LIBCXX_QUIRK_CHRONO_DATE_NO_ZONED_TIME
#endif
#if MPT_MSVC_AT_LEAST(2022, 6) && MPT_MSVC_BEFORE(2022, 7)
// std::chrono triggers ICE in VS2022 17.6.0, see <https://developercommunity.visualstudio.com/t/INTERNAL-COMPILER-ERROR-when-compiling-s/10366948>.
#define MPT_LIBCXX_QUIRK_CHRONO_DATE_BROKEN_ZONED_TIME

View file

@ -7,10 +7,9 @@
#include "mpt/base/array.hpp"
#include "mpt/base/detect.hpp"
#include "mpt/base/namespace.hpp"
#include "mpt/base/integer.hpp"
#include "mpt/base/memory.hpp"
#include "mpt/base/namespace.hpp"
#include <array>

View file

@ -5,6 +5,7 @@
#include "mpt/base/detect.hpp"
#include "mpt/base/memory.hpp"
#include "mpt/base/namespace.hpp"
#include "mpt/io_read/filedata.hpp"
@ -12,6 +13,9 @@
#include <algorithm>
#include <cstddef>
#if MPT_GCC_AT_LEAST(12, 0, 0)
#include <cstring>
#endif
@ -65,7 +69,15 @@ public:
return dst.first(0);
}
pos_type avail = std::min(streamLength - pos, static_cast<pos_type>(dst.size()));
std::copy(streamData + pos, streamData + static_cast<std::size_t>(pos + avail), dst.data());
const std::byte * src = streamData + pos;
#if MPT_GCC_AT_LEAST(12, 0, 0)
// work-around bogus -Warray-bounds
// work-around bogus -Wstringop-overflow
// See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121165>.
std::memcpy(dst.data(), src, avail);
#else
std::copy(src, src + avail, dst.data());
#endif
return dst.first(static_cast<std::size_t>(avail));
}

View file

@ -11,9 +11,7 @@
#if !MPT_PLATFORM_MULTITHREADED
#define MPT_MUTEX_NONE 1
#elif MPT_COMPILER_GENERIC
#define MPT_MUTEX_STD 1
#elif MPT_OS_WINDOWS && MPT_LIBCXX_GNU && !defined(_GLIBCXX_HAS_GTHREADS)
#elif defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD)
#define MPT_MUTEX_WIN32 1
#else
#define MPT_MUTEX_STD 1
@ -31,7 +29,7 @@
#if MPT_MUTEX_STD
#include <mutex>
#ifdef MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX
#ifdef MPT_LIBCXX_QUIRK_COMPLEX_STD_MUTEX
#include <shared_mutex>
#include <type_traits>
#endif
@ -48,7 +46,7 @@ inline namespace MPT_INLINE_NS {
#if MPT_MUTEX_STD
#ifdef MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX
#ifdef MPT_LIBCXX_QUIRK_COMPLEX_STD_MUTEX
using mutex = std::conditional<sizeof(std::shared_mutex) < sizeof(std::mutex), std::shared_mutex, std::mutex>::type;
#else
using mutex = std::mutex;

View file

@ -27,6 +27,7 @@
#include <memory>
#include <random>
#include <string>
#include <vector>
#include <cmath>
#include <cstring>

View file

@ -256,6 +256,7 @@
83BB83FD2DF2BE22002077FC /* wav.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BB83F72DF2BE22002077FC /* wav.hpp */; };
83BB83FE2DF2BE22002077FC /* wav_write.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BB83F92DF2BE22002077FC /* wav_write.hpp */; };
83BB83FF2DF2BE22002077FC /* tags.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BB83F62DF2BE22002077FC /* tags.hpp */; };
83BDCD912E418723003FC007 /* feature_fence.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCD902E418723003FC007 /* feature_fence.hpp */; };
83E5EFD01FFEF9D200659F0F /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E5EFCE1FFEF9D200659F0F /* config.h */; };
83E5FC661FFEFA0D00659F0F /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E5FC2D1FFEFA0D00659F0F /* version.h */; };
83E5FC681FFEFA0D00659F0F /* stdafx.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E5FC2F1FFEFA0D00659F0F /* stdafx.h */; };
@ -734,6 +735,7 @@
83BB83F72DF2BE22002077FC /* wav.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wav.hpp; sourceTree = "<group>"; };
83BB83F92DF2BE22002077FC /* wav_write.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wav_write.hpp; sourceTree = "<group>"; };
83BB83FA2DF2BE22002077FC /* wav_write.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wav_write.cpp; sourceTree = "<group>"; };
83BDCD902E418723003FC007 /* feature_fence.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = feature_fence.hpp; sourceTree = "<group>"; };
83E5EFBD1FFEF7CC00659F0F /* libOpenMPT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libOpenMPT.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83E5EFCE1FFEF9D200659F0F /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = SOURCE_ROOT; };
83E5EFCF1FFEF9D200659F0F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; };
@ -1487,6 +1489,7 @@
isa = PBXGroup;
children = (
83649BA62A03418500CD0580 /* arch.hpp */,
83BDCD902E418723003FC007 /* feature_fence.hpp */,
83649BA52A03418500CD0580 /* feature_flags.hpp */,
83649BA72A03418500CD0580 /* x86_amd64.hpp */,
);
@ -2113,6 +2116,7 @@
83E5FCDB1FFEFA1A00659F0F /* libopenmpt_stream_callbacks_file.h in Headers */,
830996BA27787E9A00857684 /* base.hpp in Headers */,
83E5FDC31FFEFA8500659F0F /* MIDIEvents.h in Headers */,
83BDCD912E418723003FC007 /* feature_fence.hpp in Headers */,
83E5FDF81FFEFA8500659F0F /* Compressor.h in Headers */,
8309970C27787E9A00857684 /* detect_compiler.hpp in Headers */,
830996C227787E9A00857684 /* simple_integer.hpp in Headers */,