From 151de6a39cb71f0b8c48c9058debade07e251dc1 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 18 Mar 2019 00:05:44 +0100 Subject: [PATCH] Update mixing code --- cli/vgmstream_cli.c | 36 ++++++++++----------- src/mixing.c | 76 +++++++++++++++++++++++++++------------------ src/plugins.h | 2 +- src/vgmstream.c | 13 +++++++- 4 files changed, 76 insertions(+), 51 deletions(-) diff --git a/cli/vgmstream_cli.c b/cli/vgmstream_cli.c index 1a04d6ca..d441ae43 100644 --- a/cli/vgmstream_cli.c +++ b/cli/vgmstream_cli.c @@ -21,7 +21,7 @@ #define VERSION "(unknown version)" #endif -#define BUFFER_SAMPLES 0x8000 +#define SAMPLE_BUFFER_SIZE 0x8000 /* getopt globals (the horror...) */ extern char * optarg; @@ -384,9 +384,17 @@ int main(int argc, char ** argv) { } - /* modify the VGMSTREAM if needed */ + /* modify the VGMSTREAM if needed (before printing file info) */ apply_config(vgmstream, &cfg); + channels = vgmstream->channels; + input_channels = vgmstream->channels; + +#ifdef VGMSTREAM_MIXING + /* enable after config but before outbuf */ + vgmstream_mixing_enable(vgmstream, SAMPLE_BUFFER_SIZE, &input_channels, &channels); +#endif + if (cfg.play_forever && (!vgmstream->loop_flag || vgmstream->loop_target > 0)) { fprintf(stderr,"I could play a nonlooped track forever, but it wouldn't end well."); goto fail; @@ -462,15 +470,7 @@ int main(int argc, char ** argv) { /* last init */ - channels = vgmstream->channels; - input_channels = vgmstream->channels; - -#ifdef VGMSTREAM_MIXING - /* enable after all config but before outbuf */ - vgmstream_mixing_enable(vgmstream, BUFFER_SAMPLES, &input_channels, &channels); -#endif - - buf = malloc(BUFFER_SAMPLES * sizeof(sample_t) * input_channels); + buf = malloc(SAMPLE_BUFFER_SIZE * sizeof(sample_t) * input_channels); if (!buf) { fprintf(stderr,"failed allocating output buffer\n"); goto fail; @@ -492,7 +492,7 @@ int main(int argc, char ** argv) { /* decode forever */ while (cfg.play_forever) { - int to_get = BUFFER_SAMPLES; + int to_get = SAMPLE_BUFFER_SIZE; render_vgmstream(buf, to_get, vgmstream); @@ -508,9 +508,9 @@ int main(int argc, char ** argv) { /* decode */ - for (i = 0; i < len_samples; i += BUFFER_SAMPLES) { - int to_get = BUFFER_SAMPLES; - if (i + BUFFER_SAMPLES > len_samples) + for (i = 0; i < len_samples; i += SAMPLE_BUFFER_SIZE) { + int to_get = SAMPLE_BUFFER_SIZE; + if (i + SAMPLE_BUFFER_SIZE > len_samples) to_get = len_samples - i; render_vgmstream(buf, to_get, vgmstream); @@ -563,9 +563,9 @@ int main(int argc, char ** argv) { } /* decode */ - for (i = 0; i < len_samples; i += BUFFER_SAMPLES) { - int to_get = BUFFER_SAMPLES; - if (i + BUFFER_SAMPLES > len_samples) + for (i = 0; i < len_samples; i += SAMPLE_BUFFER_SIZE) { + int to_get = SAMPLE_BUFFER_SIZE; + if (i + SAMPLE_BUFFER_SIZE > len_samples) to_get = len_samples - i; render_vgmstream(buf, to_get, vgmstream); diff --git a/src/mixing.c b/src/mixing.c index 88c77cc9..d168d7b7 100644 --- a/src/mixing.c +++ b/src/mixing.c @@ -658,17 +658,17 @@ void mixing_push_fade(VGMSTREAM* vgmstream, int ch_dst, double vol_start, double void mixing_macro_volume(VGMSTREAM* vgmstream, double volume, uint32_t mask) { mixing_data *data = vgmstream->mixing_data; - int ch, output_channels; + int ch; + if (!data) + return; if (mask == 0) { mixing_push_volume(vgmstream, -1, volume); return; } - output_channels = data ? data->output_channels : vgmstream->channels; - - for (ch = 0; ch < output_channels; ch++) { + for (ch = 0; ch < data->output_channels; ch++) { if (!((mask >> ch) & 1)) continue; mixing_push_volume(vgmstream, ch, volume); @@ -677,16 +677,17 @@ void mixing_macro_volume(VGMSTREAM* vgmstream, double volume, uint32_t mask) { void mixing_macro_track(VGMSTREAM* vgmstream, uint32_t mask) { mixing_data *data = vgmstream->mixing_data; - int ch, output_channels; + int ch; + + if (!data) + return; if (mask == 0) { return; } - output_channels = data ? data->output_channels : vgmstream->channels; - /* reverse remove all channels (easier this way as when removing channels numbers change) */ - for (ch = output_channels - 1; ch >= 0; ch--) { + for (ch = data->output_channels - 1; ch >= 0; ch--) { if ((mask >> ch) & 1) continue; mixing_push_downmix(vgmstream, ch); @@ -695,18 +696,21 @@ void mixing_macro_track(VGMSTREAM* vgmstream, uint32_t mask) { void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, int overlap) { mixing_data *data = vgmstream->mixing_data; - int current, ch, output_channels, selected_channels; + int current, ch, selected_channels; + + if (!data) + return; + if (max <= 0 || data->output_channels <= max) + return; /* set all channels (non-existant channels will be ignored) */ if (mask == 0) { mask = ~mask; } - output_channels = data ? data->output_channels : vgmstream->channels; - /* count possibly set channels */ selected_channels = 0; - for (ch = 0; ch < output_channels; ch++) { + for (ch = 0; ch < data->output_channels; ch++) { selected_channels += (mask >> ch) & 1; } @@ -717,7 +721,7 @@ void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, int overla /* add all layers in this order: ch0: 0, 0+N, 0+N*2 ... / ch1: 1, 1+N ... */ current = 0; - for (ch = 0; ch < output_channels; ch++) { + for (ch = 0; ch < data->output_channels; ch++) { double volume = 1.0; if (!((mask >> ch) & 1)) @@ -728,6 +732,8 @@ void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, int overla /* find how many will be mixed in current channel (earlier channels receive more * mixes than later ones, ex: selected 8ch + max 3ch: ch0=0+3+6, ch1=1+4+7, ch2=2+5) */ int channel_mixes = selected_channels / max; + if (channel_mixes <= 0) /* ??? */ + channel_mixes = 1; if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */ channel_mixes += 1; @@ -749,12 +755,15 @@ void mixing_macro_crosstrack(VGMSTREAM* vgmstream, int max) { int current, ch, track, track_ch, track_num, output_channels; int32_t change_pos, change_next, change_time; - + if (!data) + return; + if (max <= 0 || data->output_channels <= max) + return; if (!vgmstream->loop_flag) /* maybe force loop? */ return; /* this probably only makes sense for even channels so upmix before if needed) */ - output_channels = data ? data->output_channels : vgmstream->channels; + output_channels = data->output_channels; if (output_channels % 2) { mixing_push_upmix(vgmstream, output_channels); output_channels += 1; @@ -807,12 +816,15 @@ void mixing_macro_crosslayer(VGMSTREAM* vgmstream, int max) { int current, ch, layer, layer_ch, layer_num, loop, output_channels; int32_t change_pos, change_time; - + if (!data) + return; + if (max <= 0 || data->output_channels <= max) + return; if (!vgmstream->loop_flag) /* maybe force loop? */ return; /* this probably only makes sense for even channels so upmix before if needed) */ - output_channels = data ? data->output_channels : vgmstream->channels; + output_channels = data->output_channels; if (output_channels % 2) { mixing_push_upmix(vgmstream, output_channels); output_channels += 1; @@ -889,9 +901,9 @@ void mixing_setup(VGMSTREAM * vgmstream, int32_t max_sample_count) { data->mixing_on = 1; /* a bit wonky but eh... */ - if (vgmstream->channel_layout && vgmstream->channels != vgmstream->output_channels) { + if (vgmstream->channel_layout && vgmstream->channels != data->output_channels) { vgmstream->channel_layout = 0; - vgmstream->start_vgmstream->channel_layout = 0; + ((VGMSTREAM*)vgmstream->start_vgmstream)->channel_layout = 0; } /* since data exists on its own memory and pointer is already set @@ -904,23 +916,22 @@ fail: return; } -void mixing_info(VGMSTREAM * vgmstream, int *input_channels, int *output_channels) { +void mixing_info(VGMSTREAM * vgmstream, int *out_input_channels, int *out_output_channels) { mixing_data *data = vgmstream->mixing_data; + int input_channels, output_channels; if (!data) goto fail; - if (output_channels) { - *output_channels = data->output_channels; - } + output_channels = data->output_channels; + if (data->output_channels > vgmstream->channels) + input_channels = data->output_channels; + else + input_channels = vgmstream->channels; - if (input_channels) { - if (data->output_channels > vgmstream->channels) - *input_channels = data->output_channels; - else - *input_channels = vgmstream->channels; - } + if (out_input_channels) *out_input_channels = input_channels; + if (out_output_channels) *out_output_channels = output_channels; - //;VGM_LOG("MIX: channels in=%i, out=%i, mix=%i\n", *input_channels, *output_channels, data->mixing_channels); + //;VGM_LOG("MIX: channels %i, in=%i, out=%i, mix=%i\n", vgmstream->channels, input_channels, output_channels, data->mixing_channels); return; fail: return; @@ -933,11 +944,14 @@ void vgmstream_mixing_enable(VGMSTREAM* vgmstream, int32_t max_sample_count, int /* ********************************************************* */ -void vgmstream_mixing_downmix(VGMSTREAM *vgmstream, int max_channels) { +void vgmstream_mixing_autodownmix(VGMSTREAM *vgmstream, int max_channels) { mixing_data *data = vgmstream->mixing_data; if (!data) goto fail; + if (max_channels <= 0) + return; + /* guess mixing the best we can */ //todo: could use standard downmixing for known max_channels <> vgmstream->channels combos: diff --git a/src/plugins.h b/src/plugins.h index 4f9af079..a6c2d08e 100644 --- a/src/plugins.h +++ b/src/plugins.h @@ -87,7 +87,7 @@ void vgmstream_tags_close(VGMSTREAM_TAGS* tags); void vgmstream_mixing_enable(VGMSTREAM* vgmstream, int32_t max_sample_count, int *input_channels, int *output_channels); /* sets automatic downmixing if vgmstream's channels are higher than max_channels */ -void vgmstream_mixing_downmix(VGMSTREAM *vgmstream, int max_channels); +void vgmstream_mixing_autodownmix(VGMSTREAM *vgmstream, int max_channels); /* sets a fadeout */ //void vgmstream_mixing_fadeout(VGMSTREAM *vgmstream, float start_second, float duration_seconds); diff --git a/src/vgmstream.c b/src/vgmstream.c index fb4242a1..5288826f 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -2315,6 +2315,18 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { snprintf(temp,TEMPSIZE, "channels: %d\n", vgmstream->channels); concatn(length,desc,temp); +#ifdef VGMSTREAM_MIXING + { + int output_channels = 0; + mixing_info(vgmstream, NULL, &output_channels); + + if (output_channels != vgmstream->channels) { + snprintf(temp,TEMPSIZE, "output channels: %d\n", output_channels); + concatn(length,desc,temp); + } + } +#endif + if (vgmstream->channel_layout) { int cl = vgmstream->channel_layout; @@ -2903,7 +2915,6 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s return 1; fail: -VGM_LOG("fail\n"); /* open streams will be closed in close_vgmstream(), hopefully called by the meta */ return 0; }