diff --git a/Makefile.emscripten b/Makefile.emscripten index 19a98ef475..2901a9cc4d 100644 --- a/Makefile.emscripten +++ b/Makefile.emscripten @@ -35,6 +35,7 @@ HAVE_STATIC_AUDIO_FILTERS = 1 HAVE_STB_FONT = 1 HAVE_CONFIGFILE = 1 HAVE_CHEATS = 1 +HAVE_IBXM = 1 MEMORY = 134217728 diff --git a/Makefile.libnx b/Makefile.libnx index b126382b59..f75703b060 100644 --- a/Makefile.libnx +++ b/Makefile.libnx @@ -50,6 +50,7 @@ HAVE_STB_FONT = 1 HAVE_CHEEVOS = 1 HAVE_CHD = 0 # disabled due to static libretro-common and libchdr conflicts between different cores HAVE_STB_VORBIS = 1 +HAVE_IBXM = 1 # RetroArch libnx useful flags HAVE_THREADS = 1 diff --git a/Makefile.switch b/Makefile.switch index e5b32bd3c3..c46bddb873 100644 --- a/Makefile.switch +++ b/Makefile.switch @@ -40,6 +40,7 @@ else HAVE_DYNAMIC = 1 HAVE_PATCH = 1 HAVE_CHEATS = 1 + HAVE_IBXM = 1 include Makefile.common CFLAGS += $(DEF_FLAGS) diff --git a/deps/ibxm/README b/deps/ibxm/README index 7acec1a9b5..d32aec027d 100644 --- a/deps/ibxm/README +++ b/deps/ibxm/README @@ -1,5 +1,5 @@ -Micromod (c)2017 mumart@gmail.com +Micromod (c)2019 mumart@gmail.com A good-quality player library for the ProTracker MOD music format for Javascript (HTML5 Web Audio), Java, ANSI C (SDL) and Pascal (SDL). diff --git a/deps/ibxm/ibxm.c b/deps/ibxm/ibxm.c index 2097cedc12..0c677e21ad 100644 --- a/deps/ibxm/ibxm.c +++ b/deps/ibxm/ibxm.c @@ -4,7 +4,7 @@ #include "ibxm.h" -const char *IBXM_VERSION = "ibxm/ac mod/xm/s3m replay 20170901 (c)mumart@gmail.com"; +const char *IBXM_VERSION = "ibxm/ac mod/xm/s3m replay 20191214 (c)mumart@gmail.com"; static const int FP_SHIFT = 15, FP_ONE = 32768, FP_MASK = 32767; @@ -787,8 +787,14 @@ static struct module* module_load_mod( struct data *data, char *message ) { if( param == 0 && ( effect == 5 || effect == 6 ) ) { effect -= 2; } - if( effect == 8 && module->num_channels == 4 ) { - effect = param = 0; + if( effect == 8 ) { + if( module->num_channels == 4 ) { + effect = param = 0; + } else if( param > 128 ) { + param = 128; + } else { + param = ( param * 255 ) >> 7; + } } pattern_data[ pat_data_idx + 3 ] = effect; pattern_data[ pat_data_idx + 4 ] = param; @@ -851,7 +857,7 @@ static struct module* module_load_mod( struct data *data, char *message ) { } /* Allocate and initialize a module from the specified data, returns NULL on error. - Message should point to a 64-character buffer to receive error messages. */ + Message must point to a 64-character buffer to receive error messages. */ struct module* module_load( struct data *data, char *message ) { char ascii[ 16 ]; struct module* module; @@ -1427,7 +1433,7 @@ static void channel_row( struct channel *channel, struct note *note ) { channel_tremolo( channel ); break; case 0x08: /* Set Panning.*/ - channel->panning = ( channel->note.param < 128 ) ? ( channel->note.param << 1 ) : 255; + channel->panning = channel->note.param & 0xFF; break; case 0x0A: case 0x84: /* Vol Slide. */ if( channel->note.param > 0 ) { @@ -1901,8 +1907,9 @@ static void downsample( int *buf, int count ) { } } -/* Generates audio and returns the number of stereo samples written into mix_buf. */ -int replay_get_audio( struct replay *replay, int *mix_buf ) { +/* Generates audio and returns the number of stereo samples written into mix_buf. + Individual channels may be excluded using the mute bitmask. */ +int replay_get_audio( struct replay *replay, int *mix_buf, int mute ) { struct channel *channel; int idx, num_channels, tick_len = calculate_tick_len( replay->tempo, replay->sample_rate ); /* Clear output buffer. */ @@ -1911,12 +1918,25 @@ int replay_get_audio( struct replay *replay, int *mix_buf ) { num_channels = replay->module->num_channels; for( idx = 0; idx < num_channels; idx++ ) { channel = &replay->channels[ idx ]; - channel_resample( channel, mix_buf, 0, ( tick_len + 65 ) * 2, - replay->sample_rate * 2, replay->interpolation ); + if( !( mute & 1 ) ) { + channel_resample( channel, mix_buf, 0, ( tick_len + 65 ) * 2, + replay->sample_rate * 2, replay->interpolation ); + } channel_update_sample_idx( channel, tick_len * 2, replay->sample_rate * 2 ); + mute >>= 1; } downsample( mix_buf, tick_len + 64 ); replay_volume_ramp( replay, mix_buf, tick_len ); replay_tick( replay ); return tick_len; } + +/* Returns the currently playing pattern in the sequence.*/ +int replay_get_sequence_pos( struct replay *replay ) { + return replay->seq_pos; +} + +/* Returns the currently playing row in the pattern. */ +int replay_get_row( struct replay *replay ) { + return replay->row; +} diff --git a/deps/ibxm/ibxm.h b/deps/ibxm/ibxm.h index 0949b2c6ca..b939b44f7c 100644 --- a/deps/ibxm/ibxm.h +++ b/deps/ibxm/ibxm.h @@ -48,7 +48,7 @@ struct module { }; /* Allocate and initialize a module from the specified data, returns NULL on error. - Message should point to a 64-character buffer to receive error messages. */ + Message must point to a 64-character buffer to receive error messages. */ struct module* module_load( struct data *data, char *message ); /* Deallocate the specified module. */ void dispose_module( struct module *module ); @@ -63,8 +63,13 @@ int replay_calculate_duration( struct replay *replay ); int replay_seek( struct replay *replay, int sample_pos ); /* Set the pattern in the sequence to play. The tempo is reset to the default. */ void replay_set_sequence_pos( struct replay *replay, int pos ); -/* Generates audio and returns the number of stereo samples written into mix_buf. */ -int replay_get_audio( struct replay *replay, int *mix_buf ); +/* Generates audio and returns the number of stereo samples written into mix_buf. + Individual channels may be excluded using the mute bitmask. */ +int replay_get_audio( struct replay *replay, int *mix_buf, int mute ); +/* Returns the currently playing pattern in the sequence.*/ +int replay_get_sequence_pos( struct replay *replay ); +/* Returns the currently playing row in the pattern. */ +int replay_get_row( struct replay *replay ); /* Returns the length of the output buffer required by replay_get_audio(). */ int calculate_mix_buf_len( int sample_rate ); diff --git a/libretro-common/audio/audio_mixer.c b/libretro-common/audio/audio_mixer.c index 8afe74c0fd..d064831696 100644 --- a/libretro-common/audio/audio_mixer.c +++ b/libretro-common/audio/audio_mixer.c @@ -996,13 +996,11 @@ static void audio_mixer_mix_mod(float* buffer, size_t num_frames, unsigned buf_free = (unsigned)(num_frames * 2); int* pcm = NULL; - if (voice->types.mod.position == voice->types.mod.samples) + if (voice->types.mod.samples == 0) { again: temp_samples = replay_get_audio( - voice->types.mod.stream, voice->types.mod.buffer ); - - temp_samples *= 2; /* stereo */ + voice->types.mod.stream, voice->types.mod.buffer, 0 ) * 2; if (temp_samples == 0) { @@ -1031,10 +1029,9 @@ again: { for (i = voice->types.mod.samples; i != 0; i--) { - samplei = *pcm++ * volume; - samplef = (float)((int)samplei + 32768) / 65535.0f; + samplef = ((float)(*pcm++) + 32768.0f) / 65535.0f; samplef = samplef * 2.0f - 1.0f; - *buffer++ += samplef; + *buffer++ += samplef * volume; } buf_free -= voice->types.mod.samples; @@ -1043,10 +1040,9 @@ again: for (i = buf_free; i != 0; --i ) { - samplei = *pcm++ * volume; - samplef = (float)((int)samplei + 32768) / 65535.0f; + samplef = ((float)(*pcm++) + 32768.0f) / 65535.0f; samplef = samplef * 2.0f - 1.0f; - *buffer++ += samplef; + *buffer++ += samplef * volume; } voice->types.mod.position += buf_free;