Updated libopenmpt to version 0.3.9.
parent
186d432108
commit
ae22f79bad
|
@ -629,6 +629,13 @@ mpt::ustring GetFullCreditsString()
|
||||||
"http://www.hermannseib.com/english/vsthost.htm\n"
|
"http://www.hermannseib.com/english/vsthost.htm\n"
|
||||||
"\n"
|
"\n"
|
||||||
#endif
|
#endif
|
||||||
|
"Storlek for all the IT compatibility hints and testcases\n"
|
||||||
|
"as well as the IMF, MDL, OKT and ULT loaders\n"
|
||||||
|
"http://schismtracker.org/\n"
|
||||||
|
"\n"
|
||||||
|
"Sergei \"x0r\" Kolzun for various hints on Scream Tracker 2 compatibility\n"
|
||||||
|
"https://github.com/viiri/st2play\n"
|
||||||
|
"\n"
|
||||||
"Laurent Cl\xc3\xA9vy for unofficial MO3 documentation and decompression code\n"
|
"Laurent Cl\xc3\xA9vy for unofficial MO3 documentation and decompression code\n"
|
||||||
"https://github.com/lclevy/unmo3\n"
|
"https://github.com/lclevy/unmo3\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -716,10 +723,6 @@ mpt::ustring GetFullCreditsString()
|
||||||
"https://github.com/kazuho/picojson\n"
|
"https://github.com/kazuho/picojson\n"
|
||||||
"\n"
|
"\n"
|
||||||
#endif
|
#endif
|
||||||
"Storlek for all the IT compatibility hints and testcases\n"
|
|
||||||
"as well as the IMF, MDL, OKT and ULT loaders\n"
|
|
||||||
"http://schismtracker.org/\n"
|
|
||||||
"\n"
|
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
"Lennart Poettering and David Henningsson for RealtimeKit\n"
|
"Lennart Poettering and David Henningsson for RealtimeKit\n"
|
||||||
"http://git.0pointer.net/rtkit.git/\n"
|
"http://git.0pointer.net/rtkit.git/\n"
|
||||||
|
|
|
@ -19,7 +19,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
#define VER_MAJORMAJOR 1
|
#define VER_MAJORMAJOR 1
|
||||||
#define VER_MAJOR 27
|
#define VER_MAJOR 27
|
||||||
#define VER_MINOR 07
|
#define VER_MINOR 07
|
||||||
#define VER_MINORMINOR 00
|
#define VER_MINORMINOR 02
|
||||||
|
|
||||||
//Version string. For example "1.17.02.28"
|
//Version string. For example "1.17.02.28"
|
||||||
#define MPT_VERSION_STR VER_STRINGIZE(VER_MAJORMAJOR) "." VER_STRINGIZE(VER_MAJOR) "." VER_STRINGIZE(VER_MINOR) "." VER_STRINGIZE(VER_MINORMINOR)
|
#define MPT_VERSION_STR VER_STRINGIZE(VER_MAJORMAJOR) "." VER_STRINGIZE(VER_MAJOR) "." VER_STRINGIZE(VER_MINOR) "." VER_STRINGIZE(VER_MINORMINOR)
|
||||||
|
|
|
@ -5,10 +5,26 @@ 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.3.9 (2018-04-29)
|
||||||
|
|
||||||
|
* [**Sec**] Possible write near address 0 in out-of-memory situations when
|
||||||
|
reading AMS files (r10149).
|
||||||
|
|
||||||
|
* [**Bug**] openmpt123: Fixed build failure in C++17 due to use of removed
|
||||||
|
feature `std::random_shuffle`.
|
||||||
|
|
||||||
|
* STM: Having both Bxx and Cxx commands in a pattern imported the Bxx command
|
||||||
|
incorrectly.
|
||||||
|
* STM: Last character of sample name was missing.
|
||||||
|
* Speed up reading of truncated ULT files.
|
||||||
|
* ULT: Portamento import was sometimes broken.
|
||||||
|
* The resonant filter was sometimes unstable when combining low-volume
|
||||||
|
samples, low cutoff and high mixing rates.
|
||||||
|
|
||||||
### libopenmpt 0.3.8 (2018-04-08)
|
### libopenmpt 0.3.8 (2018-04-08)
|
||||||
|
|
||||||
* [**Sec**] Possible out-of-bounds memory read with IT / ITP / MO3 files
|
* [**Sec**] Possible out-of-bounds memory read with IT and MO3 files
|
||||||
containing pattern loops (r10028).
|
containing many nested pattern loops (r10028).
|
||||||
|
|
||||||
* Keep track of active SFx macro during seeking.
|
* Keep track of active SFx macro during seeking.
|
||||||
* The "note cut" duplicate note action did not volume-ramp the previously
|
* The "note cut" duplicate note action did not volume-ramp the previously
|
||||||
|
@ -60,7 +76,6 @@ is just a high-level summary.
|
||||||
* Tighten M15 and MOD file rejection heuristics.
|
* Tighten M15 and MOD file rejection heuristics.
|
||||||
* J2B: Ignore frequency limits from file header. Fixes Medivo.j2b, broken
|
* J2B: Ignore frequency limits from file header. Fixes Medivo.j2b, broken
|
||||||
since libopenmpt-0.2.6401-beta17.
|
since libopenmpt-0.2.6401-beta17.
|
||||||
* STM: Last character of sample name was missing.
|
|
||||||
* ParamEq plugin center frequency was not limited correctly.
|
* ParamEq plugin center frequency was not limited correctly.
|
||||||
* libopenmpt_ext C API was not included in the documentation.
|
* libopenmpt_ext C API was not included in the documentation.
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
/*! \brief libopenmpt minor version number */
|
/*! \brief libopenmpt minor version number */
|
||||||
#define OPENMPT_API_VERSION_MINOR 3
|
#define OPENMPT_API_VERSION_MINOR 3
|
||||||
/*! \brief libopenmpt patch version number */
|
/*! \brief libopenmpt patch version number */
|
||||||
#define OPENMPT_API_VERSION_PATCH 8
|
#define OPENMPT_API_VERSION_PATCH 9
|
||||||
/*! \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=3
|
LIBOPENMPT_VERSION_MINOR=3
|
||||||
LIBOPENMPT_VERSION_PATCH=8
|
LIBOPENMPT_VERSION_PATCH=9
|
||||||
LIBOPENMPT_VERSION_PREREL=
|
LIBOPENMPT_VERSION_PREREL=
|
||||||
|
|
||||||
LIBOPENMPT_LTVER_CURRENT=1
|
LIBOPENMPT_LTVER_CURRENT=1
|
||||||
LIBOPENMPT_LTVER_REVISION=8
|
LIBOPENMPT_LTVER_REVISION=9
|
||||||
LIBOPENMPT_LTVER_AGE=1
|
LIBOPENMPT_LTVER_AGE=1
|
||||||
|
|
|
@ -290,7 +290,7 @@ static void load_settings_from_map( libopenmpt::plugin::settings & s, const std:
|
||||||
|
|
||||||
static void load_settings_from_xml( libopenmpt::plugin::settings & s, const std::string & xml ) {
|
static void load_settings_from_xml( libopenmpt::plugin::settings & s, const std::string & xml ) {
|
||||||
pugi::xml_document doc;
|
pugi::xml_document doc;
|
||||||
doc.load( xml.c_str() );
|
doc.load_string( xml.c_str() );
|
||||||
pugi::xml_node settings_node = doc.child( "settings" );
|
pugi::xml_node settings_node = doc.child( "settings" );
|
||||||
std::map<std::string,int> map;
|
std::map<std::string,int> map;
|
||||||
for ( pugi::xml_attribute_iterator it = settings_node.attributes_begin(); it != settings_node.attributes_end(); ++it ) {
|
for ( pugi::xml_attribute_iterator it = settings_node.attributes_begin(); it != settings_node.attributes_end(); ++it ) {
|
||||||
|
|
|
@ -47,6 +47,7 @@ static const char * const license =
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <random>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -1754,18 +1755,17 @@ static void render_file( commandlineflags & flags, const std::string & filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static std::string get_random_filename(std::set<std::string> & filenames) {
|
static std::string get_random_filename( std::set<std::string> & filenames, std::default_random_engine & prng ) {
|
||||||
// TODO: actually use a useful random distribution
|
std::size_t index = std::uniform_int_distribution<std::size_t>( 0, filenames.size() - 1 )( prng );
|
||||||
std::size_t index = std::rand() % filenames.size();
|
|
||||||
std::set<std::string>::iterator it = filenames.begin();
|
std::set<std::string>::iterator it = filenames.begin();
|
||||||
std::advance( it, index );
|
std::advance( it, index );
|
||||||
return *it;
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void render_files( commandlineflags & flags, textout & log, write_buffers_interface & audio_stream ) {
|
static void render_files( commandlineflags & flags, textout & log, write_buffers_interface & audio_stream, std::default_random_engine & prng ) {
|
||||||
if ( flags.randomize ) {
|
if ( flags.randomize ) {
|
||||||
std::random_shuffle( flags.filenames.begin(), flags.filenames.end() );
|
std::shuffle( flags.filenames.begin(), flags.filenames.end(), prng );
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
|
@ -1777,7 +1777,7 @@ static void render_files( commandlineflags & flags, textout & log, write_buffers
|
||||||
if ( shuffle_set.empty() ) {
|
if ( shuffle_set.empty() ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::string filename = get_random_filename( shuffle_set );
|
std::string filename = get_random_filename( shuffle_set, prng );
|
||||||
try {
|
try {
|
||||||
flags.playlist_index = std::find( flags.filenames.begin(), flags.filenames.end(), filename ) - flags.filenames.begin();
|
flags.playlist_index = std::find( flags.filenames.begin(), flags.filenames.end(), filename ) - flags.filenames.begin();
|
||||||
render_file( flags, filename, log, audio_stream );
|
render_file( flags, filename, log, audio_stream );
|
||||||
|
@ -2393,7 +2393,10 @@ static int main( int argc, char * argv [] ) {
|
||||||
|
|
||||||
log.writeout();
|
log.writeout();
|
||||||
|
|
||||||
std::srand( static_cast<unsigned int>( std::time( NULL ) ) );
|
std::random_device rd;
|
||||||
|
std::seed_seq seq{ rd(), static_cast<unsigned int>( std::time( NULL ) ) };
|
||||||
|
std::default_random_engine prng( seq );
|
||||||
|
std::srand( std::uniform_int_distribution<unsigned int>()( prng ) );
|
||||||
|
|
||||||
switch ( flags.mode ) {
|
switch ( flags.mode ) {
|
||||||
case ModeProbe: {
|
case ModeProbe: {
|
||||||
|
@ -2404,42 +2407,42 @@ static int main( int argc, char * argv [] ) {
|
||||||
} break;
|
} break;
|
||||||
case ModeInfo: {
|
case ModeInfo: {
|
||||||
void_audio_stream dummy;
|
void_audio_stream dummy;
|
||||||
render_files( flags, log, dummy );
|
render_files( flags, log, dummy, prng );
|
||||||
} break;
|
} break;
|
||||||
case ModeUI:
|
case ModeUI:
|
||||||
case ModeBatch: {
|
case ModeBatch: {
|
||||||
if ( flags.use_stdout ) {
|
if ( flags.use_stdout ) {
|
||||||
flags.apply_default_buffer_sizes();
|
flags.apply_default_buffer_sizes();
|
||||||
stdout_stream_raii stdout_audio_stream;
|
stdout_stream_raii stdout_audio_stream;
|
||||||
render_files( flags, log, stdout_audio_stream );
|
render_files( flags, log, stdout_audio_stream, prng );
|
||||||
} else if ( !flags.output_filename.empty() ) {
|
} else if ( !flags.output_filename.empty() ) {
|
||||||
flags.apply_default_buffer_sizes();
|
flags.apply_default_buffer_sizes();
|
||||||
file_audio_stream_raii file_audio_stream( flags, flags.output_filename, log );
|
file_audio_stream_raii file_audio_stream( flags, flags.output_filename, log );
|
||||||
render_files( flags, log, file_audio_stream );
|
render_files( flags, log, file_audio_stream, prng );
|
||||||
#if defined( MPT_WITH_PULSEAUDIO )
|
#if defined( MPT_WITH_PULSEAUDIO )
|
||||||
} else if ( flags.driver == "pulseaudio" || flags.driver.empty() ) {
|
} else if ( flags.driver == "pulseaudio" || flags.driver.empty() ) {
|
||||||
pulseaudio_stream_raii pulseaudio_stream( flags, log );
|
pulseaudio_stream_raii pulseaudio_stream( flags, log );
|
||||||
render_files( flags, log, pulseaudio_stream );
|
render_files( flags, log, pulseaudio_stream, prng );
|
||||||
#endif
|
#endif
|
||||||
#if defined( MPT_WITH_SDL2 )
|
#if defined( MPT_WITH_SDL2 )
|
||||||
} else if ( flags.driver == "sdl2" || flags.driver.empty() ) {
|
} else if ( flags.driver == "sdl2" || flags.driver.empty() ) {
|
||||||
sdl2_stream_raii sdl2_stream( flags, log );
|
sdl2_stream_raii sdl2_stream( flags, log );
|
||||||
render_files( flags, log, sdl2_stream );
|
render_files( flags, log, sdl2_stream, prng );
|
||||||
#endif
|
#endif
|
||||||
#if defined( MPT_WITH_SDL )
|
#if defined( MPT_WITH_SDL )
|
||||||
} else if ( flags.driver == "sdl" || flags.driver.empty() ) {
|
} else if ( flags.driver == "sdl" || flags.driver.empty() ) {
|
||||||
sdl_stream_raii sdl_stream( flags, log );
|
sdl_stream_raii sdl_stream( flags, log );
|
||||||
render_files( flags, log, sdl_stream );
|
render_files( flags, log, sdl_stream, prng );
|
||||||
#endif
|
#endif
|
||||||
#if defined( MPT_WITH_PORTAUDIO )
|
#if defined( MPT_WITH_PORTAUDIO )
|
||||||
} else if ( flags.driver == "portaudio" || flags.driver.empty() ) {
|
} else if ( flags.driver == "portaudio" || flags.driver.empty() ) {
|
||||||
portaudio_stream_raii portaudio_stream( flags, log );
|
portaudio_stream_raii portaudio_stream( flags, log );
|
||||||
render_files( flags, log, portaudio_stream );
|
render_files( flags, log, portaudio_stream, prng );
|
||||||
#endif
|
#endif
|
||||||
#if defined( WIN32 )
|
#if defined( WIN32 )
|
||||||
} else if ( flags.driver == "waveout" || flags.driver.empty() ) {
|
} else if ( flags.driver == "waveout" || flags.driver.empty() ) {
|
||||||
waveout_stream_raii waveout_stream( flags );
|
waveout_stream_raii waveout_stream( flags );
|
||||||
render_files( flags, log, waveout_stream );
|
render_files( flags, log, waveout_stream, prng );
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if ( flags.driver.empty() ) {
|
if ( flags.driver.empty() ) {
|
||||||
|
|
|
@ -361,8 +361,10 @@ struct ResonantFilter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To avoid a precision loss in the state variables especially with quiet samples at low cutoff and high mix rate, we pre-amplify the sample.
|
||||||
|
#define MIXING_FILTER_PREAMP 256
|
||||||
// Filter values are clipped to double the input range
|
// Filter values are clipped to double the input range
|
||||||
#define ClipFilter(x) Clamp<typename Traits::output_t, typename Traits::output_t>(x, int16_min * 2, int16_max * 2)
|
#define ClipFilter(x) Clamp<typename Traits::output_t, typename Traits::output_t>(x, int16_min * 2 * MIXING_FILTER_PREAMP, int16_max * 2 * MIXING_FILTER_PREAMP)
|
||||||
|
|
||||||
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const ModChannel &chn)
|
MPT_FORCEINLINE void operator() (typename Traits::outbuf_t &outSample, const ModChannel &chn)
|
||||||
{
|
{
|
||||||
|
@ -370,14 +372,15 @@ struct ResonantFilter
|
||||||
|
|
||||||
for(int i = 0; i < Traits::numChannelsIn; i++)
|
for(int i = 0; i < Traits::numChannelsIn; i++)
|
||||||
{
|
{
|
||||||
typename Traits::output_t val = static_cast<typename Traits::output_t>((
|
const auto inputAmp = outSample[i] * MIXING_FILTER_PREAMP;
|
||||||
Util::mul32to64(outSample[i], chn.nFilter_A0) +
|
typename Traits::output_t val = static_cast<typename Traits::output_t>(mpt::rshift_signed(
|
||||||
|
Util::mul32to64(inputAmp, chn.nFilter_A0) +
|
||||||
Util::mul32to64(ClipFilter(fy[i][0]), chn.nFilter_B0) +
|
Util::mul32to64(ClipFilter(fy[i][0]), chn.nFilter_B0) +
|
||||||
Util::mul32to64(ClipFilter(fy[i][1]), chn.nFilter_B1) +
|
Util::mul32to64(ClipFilter(fy[i][1]), chn.nFilter_B1) +
|
||||||
(1 << (MIXING_FILTER_PRECISION - 1))) / (1 << MIXING_FILTER_PRECISION));
|
(1 << (MIXING_FILTER_PRECISION - 1)), MIXING_FILTER_PRECISION));
|
||||||
fy[i][1] = fy[i][0];
|
fy[i][1] = fy[i][0];
|
||||||
fy[i][0] = val - (outSample[i] & chn.nFilter_HP);
|
fy[i][0] = val - (inputAmp & chn.nFilter_HP);
|
||||||
outSample[i] = val;
|
outSample[i] = val / MIXING_FILTER_PREAMP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,7 @@ bool CSoundFile::ReadSTM(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
if(sampleHeader.zero != 0 && sampleHeader.zero != 46) // putup10.stm has zero = 46
|
if(sampleHeader.zero != 0 && sampleHeader.zero != 46) // putup10.stm has zero = 46
|
||||||
return false;
|
return false;
|
||||||
sampleHeader.ConvertToMPT(Samples[smp]);
|
sampleHeader.ConvertToMPT(Samples[smp]);
|
||||||
mpt::String::Read<mpt::String::nullTerminated>(m_szNames[smp], sampleHeader.filename);
|
mpt::String::Read<mpt::String::maybeNullTerminated>(m_szNames[smp], sampleHeader.filename);
|
||||||
sampleOffsets[smp - 1] = sampleHeader.offset;
|
sampleOffsets[smp - 1] = sampleHeader.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ bool CSoundFile::ReadSTM(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
ORDERINDEX breakPos = ORDERINDEX_INVALID;
|
ORDERINDEX breakPos = ORDERINDEX_INVALID;
|
||||||
ROWINDEX breakRow = 63; // Candidate row for inserting pattern break
|
ROWINDEX breakRow = 63; // Candidate row for inserting pattern break
|
||||||
|
|
||||||
for(int i = 0; i < 64 * 4; i++, m++)
|
for(unsigned int i = 0; i < 64 * 4; i++, m++)
|
||||||
{
|
{
|
||||||
uint8 note = file.ReadUint8(), insvol, volcmd, cmdinf;
|
uint8 note = file.ReadUint8(), insvol, volcmd, cmdinf;
|
||||||
switch(note)
|
switch(note)
|
||||||
|
@ -226,9 +226,13 @@ bool CSoundFile::ReadSTM(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
m->note = NOTE_NOTECUT;
|
m->note = NOTE_NOTECUT;
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
insvol = file.ReadUint8();
|
{
|
||||||
volcmd = file.ReadUint8();
|
uint8 patData[3];
|
||||||
cmdinf = file.ReadUint8();
|
file.ReadArray(patData);
|
||||||
|
insvol = patData[0];
|
||||||
|
volcmd = patData[1];
|
||||||
|
cmdinf = patData[2];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,16 +270,22 @@ bool CSoundFile::ReadSTM(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
{
|
{
|
||||||
case CMD_VOLUMESLIDE:
|
case CMD_VOLUMESLIDE:
|
||||||
// Lower nibble always has precedence, and there are no fine slides.
|
// Lower nibble always has precedence, and there are no fine slides.
|
||||||
if(m->param & 0x0F) m->param &= 0x0F;
|
if(m->param & 0x0F)
|
||||||
else m->param &= 0xF0;
|
m->param &= 0x0F;
|
||||||
|
else
|
||||||
|
m->param &= 0xF0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_PATTERNBREAK:
|
case CMD_PATTERNBREAK:
|
||||||
m->param = (m->param & 0xF0) * 10 + (m->param & 0x0F);
|
m->param = (m->param & 0xF0) * 10 + (m->param & 0x0F);
|
||||||
if(breakRow > m->param)
|
if(breakPos != ORDERINDEX_INVALID && m->param == 0)
|
||||||
{
|
{
|
||||||
breakRow = m->param;
|
// Merge Bxx + C00 into just Bxx
|
||||||
|
m->command = CMD_POSITIONJUMP;
|
||||||
|
m->param = static_cast<ModCommand::PARAM>(breakPos);
|
||||||
|
breakPos = ORDERINDEX_INVALID;
|
||||||
}
|
}
|
||||||
|
LimitMax(breakRow, i / 4u);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_POSITIONJUMP:
|
case CMD_POSITIONJUMP:
|
||||||
|
|
|
@ -85,6 +85,17 @@ struct UltSample
|
||||||
MPT_BINARY_STRUCT(UltSample, 66)
|
MPT_BINARY_STRUCT(UltSample, 66)
|
||||||
|
|
||||||
|
|
||||||
|
struct UltPatternCommand
|
||||||
|
{
|
||||||
|
uint8 instr;
|
||||||
|
uint8 cmd;
|
||||||
|
uint8 param1;
|
||||||
|
uint8 param2;
|
||||||
|
};
|
||||||
|
|
||||||
|
MPT_BINARY_STRUCT(UltPatternCommand, 4)
|
||||||
|
|
||||||
|
|
||||||
/* Unhandled effects:
|
/* Unhandled effects:
|
||||||
5x1 - do not loop sample (x is unused)
|
5x1 - do not loop sample (x is unused)
|
||||||
9xx - set sample offset to xx * 1024
|
9xx - set sample offset to xx * 1024
|
||||||
|
@ -215,13 +226,14 @@ static int ReadULTEvent(ModCommand &m, FileReader &file, uint8 version)
|
||||||
b = file.ReadUint8();
|
b = file.ReadUint8();
|
||||||
}
|
}
|
||||||
|
|
||||||
m.note = (b > 0 && b < 61) ? b + 36 : NOTE_NONE;
|
m.note = (b > 0 && b < 61) ? (b + 35 + NOTE_MIN) : NOTE_NONE;
|
||||||
m.instr = file.ReadUint8();
|
UltPatternCommand patCmd;
|
||||||
b = file.ReadUint8();
|
file.ReadStruct(patCmd);
|
||||||
cmd1 = b & 0x0F;
|
m.instr = patCmd.instr;
|
||||||
cmd2 = b >> 4;
|
cmd1 = patCmd.cmd & 0x0F;
|
||||||
param1 = file.ReadUint8();
|
cmd2 = patCmd.cmd >> 4;
|
||||||
param2 = file.ReadUint8();
|
param1 = patCmd.param1;
|
||||||
|
param2 = patCmd.param2;
|
||||||
TranslateULTCommands(cmd1, param1, version);
|
TranslateULTCommands(cmd1, param1, version);
|
||||||
TranslateULTCommands(cmd2, param2, version);
|
TranslateULTCommands(cmd2, param2, version);
|
||||||
|
|
||||||
|
@ -295,7 +307,7 @@ struct PostFixUltCommands
|
||||||
// Apply porta?
|
// Apply porta?
|
||||||
if(m.note == NOTE_NONE && isPortaActive[curChannel])
|
if(m.note == NOTE_NONE && isPortaActive[curChannel])
|
||||||
{
|
{
|
||||||
if(m.command == CMD_NONE && m.vol != VOLCMD_TONEPORTAMENTO)
|
if(m.command == CMD_NONE && m.volcmd != VOLCMD_TONEPORTAMENTO)
|
||||||
{
|
{
|
||||||
m.command = CMD_TONEPORTAMENTO;
|
m.command = CMD_TONEPORTAMENTO;
|
||||||
m.param = 0;
|
m.param = 0;
|
||||||
|
@ -345,6 +357,10 @@ static bool ValidateHeader(const UltFileHeader &fileHeader)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64 GetHeaderMinimumAdditionalSize(const UltFileHeader &fileHeader)
|
||||||
|
{
|
||||||
|
return fileHeader.messageLength * 32u;
|
||||||
|
}
|
||||||
|
|
||||||
CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderULT(MemoryFileReader file, const uint64 *pfilesize)
|
CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderULT(MemoryFileReader file, const uint64 *pfilesize)
|
||||||
{
|
{
|
||||||
|
@ -357,8 +373,7 @@ CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderULT(MemoryFileReader file, co
|
||||||
{
|
{
|
||||||
return ProbeFailure;
|
return ProbeFailure;
|
||||||
}
|
}
|
||||||
MPT_UNREFERENCED_PARAMETER(pfilesize);
|
return ProbeAdditionalSize(file, pfilesize, GetHeaderMinimumAdditionalSize(fileHeader));
|
||||||
return ProbeSuccess;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -379,6 +394,10 @@ bool CSoundFile::ReadUlt(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if(!file.CanRead(mpt::saturate_cast<FileReader::off_t>(GetHeaderMinimumAdditionalSize(fileHeader))))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
InitializeGlobals(MOD_TYPE_ULT);
|
InitializeGlobals(MOD_TYPE_ULT);
|
||||||
mpt::String::Read<mpt::String::maybeNullTerminated>(m_songName, fileHeader.songName);
|
mpt::String::Read<mpt::String::maybeNullTerminated>(m_songName, fileHeader.songName);
|
||||||
|
@ -442,12 +461,9 @@ bool CSoundFile::ReadUlt(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
for(CHANNELINDEX chn = 0; chn < m_nChannels; chn++)
|
for(CHANNELINDEX chn = 0; chn < m_nChannels; chn++)
|
||||||
{
|
{
|
||||||
ModCommand evnote;
|
ModCommand evnote;
|
||||||
ModCommand *note;
|
for(PATTERNINDEX pat = 0; pat < numPats && file.CanRead(5); pat++)
|
||||||
evnote.Clear();
|
|
||||||
|
|
||||||
for(PATTERNINDEX pat = 0; pat < numPats; pat++)
|
|
||||||
{
|
{
|
||||||
note = Patterns[pat].GetpModCommand(0, chn);
|
ModCommand *note = Patterns[pat].GetpModCommand(0, chn);
|
||||||
ROWINDEX row = 0;
|
ROWINDEX row = 0;
|
||||||
while(row < 64)
|
while(row < 64)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,7 @@ OPENMPT_NAMESPACE_BEGIN
|
||||||
|
|
||||||
#ifdef MPT_INTMIXER
|
#ifdef MPT_INTMIXER
|
||||||
typedef int32 mixsample_t;
|
typedef int32 mixsample_t;
|
||||||
enum { MIXING_FILTER_PRECISION = 16 }; // Fixed point resonant filter bits
|
enum { MIXING_FILTER_PRECISION = 24 }; // Fixed point resonant filter bits
|
||||||
#else
|
#else
|
||||||
typedef float mixsample_t;
|
typedef float mixsample_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1665,7 +1665,7 @@ bool CSoundFile::ReadSFZInstrument(INSTRUMENTINDEX nInstr, FileReader &file)
|
||||||
}
|
}
|
||||||
if(!region.name.empty())
|
if(!region.name.empty())
|
||||||
{
|
{
|
||||||
mpt::String::Copy(m_szNames[smp], region.name);
|
mpt::String::Copy(m_szNames[smp], mpt::ToCharset(GetCharsetInternal(), mpt::CharsetUTF8, region.name));
|
||||||
}
|
}
|
||||||
if(!m_szNames[smp][0])
|
if(!m_szNames[smp][0])
|
||||||
{
|
{
|
||||||
|
|
|
@ -133,7 +133,7 @@ public:
|
||||||
const_iterator end() const { return m_ModCommands.end(); }
|
const_iterator end() const { return m_ModCommands.end(); }
|
||||||
const_iterator cend() const { return m_ModCommands.cend(); }
|
const_iterator cend() const { return m_ModCommands.cend(); }
|
||||||
|
|
||||||
CPattern(CPatternContainer& patCont) : m_ModCommands(0), m_Rows(64), m_RowsPerBeat(0), m_RowsPerMeasure(0), m_rPatternContainer(patCont) {};
|
CPattern(CPatternContainer& patCont) : m_rPatternContainer(patCont) {};
|
||||||
CPattern(const CPattern &) = default;
|
CPattern(const CPattern &) = default;
|
||||||
CPattern(CPattern &&) noexcept = default;
|
CPattern(CPattern &&) noexcept = default;
|
||||||
|
|
||||||
|
@ -148,9 +148,9 @@ protected:
|
||||||
//BEGIN: DATA
|
//BEGIN: DATA
|
||||||
protected:
|
protected:
|
||||||
std::vector<ModCommand> m_ModCommands;
|
std::vector<ModCommand> m_ModCommands;
|
||||||
ROWINDEX m_Rows;
|
ROWINDEX m_Rows = 0;
|
||||||
ROWINDEX m_RowsPerBeat; // patterns-specific time signature. if != 0, this is implicitely set.
|
ROWINDEX m_RowsPerBeat = 0; // patterns-specific time signature. if != 0, this is implicitely set.
|
||||||
ROWINDEX m_RowsPerMeasure; // ditto
|
ROWINDEX m_RowsPerMeasure = 0; // ditto
|
||||||
TempoSwing m_tempoSwing;
|
TempoSwing m_tempoSwing;
|
||||||
std::string m_PatternName;
|
std::string m_PatternName;
|
||||||
CPatternContainer& m_rPatternContainer;
|
CPatternContainer& m_rPatternContainer;
|
||||||
|
|
Loading…
Reference in New Issue