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_SVNVERSION=17954
|
||||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.5
|
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.6
|
||||||
MPT_SVNDATE=2022-08-21T11:52:57.985463Z
|
MPT_SVNDATE=2022-09-25T14:18:19.447172Z
|
||||||
|
|
|
@ -80,6 +80,11 @@ CXXFLAGS +=
|
||||||
CFLAGS +=
|
CFLAGS +=
|
||||||
LDFLAGS += -s WASM=2 -s LEGACY_VM_SUPPORT=1 -Wno-transpile
|
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
|
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||||
|
|
||||||
else ifeq ($(EMSCRIPTEN_TARGET),audioworkletprocessor)
|
else ifeq ($(EMSCRIPTEN_TARGET),audioworkletprocessor)
|
||||||
|
@ -107,6 +112,11 @@ CXXFLAGS +=
|
||||||
CFLAGS +=
|
CFLAGS +=
|
||||||
LDFLAGS += -s WASM=0 -s LEGACY_VM_SUPPORT=1 -Wno-transpile
|
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
|
LDFLAGS += -s ALLOW_MEMORY_GROWTH=1
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#define OPENMPT_VERSION_SVNVERSION "17761"
|
#define OPENMPT_VERSION_SVNVERSION "17954"
|
||||||
#define OPENMPT_VERSION_REVISION 17761
|
#define OPENMPT_VERSION_REVISION 17954
|
||||||
#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.6.5"
|
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.6.6"
|
||||||
#define OPENMPT_VERSION_DATE "2022-08-21T11:52:57.985463Z"
|
#define OPENMPT_VERSION_DATE "2022-09-25T14:18:19.447172Z"
|
||||||
#define OPENMPT_VERSION_IS_PACKAGE 1
|
#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.
|
// 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 30
|
#define VER_MAJOR 30
|
||||||
#define VER_MINOR 06
|
#define VER_MINOR 07
|
||||||
#define VER_MINORMINOR 00
|
#define VER_MINORMINOR 00
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_END
|
OPENMPT_NAMESPACE_END
|
||||||
|
|
|
@ -5,6 +5,22 @@ 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.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)
|
### libopenmpt 0.6.5 (2022-08-21)
|
||||||
|
|
||||||
* [**Bug**] `Makefile` now also uses `CC`, `CXX`, `LD`, and `AR` when set as
|
* [**Bug**] `Makefile` now also uses `CC`, `CXX`, `LD`, and `AR` when set as
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
/*! \brief libopenmpt minor version number */
|
/*! \brief libopenmpt minor version number */
|
||||||
#define OPENMPT_API_VERSION_MINOR 6
|
#define OPENMPT_API_VERSION_MINOR 6
|
||||||
/*! \brief libopenmpt patch version number */
|
/*! \brief libopenmpt patch version number */
|
||||||
#define OPENMPT_API_VERSION_PATCH 5
|
#define OPENMPT_API_VERSION_PATCH 6
|
||||||
/*! \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 */
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
LIBOPENMPT_VERSION_MAJOR=0
|
LIBOPENMPT_VERSION_MAJOR=0
|
||||||
LIBOPENMPT_VERSION_MINOR=6
|
LIBOPENMPT_VERSION_MINOR=6
|
||||||
LIBOPENMPT_VERSION_PATCH=5
|
LIBOPENMPT_VERSION_PATCH=6
|
||||||
LIBOPENMPT_VERSION_PREREL=
|
LIBOPENMPT_VERSION_PREREL=
|
||||||
|
|
||||||
LIBOPENMPT_LTVER_CURRENT=3
|
LIBOPENMPT_LTVER_CURRENT=3
|
||||||
LIBOPENMPT_LTVER_REVISION=5
|
LIBOPENMPT_LTVER_REVISION=6
|
||||||
LIBOPENMPT_LTVER_AGE=3
|
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 program = (pIns->nMidiProgram != 0) ? pIns->nMidiProgram - 1 : 0;
|
||||||
const uint32 key = isDrum ? (pIns->nMidiDrumKey & 0x7F) : 0xFF;
|
const uint32 key = isDrum ? (pIns->nMidiDrumKey & 0x7F) : 0xFF;
|
||||||
if(FindInstrument(isDrum, (pIns->wMidiBank - 1) & 0x3FFF, program, key, &dlsIns)
|
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))
|
|| FindInstrument(isDrum, 0xFFFF, isDrum ? 0xFF : program, key, &dlsIns))
|
||||||
{
|
{
|
||||||
if(key < 0x80) drumRgn = GetRegionFromKey(dlsIns, key);
|
if(key < 0x80) drumRgn = GetRegionFromKey(dlsIns, key);
|
||||||
|
|
|
@ -56,8 +56,10 @@ struct MTMSampleHeader
|
||||||
mptSmp.nLoopStart = loopStart;
|
mptSmp.nLoopStart = loopStart;
|
||||||
mptSmp.nLoopEnd = std::max(loopEnd.get(), uint32(1)) - 1;
|
mptSmp.nLoopEnd = std::max(loopEnd.get(), uint32(1)) - 1;
|
||||||
LimitMax(mptSmp.nLoopEnd, mptSmp.nLength);
|
LimitMax(mptSmp.nLoopEnd, mptSmp.nLength);
|
||||||
if(mptSmp.nLoopStart + 4 >= mptSmp.nLoopEnd) mptSmp.nLoopStart = mptSmp.nLoopEnd = 0;
|
if(mptSmp.nLoopStart + 4 >= mptSmp.nLoopEnd)
|
||||||
if(mptSmp.nLoopEnd) mptSmp.uFlags.set(CHN_LOOP);
|
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.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);
|
mptSmp.nC5Speed = ModSample::TransposeToFrequency(0, finetune * 16);
|
||||||
|
|
||||||
|
@ -170,6 +172,8 @@ bool CSoundFile::ReadMTM(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
|
|
||||||
if(loadFlags & loadPatternData)
|
if(loadFlags & loadPatternData)
|
||||||
Patterns.ResizeArray(fileHeader.lastPattern + 1);
|
Patterns.ResizeArray(fileHeader.lastPattern + 1);
|
||||||
|
|
||||||
|
bool hasSpeed = false, hasTempo = false;
|
||||||
for(PATTERNINDEX pat = 0; pat <= fileHeader.lastPattern; pat++)
|
for(PATTERNINDEX pat = 0; pat <= fileHeader.lastPattern; pat++)
|
||||||
{
|
{
|
||||||
if(!(loadFlags & loadPatternData) || !Patterns.Insert(pat, rowsPerPat))
|
if(!(loadFlags & loadPatternData) || !Patterns.Insert(pat, rowsPerPat))
|
||||||
|
@ -228,6 +232,63 @@ bool CSoundFile::ReadMTM(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
m->Convert(MOD_TYPE_MTM, MOD_TYPE_S3M, *this);
|
m->Convert(MOD_TYPE_MTM, MOD_TYPE_S3M, *this);
|
||||||
#endif
|
#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
|
#ifdef MPT_ENABLE_MP3_SAMPLES
|
||||||
#include "MPEGFrame.h"
|
#include "MPEGFrame.h"
|
||||||
#endif // MPT_ENABLE_MP3_SAMPLES
|
#endif // MPT_ENABLE_MP3_SAMPLES
|
||||||
|
#if defined(MPT_WITH_MINIMP3)
|
||||||
|
#include "mpt/base/alloc.hpp"
|
||||||
|
#endif // MPT_WITH_MINIMP3
|
||||||
|
|
||||||
#if defined(MPT_WITH_MINIMP3)
|
#if defined(MPT_WITH_MINIMP3)
|
||||||
#include <minimp3/minimp3.h>
|
#include <minimp3/minimp3.h>
|
||||||
#endif // MPT_WITH_MINIMP3
|
#endif // MPT_WITH_MINIMP3
|
||||||
|
@ -163,6 +167,28 @@ static mpt::ustring ReadMPG123String(const char (&str)[N])
|
||||||
#endif // MPT_WITH_MPG123
|
#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)
|
bool CSoundFile::ReadMP3Sample(SAMPLEINDEX sample, FileReader &file, bool raw, bool mo3Decode)
|
||||||
{
|
{
|
||||||
#if defined(MPT_WITH_MPG123) || defined(MPT_WITH_MINIMP3)
|
#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;
|
std::vector<int16> raw_sample_data;
|
||||||
|
|
||||||
mp3dec_t mp3;
|
mpt::heap_value<mp3dec_t> mp3;
|
||||||
std::memset(&mp3, 0, sizeof(mp3dec_t));
|
std::memset(&*mp3, 0, sizeof(mp3dec_t));
|
||||||
mp3dec_init(&mp3);
|
mp3dec_init(&*mp3);
|
||||||
|
|
||||||
int rate = 0;
|
int rate = 0;
|
||||||
int channels = 0;
|
int channels = 0;
|
||||||
|
|
||||||
mp3dec_frame_info_t info;
|
mp3dec_frame_info_t info;
|
||||||
std::memset(&info, 0, sizeof(mp3dec_frame_info_t));
|
std::memset(&info, 0, sizeof(mp3dec_frame_info_t));
|
||||||
|
std::vector<int16> sample_buf(MINIMP3_MAX_SAMPLES_PER_FRAME);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int16 sample_buf[MINIMP3_MAX_SAMPLES_PER_FRAME];
|
int frame_samples = mp3dec_decode_frame_no_inline(&*mp3, stream_pos, mpt::saturate_cast<int>(bytes_left), sample_buf.data(), &info);
|
||||||
int frame_samples = mp3dec_decode_frame(&mp3, stream_pos, mpt::saturate_cast<int>(bytes_left), sample_buf, &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; // 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
|
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
|
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)
|
} catch(mpt::out_of_memory e)
|
||||||
{
|
{
|
||||||
mpt::delete_out_of_memory(e);
|
mpt::delete_out_of_memory(e);
|
||||||
|
|
|
@ -913,13 +913,13 @@ bool CSoundFile::ReadSFZInstrument(INSTRUMENTINDEX nInstr, FileReader &file)
|
||||||
switch(region.loopMode)
|
switch(region.loopMode)
|
||||||
{
|
{
|
||||||
case SFZRegion::LoopMode::kContinuous:
|
case SFZRegion::LoopMode::kContinuous:
|
||||||
case SFZRegion::LoopMode::kOneShot:
|
|
||||||
sample.uFlags.set(CHN_LOOP);
|
sample.uFlags.set(CHN_LOOP);
|
||||||
break;
|
break;
|
||||||
case SFZRegion::LoopMode::kSustain:
|
case SFZRegion::LoopMode::kSustain:
|
||||||
sample.uFlags.set(CHN_SUSTAINLOOP);
|
sample.uFlags.set(CHN_SUSTAINLOOP);
|
||||||
break;
|
break;
|
||||||
case SFZRegion::LoopMode::kNoLoop:
|
case SFZRegion::LoopMode::kNoLoop:
|
||||||
|
case SFZRegion::LoopMode::kOneShot:
|
||||||
sample.uFlags.reset(CHN_LOOP | CHN_SUSTAINLOOP);
|
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::NoteOff:
|
||||||
case DuplicateNoteAction::NoteFade:
|
case DuplicateNoteAction::NoteFade:
|
||||||
// Switch off duplicated note played on this plugin
|
// Switch off duplicated note played on this plugin
|
||||||
SendMIDINote(i, chn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]) + NOTE_MAX_SPECIAL, 0);
|
if(const auto oldNote = chn.GetPluginNote(m_playBehaviour[kITRealNoteMapping]); oldNote != NOTE_NONE)
|
||||||
|
{
|
||||||
|
SendMIDINote(i, oldNote + NOTE_MAX_SPECIAL, 0);
|
||||||
chn.nArpeggioLastNote = NOTE_NONE;
|
chn.nArpeggioLastNote = NOTE_NONE;
|
||||||
|
chn.nNote = NOTE_NONE;
|
||||||
|
}
|
||||||
break;
|
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
|
// 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).
|
// (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,20 +2300,6 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo
|
||||||
if(!srcChn.IsSamplePlaying() && !applyNNAtoPlug)
|
if(!srcChn.IsSamplePlaying() && !applyNNAtoPlug)
|
||||||
return CHANNELINDEX_INVALID;
|
return CHANNELINDEX_INVALID;
|
||||||
|
|
||||||
CHANNELINDEX nnaChn = GetNNAChannel(nChn);
|
|
||||||
if(nnaChn == CHANNELINDEX_INVALID)
|
|
||||||
return CHANNELINDEX_INVALID;
|
|
||||||
|
|
||||||
ModChannel &chn = m_PlayState.Chn[nnaChn];
|
|
||||||
if(chn.dwFlags[CHN_ADLIB] && m_opl)
|
|
||||||
m_opl->NoteCut(nnaChn);
|
|
||||||
// Copy Channel
|
|
||||||
chn = srcChn;
|
|
||||||
chn.dwFlags.reset(CHN_VIBRATO | CHN_TREMOLO | CHN_PORTAMENTO);
|
|
||||||
chn.nPanbrelloOffset = 0;
|
|
||||||
|
|
||||||
chn.nMasterChn = nChn < GetNumChannels() ? nChn + 1 : 0;
|
|
||||||
chn.nCommand = CMD_NONE;
|
|
||||||
#ifndef NO_PLUGINS
|
#ifndef NO_PLUGINS
|
||||||
if(applyNNAtoPlug && pPlugin)
|
if(applyNNAtoPlug && pPlugin)
|
||||||
{
|
{
|
||||||
|
@ -2327,6 +2318,21 @@ CHANNELINDEX CSoundFile::CheckNNA(CHANNELINDEX nChn, uint32 instr, int note, boo
|
||||||
}
|
}
|
||||||
#endif // NO_PLUGINS
|
#endif // NO_PLUGINS
|
||||||
|
|
||||||
|
CHANNELINDEX nnaChn = GetNNAChannel(nChn);
|
||||||
|
if(nnaChn == CHANNELINDEX_INVALID)
|
||||||
|
return CHANNELINDEX_INVALID;
|
||||||
|
|
||||||
|
ModChannel &chn = m_PlayState.Chn[nnaChn];
|
||||||
|
if(chn.dwFlags[CHN_ADLIB] && m_opl)
|
||||||
|
m_opl->NoteCut(nnaChn);
|
||||||
|
// Copy Channel
|
||||||
|
chn = srcChn;
|
||||||
|
chn.dwFlags.reset(CHN_VIBRATO | CHN_TREMOLO | CHN_PORTAMENTO);
|
||||||
|
chn.nPanbrelloOffset = 0;
|
||||||
|
|
||||||
|
chn.nMasterChn = nChn < GetNumChannels() ? nChn + 1 : 0;
|
||||||
|
chn.nCommand = CMD_NONE;
|
||||||
|
|
||||||
// Key Off the note
|
// Key Off the note
|
||||||
switch(srcChn.nNNA)
|
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.
|
// ProTracker sets the tempo after the first tick. This block handles the case of one tick per row.
|
||||||
// Test case: TempoChange.mod
|
// 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;
|
pChn->rowCommand = *m;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* UpdateModule.cpp
|
* 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)
|
* Notes : (currently none)
|
||||||
* Authors: OpenMPT Devs
|
* Authors: OpenMPT Devs
|
||||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
* 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)";
|
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
|
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 bankChanged = (channel.currentBank != midiBank) && (midiBank < 0x4000);
|
||||||
bool progChanged = (channel.currentProgram != midiProg) && (midiProg < 0x80);
|
bool progChanged = (channel.currentProgram != midiProg) && (midiProg < 0x80);
|
||||||
//get vol in [0,128[
|
//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
|
// Bank change
|
||||||
if(bankChanged)
|
if(bankChanged)
|
||||||
|
|
|
@ -37,8 +37,8 @@ Echo::Echo(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
|
||||||
{
|
{
|
||||||
m_param[kEchoWetDry] = 0.5f;
|
m_param[kEchoWetDry] = 0.5f;
|
||||||
m_param[kEchoFeedback] = 0.5f;
|
m_param[kEchoFeedback] = 0.5f;
|
||||||
m_param[kEchoLeftDelay] = 0.25f;
|
m_param[kEchoLeftDelay] = (500.0f - 1.0f) / 1999.0f;
|
||||||
m_param[kEchoRightDelay] = 0.25f;
|
m_param[kEchoRightDelay] = (500.0f - 1.0f) / 1999.0f;
|
||||||
m_param[kEchoPanDelay] = 0.0f;
|
m_param[kEchoPanDelay] = 0.0f;
|
||||||
|
|
||||||
m_mixBuffer.Initialize(2, 2);
|
m_mixBuffer.Initialize(2, 2);
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#define MPT_OS_DJGPP 1
|
#define MPT_OS_DJGPP 1
|
||||||
#elif defined(__EMSCRIPTEN__)
|
#elif defined(__EMSCRIPTEN__)
|
||||||
#define MPT_OS_EMSCRIPTEN 1
|
#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 defined(__EMSCRIPTEN_major__) && defined(__EMSCRIPTEN_minor__)
|
||||||
#if (__EMSCRIPTEN_major__ > 1)
|
#if (__EMSCRIPTEN_major__ > 1)
|
||||||
// ok
|
// ok
|
||||||
|
|
Loading…
Reference in New Issue