Updated libOpenMPT to version 0.6.6
Signed-off-by: Christopher Snowhill <kode54@gmail.com>main
parent
929ab11738
commit
894aada3d2
|
@ -1,4 +1,4 @@
|
|||
|
||||
MPT_SVNVERSION=17761
|
||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.5
|
||||
MPT_SVNDATE=2022-08-21T11:52:57.985463Z
|
||||
MPT_SVNVERSION=17954
|
||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.6
|
||||
MPT_SVNDATE=2022-09-25T14:18:19.447172Z
|
||||
|
|
|
@ -80,6 +80,11 @@ CXXFLAGS +=
|
|||
CFLAGS +=
|
||||
LDFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1 -Wno-transpile
|
||||
|
||||
# work-around <https://github.com/emscripten-core/emscripten/issues/17897>.
|
||||
CXXFLAGS += -fno-inline-functions
|
||||
CFLAGS += -fno-inline-functions
|
||||
LDFLAGS += -fno-inline-functions
|
||||
|
||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||
|
||||
else ifeq ($(EMSCRIPTEN_TARGET),audioworkletprocessor)
|
||||
|
@ -107,6 +112,11 @@ CXXFLAGS +=
|
|||
CFLAGS +=
|
||||
LDFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1 -Wno-transpile
|
||||
|
||||
# work-around <https://github.com/emscripten-core/emscripten/issues/17897>.
|
||||
CXXFLAGS += -fno-inline-functions
|
||||
CFLAGS += -fno-inline-functions
|
||||
LDFLAGS += -fno-inline-functions
|
||||
|
||||
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||
|
||||
endif
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
#pragma once
|
||||
#define OPENMPT_VERSION_SVNVERSION "17761"
|
||||
#define OPENMPT_VERSION_REVISION 17761
|
||||
#define OPENMPT_VERSION_SVNVERSION "17954"
|
||||
#define OPENMPT_VERSION_REVISION 17954
|
||||
#define OPENMPT_VERSION_DIRTY 0
|
||||
#define OPENMPT_VERSION_MIXEDREVISIONS 0
|
||||
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.5"
|
||||
#define OPENMPT_VERSION_DATE "2022-08-21T11:52:57.985463Z"
|
||||
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.6"
|
||||
#define OPENMPT_VERSION_DATE "2022-09-25T14:18:19.447172Z"
|
||||
#define OPENMPT_VERSION_IS_PACKAGE 1
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ OPENMPT_NAMESPACE_BEGIN
|
|||
// Version definitions. The only thing that needs to be changed when changing version number.
|
||||
#define VER_MAJORMAJOR 1
|
||||
#define VER_MAJOR 30
|
||||
#define VER_MINOR 06
|
||||
#define VER_MINOR 07
|
||||
#define VER_MINORMINOR 00
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
||||
|
|
|
@ -5,6 +5,22 @@ Changelog {#changelog}
|
|||
For fully detailed change log, please see the source repository directly. This
|
||||
is just a high-level summary.
|
||||
|
||||
### libopenmpt 0.6.6 (2022-09-25)
|
||||
|
||||
* [**Sec**] Possible crash when playing manipulated IT / MPTM files with a T00
|
||||
command. (r17789)
|
||||
|
||||
* MTM: In MultiTracker, setting speed and tempo are mutually exclusive
|
||||
commands. Still, some MultiTracker modules were made to be played with
|
||||
external players such as DMP, so they actually rely on "standard" speed /
|
||||
tempo behaviour. Decide which behaviour to use by checking of speed and
|
||||
tempo commands are found on the same row.
|
||||
* MTM: Ignore sample loops if the loop end is <= 2.
|
||||
* Echo DMO: Migrate left and right delay values in modules made with OpenMPT
|
||||
versions between 1.27.01.00 and 1.30.05.00 to the correct interpretation.
|
||||
|
||||
* FLAC: Update to v1.4.1 (2022-09-22).
|
||||
|
||||
### libopenmpt 0.6.5 (2022-08-21)
|
||||
|
||||
* [**Bug**] `Makefile` now also uses `CC`, `CXX`, `LD`, and `AR` when set as
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
/*! \brief libopenmpt minor version number */
|
||||
#define OPENMPT_API_VERSION_MINOR 6
|
||||
/*! \brief libopenmpt patch version number */
|
||||
#define OPENMPT_API_VERSION_PATCH 5
|
||||
#define OPENMPT_API_VERSION_PATCH 6
|
||||
/*! \brief libopenmpt pre-release tag */
|
||||
#define OPENMPT_API_VERSION_PREREL ""
|
||||
/*! \brief libopenmpt pre-release flag */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
LIBOPENMPT_VERSION_MAJOR=0
|
||||
LIBOPENMPT_VERSION_MINOR=6
|
||||
LIBOPENMPT_VERSION_PATCH=5
|
||||
LIBOPENMPT_VERSION_PATCH=6
|
||||
LIBOPENMPT_VERSION_PREREL=
|
||||
|
||||
LIBOPENMPT_LTVER_CURRENT=3
|
||||
LIBOPENMPT_LTVER_REVISION=5
|
||||
LIBOPENMPT_LTVER_REVISION=6
|
||||
LIBOPENMPT_LTVER_AGE=3
|
||||
|
|
|
@ -646,6 +646,7 @@ bool CDLSBank::FindAndExtract(CSoundFile &sndFile, const INSTRUMENTINDEX ins, co
|
|||
const uint32 program = (pIns->nMidiProgram != 0) ? pIns->nMidiProgram - 1 : 0;
|
||||
const uint32 key = isDrum ? (pIns->nMidiDrumKey & 0x7F) : 0xFF;
|
||||
if(FindInstrument(isDrum, (pIns->wMidiBank - 1) & 0x3FFF, program, key, &dlsIns)
|
||||
|| FindInstrument(isDrum, (pIns->wMidiBank - 1) & 0x3F80, program, key, &dlsIns)
|
||||
|| FindInstrument(isDrum, 0xFFFF, isDrum ? 0xFF : program, key, &dlsIns))
|
||||
{
|
||||
if(key < 0x80) drumRgn = GetRegionFromKey(dlsIns, key);
|
||||
|
|
|
@ -17,18 +17,18 @@ OPENMPT_NAMESPACE_BEGIN
|
|||
// File Header
|
||||
struct MTMFileHeader
|
||||
{
|
||||
char id[3]; // MTM file marker
|
||||
uint8le version; // Tracker version
|
||||
char songName[20]; // ASCIIZ songname
|
||||
uint16le numTracks; // Number of tracks saved
|
||||
uint8le lastPattern; // Last pattern number saved
|
||||
uint8le lastOrder; // Last order number to play (songlength-1)
|
||||
uint16le commentSize; // Length of comment field
|
||||
uint8le numSamples; // Number of samples saved
|
||||
uint8le attribute; // Attribute byte (unused)
|
||||
uint8le beatsPerTrack; // Numbers of rows in every pattern (MultiTracker itself does not seem to support values != 64)
|
||||
uint8le numChannels; // Number of channels used
|
||||
uint8le panPos[32]; // Channel pan positions
|
||||
char id[3]; // MTM file marker
|
||||
uint8le version; // Tracker version
|
||||
char songName[20]; // ASCIIZ songname
|
||||
uint16le numTracks; // Number of tracks saved
|
||||
uint8le lastPattern; // Last pattern number saved
|
||||
uint8le lastOrder; // Last order number to play (songlength-1)
|
||||
uint16le commentSize; // Length of comment field
|
||||
uint8le numSamples; // Number of samples saved
|
||||
uint8le attribute; // Attribute byte (unused)
|
||||
uint8le beatsPerTrack; // Numbers of rows in every pattern (MultiTracker itself does not seem to support values != 64)
|
||||
uint8le numChannels; // Number of channels used
|
||||
uint8le panPos[32]; // Channel pan positions
|
||||
};
|
||||
|
||||
MPT_BINARY_STRUCT(MTMFileHeader, 66)
|
||||
|
@ -56,8 +56,10 @@ struct MTMSampleHeader
|
|||
mptSmp.nLoopStart = loopStart;
|
||||
mptSmp.nLoopEnd = std::max(loopEnd.get(), uint32(1)) - 1;
|
||||
LimitMax(mptSmp.nLoopEnd, mptSmp.nLength);
|
||||
if(mptSmp.nLoopStart + 4 >= mptSmp.nLoopEnd) mptSmp.nLoopStart = mptSmp.nLoopEnd = 0;
|
||||
if(mptSmp.nLoopEnd) mptSmp.uFlags.set(CHN_LOOP);
|
||||
if(mptSmp.nLoopStart + 4 >= mptSmp.nLoopEnd)
|
||||
mptSmp.nLoopStart = mptSmp.nLoopEnd = 0;
|
||||
if(mptSmp.nLoopEnd > 2)
|
||||
mptSmp.uFlags.set(CHN_LOOP);
|
||||
mptSmp.nFineTune = finetune; // Uses MOD units but allows the full int8 range rather than just -8...+7 so we keep the value as-is and convert it during playback
|
||||
mptSmp.nC5Speed = ModSample::TransposeToFrequency(0, finetune * 16);
|
||||
|
||||
|
@ -170,6 +172,8 @@ bool CSoundFile::ReadMTM(FileReader &file, ModLoadingFlags loadFlags)
|
|||
|
||||
if(loadFlags & loadPatternData)
|
||||
Patterns.ResizeArray(fileHeader.lastPattern + 1);
|
||||
|
||||
bool hasSpeed = false, hasTempo = false;
|
||||
for(PATTERNINDEX pat = 0; pat <= fileHeader.lastPattern; pat++)
|
||||
{
|
||||
if(!(loadFlags & loadPatternData) || !Patterns.Insert(pat, rowsPerPat))
|
||||
|
@ -228,6 +232,63 @@ bool CSoundFile::ReadMTM(FileReader &file, ModLoadingFlags loadFlags)
|
|||
#ifdef MODPLUG_TRACKER
|
||||
m->Convert(MOD_TYPE_MTM, MOD_TYPE_S3M, *this);
|
||||
#endif
|
||||
if(m->command == CMD_SPEED)
|
||||
hasSpeed = true;
|
||||
else if(m->command == CMD_TEMPO)
|
||||
hasTempo = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Curiously, speed commands reset the tempo to 125 in MultiTracker, and tempo commands reset the speed to 6.
|
||||
// External players of the time (e.g. DMP) did not implement this quirk and assumed a more ProTracker-like interpretation of speed and tempo.
|
||||
// Quite a few musicians created MTMs that make use DMP's speed and tempo interpretation, which in return means that they will play too
|
||||
// fast or too slow in MultiTracker. On the other hand there are also a few MTMs that break when using ProTracker-like speed and tempo.
|
||||
// As a way to support as many modules of both types as possible, we will assume a ProTracker-like interpretation if both speed and tempo
|
||||
// commands are found on the same line, and a MultiTracker-like interpretation when they are never found on the same line.
|
||||
if(hasSpeed && hasTempo)
|
||||
{
|
||||
bool hasSpeedAndTempoOnSameRow = false;
|
||||
for(const auto &pattern : Patterns)
|
||||
{
|
||||
for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++)
|
||||
{
|
||||
const auto rowBase = pattern.GetRow(row);
|
||||
bool hasSpeedOnRow = false, hasTempoOnRow = false;
|
||||
for(CHANNELINDEX chn = 0; chn < GetNumChannels(); chn++)
|
||||
{
|
||||
if(rowBase[chn].command == CMD_SPEED)
|
||||
hasSpeedOnRow = true;
|
||||
else if(rowBase[chn].command == CMD_TEMPO)
|
||||
hasTempoOnRow = true;
|
||||
}
|
||||
if(hasSpeedOnRow && hasTempoOnRow)
|
||||
{
|
||||
hasSpeedAndTempoOnSameRow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(hasSpeedAndTempoOnSameRow)
|
||||
break;
|
||||
}
|
||||
|
||||
if(!hasSpeedAndTempoOnSameRow)
|
||||
{
|
||||
for(auto &pattern : Patterns)
|
||||
{
|
||||
for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++)
|
||||
{
|
||||
const auto rowBase = pattern.GetRow(row);
|
||||
for(CHANNELINDEX chn = 0; chn < GetNumChannels(); chn++)
|
||||
{
|
||||
if(rowBase[chn].command == CMD_SPEED || rowBase[chn].command == CMD_TEMPO)
|
||||
{
|
||||
const bool writeTempo = rowBase[chn].command == CMD_SPEED;
|
||||
pattern.WriteEffect(EffectWriter(writeTempo ? CMD_TEMPO : CMD_SPEED, writeTempo ? 125 : 6).Row(row));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#ifdef MPT_ENABLE_MP3_SAMPLES
|
||||
#include "MPEGFrame.h"
|
||||
#endif // MPT_ENABLE_MP3_SAMPLES
|
||||
#if defined(MPT_WITH_MINIMP3)
|
||||
#include "mpt/base/alloc.hpp"
|
||||
#endif // MPT_WITH_MINIMP3
|
||||
|
||||
#if defined(MPT_WITH_MINIMP3)
|
||||
#include <minimp3/minimp3.h>
|
||||
#endif // MPT_WITH_MINIMP3
|
||||
|
@ -163,6 +167,28 @@ static mpt::ustring ReadMPG123String(const char (&str)[N])
|
|||
#endif // MPT_WITH_MPG123
|
||||
|
||||
|
||||
#if defined(MPT_WITH_MINIMP3)
|
||||
#if MPT_COMPILER_GCC
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wframe-larger-than=16000"
|
||||
#endif // MPT_COMPILER_GCC
|
||||
#if MPT_CLANG_AT_LEAST(13,0,0)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wframe-larger-than"
|
||||
#endif // MPT_COMPILER_CLANG
|
||||
static MPT_NOINLINE int mp3dec_decode_frame_no_inline(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info)
|
||||
{
|
||||
return mp3dec_decode_frame(dec, mp3, mp3_bytes, pcm, info);
|
||||
}
|
||||
#if MPT_CLANG_AT_LEAST(13,0,0)
|
||||
#pragma clang diagnostic pop
|
||||
#endif // MPT_COMPILER_CLANG
|
||||
#if MPT_COMPILER_GCC
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // MPT_COMPILER_GCC
|
||||
#endif // MPT_WITH_MINIMP3
|
||||
|
||||
|
||||
bool CSoundFile::ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw, bool mo3Decode)
|
||||
{
|
||||
#if defined(MPT_WITH_MPG123) || defined(MPT_WITH_MINIMP3)
|
||||
|
@ -603,19 +629,19 @@ bool CSoundFile::ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw, b
|
|||
|
||||
std::vector<int16> raw_sample_data;
|
||||
|
||||
mp3dec_t mp3;
|
||||
std::memset(&mp3, 0, sizeof(mp3dec_t));
|
||||
mp3dec_init(&mp3);
|
||||
mpt::heap_value<mp3dec_t> mp3;
|
||||
std::memset(&*mp3, 0, sizeof(mp3dec_t));
|
||||
mp3dec_init(&*mp3);
|
||||
|
||||
int rate = 0;
|
||||
int channels = 0;
|
||||
|
||||
mp3dec_frame_info_t info;
|
||||
std::memset(&info, 0, sizeof(mp3dec_frame_info_t));
|
||||
std::vector<int16> sample_buf(MINIMP3_MAX_SAMPLES_PER_FRAME);
|
||||
do
|
||||
{
|
||||
int16 sample_buf[MINIMP3_MAX_SAMPLES_PER_FRAME];
|
||||
int frame_samples = mp3dec_decode_frame(&mp3, stream_pos, mpt::saturate_cast<int>(bytes_left), sample_buf, &info);
|
||||
int frame_samples = mp3dec_decode_frame_no_inline(&*mp3, stream_pos, mpt::saturate_cast<int>(bytes_left), sample_buf.data(), &info);
|
||||
if(frame_samples < 0 || info.frame_bytes < 0) break; // internal error in minimp3
|
||||
if(frame_samples > 0 && info.frame_bytes == 0) break; // internal error in minimp3
|
||||
if(frame_samples == 0 && info.frame_bytes == 0) break; // end of stream, no progress
|
||||
|
@ -635,7 +661,7 @@ bool CSoundFile::ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw, b
|
|||
{
|
||||
try
|
||||
{
|
||||
mpt::append(raw_sample_data, sample_buf, sample_buf + frame_samples * channels);
|
||||
mpt::append(raw_sample_data, sample_buf.data(), sample_buf.data() + frame_samples * channels);
|
||||
} catch(mpt::out_of_memory e)
|
||||
{
|
||||
mpt::delete_out_of_memory(e);
|
||||
|
|
|
@ -913,13 +913,13 @@ bool CSoundFile::ReadSFZInstrument(INSTRUMENTINDEX nInstr, FileReader &file)
|
|||
switch(region.loopMode)
|
||||
{
|
||||
case SFZRegion::LoopMode::kContinuous:
|
||||
case SFZRegion::LoopMode::kOneShot:
|
||||
sample.uFlags.set(CHN_LOOP);
|
||||
break;
|
||||
case SFZRegion::LoopMode::kSustain:
|
||||
sample.uFlags.set(CHN_SUSTAINLOOP);
|
||||
break;
|
||||
case SFZRegion::LoopMode::kNoLoop:
|
||||
case SFZRegion::LoopMode::kOneShot:
|
||||
sample.uFlags.reset(CHN_LOOP | CHN_SUSTAINLOOP);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2232,8 +2232,12 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo
|
|||
case DuplicateNoteAction::NoteOff:
|
||||
case DuplicateNoteAction::NoteFade:
|
||||
// Switch off duplicated note played on this plugin
|
||||
SendMIDINote(i, chn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]) + NOTE_MAX_SPECIAL, 0);
|
||||
chn.nArpeggioLastNote = NOTE_NONE;
|
||||
if(const auto oldNote = chn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]); oldNote != NOTE_NONE)
|
||||
{
|
||||
SendMIDINote(i, oldNote + NOTE_MAX_SPECIAL, 0);
|
||||
chn.nArpeggioLastNote = NOTE_NONE;
|
||||
chn.nNote = NOTE_NONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2285,7 +2289,8 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo
|
|||
{
|
||||
// apply NNA to this plugin iff it is currently playing a note on this tracker channel
|
||||
// (and if it is playing a note, we know that would be the last note played on this chan).
|
||||
applyNNAtoPlug = pPlugin->IsNotePlaying(srcChn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]), nChn);
|
||||
const auto oldNote = srcChn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]);
|
||||
applyNNAtoPlug = (oldNote != NOTE_NONE) && pPlugin->IsNotePlaying(oldNote, nChn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2295,6 +2300,24 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo
|
|||
if(!srcChn.IsSamplePlaying() && !applyNNAtoPlug)
|
||||
return CHANNELINDEX_INVALID;
|
||||
|
||||
#ifndef NO_PLUGINS
|
||||
if(applyNNAtoPlug && pPlugin)
|
||||
{
|
||||
switch(srcChn.nNNA)
|
||||
{
|
||||
case NewNoteAction::NoteOff:
|
||||
case NewNoteAction::NoteCut:
|
||||
case NewNoteAction::NoteFade:
|
||||
// Switch off note played on this plugin, on this tracker channel and midi channel
|
||||
SendMIDINote(nChn, NOTE_KEYOFF, 0);
|
||||
srcChn.nArpeggioLastNote = NOTE_NONE;
|
||||
break;
|
||||
case NewNoteAction::Continue:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // NO_PLUGINS
|
||||
|
||||
CHANNELINDEX nnaChn = GetNNAChannel(nChn);
|
||||
if(nnaChn == CHANNELINDEX_INVALID)
|
||||
return CHANNELINDEX_INVALID;
|
||||
|
@ -2309,23 +2332,6 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo
|
|||
|
||||
chn.nMasterChn = nChn < GetNumChannels() ? nChn + 1 : 0;
|
||||
chn.nCommand = CMD_NONE;
|
||||
#ifndef NO_PLUGINS
|
||||
if(applyNNAtoPlug && pPlugin)
|
||||
{
|
||||
switch(srcChn.nNNA)
|
||||
{
|
||||
case NewNoteAction::NoteOff:
|
||||
case NewNoteAction::NoteCut:
|
||||
case NewNoteAction::NoteFade:
|
||||
// Switch off note played on this plugin, on this tracker channel and midi channel
|
||||
SendMIDINote(nChn, NOTE_KEYOFF, 0);
|
||||
srcChn.nArpeggioLastNote = NOTE_NONE;
|
||||
break;
|
||||
case NewNoteAction::Continue:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // NO_PLUGINS
|
||||
|
||||
// Key Off the note
|
||||
switch(srcChn.nNNA)
|
||||
|
|
|
@ -696,7 +696,7 @@ bool CSoundFile::ProcessRow()
|
|||
{
|
||||
// ProTracker sets the tempo after the first tick. This block handles the case of one tick per row.
|
||||
// Test case: TempoChange.mod
|
||||
m_PlayState.m_nMusicTempo = TEMPO(pChn->rowCommand.param, 0);
|
||||
m_PlayState.m_nMusicTempo = TEMPO(std::max(ModCommand::PARAM(1), pChn->rowCommand.param), 0);
|
||||
}
|
||||
|
||||
pChn->rowCommand = *m;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* UpdateModule.cpp
|
||||
* ----------------
|
||||
* Purpose: CSoundFile functions for correcting modules made with previous versions of OpenMPT.
|
||||
* Purpose: Compensate for playback bugs of previous OpenMPT versions during import
|
||||
* by rewriting patterns / samples / instruments or enabling / disabling specific compatibility flags
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
|
@ -726,6 +727,24 @@ void CSoundFile::UpgradeModule()
|
|||
plugin.Info.szLibraryName = "Flanger (Legacy)";
|
||||
}
|
||||
}
|
||||
|
||||
if(m_dwLastSavedWithVersion >= MPT_V("1.27") && m_dwLastSavedWithVersion < MPT_V("1.30.06.00") && (GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT | MOD_TYPE_XM)))
|
||||
{
|
||||
// Fix off-by-one delay length in older Echo DMO emulation
|
||||
for(auto &plugin : m_MixPlugins)
|
||||
{
|
||||
if(plugin.Info.dwPluginId1 == kDmoMagic && plugin.Info.dwPluginId2 == int32(0xEF3E932C) && plugin.pluginData.size() == 24)
|
||||
{
|
||||
float32le leftDelay, rightDelay;
|
||||
memcpy(&leftDelay, plugin.pluginData.data() + 12, 4);
|
||||
memcpy(&rightDelay, plugin.pluginData.data() + 16, 4);
|
||||
leftDelay = float32le{mpt::safe_clamp(((leftDelay * 2000.0f) - 1.0f) / 1999.0f, 0.0f, 1.0f)};
|
||||
rightDelay = float32le{mpt::safe_clamp(((rightDelay * 2000.0f) - 1.0f) / 1999.0f, 0.0f, 1.0f)};
|
||||
memcpy(plugin.pluginData.data() + 12, &leftDelay, 4);
|
||||
memcpy(plugin.pluginData.data() + 16, &rightDelay, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
||||
|
|
|
@ -884,7 +884,7 @@ void IMidiPlugin::MidiCommand(const ModInstrument &instr, uint16 note, uint16 vo
|
|||
bool bankChanged = (channel.currentBank != midiBank) && (midiBank < 0x4000);
|
||||
bool progChanged = (channel.currentProgram != midiProg) && (midiProg < 0x80);
|
||||
//get vol in [0,128[
|
||||
uint8 volume = static_cast<uint8>(std::min(vol / 2u, 127u));
|
||||
uint8 volume = static_cast<uint8>(std::min((vol + 1u) / 2u, 127u));
|
||||
|
||||
// Bank change
|
||||
if(bankChanged)
|
||||
|
|
|
@ -37,8 +37,8 @@ Echo::Echo(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
|
|||
{
|
||||
m_param[kEchoWetDry] = 0.5f;
|
||||
m_param[kEchoFeedback] = 0.5f;
|
||||
m_param[kEchoLeftDelay] = 0.25f;
|
||||
m_param[kEchoRightDelay] = 0.25f;
|
||||
m_param[kEchoLeftDelay] = (500.0f - 1.0f) / 1999.0f;
|
||||
m_param[kEchoRightDelay] = (500.0f - 1.0f) / 1999.0f;
|
||||
m_param[kEchoPanDelay] = 0.0f;
|
||||
|
||||
m_mixBuffer.Initialize(2, 2);
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#define MPT_OS_DJGPP 1
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define MPT_OS_EMSCRIPTEN 1
|
||||
#if !defined(__EMSCRIPTEN_major__) || !defined(__EMSCRIPTEN_minor__) || !defined(__EMSCRIPTEN_tiny__)
|
||||
#include <emscripten/version.h>
|
||||
#endif
|
||||
#if defined(__EMSCRIPTEN_major__) && defined(__EMSCRIPTEN_minor__)
|
||||
#if (__EMSCRIPTEN_major__ > 1)
|
||||
// ok
|
||||
|
|
Loading…
Reference in New Issue