Update mixing code

This commit is contained in:
bnnm 2019-03-18 00:05:44 +01:00
parent dd1bafb201
commit 151de6a39c
4 changed files with 76 additions and 51 deletions

View File

@ -21,7 +21,7 @@
#define VERSION "(unknown version)" #define VERSION "(unknown version)"
#endif #endif
#define BUFFER_SAMPLES 0x8000 #define SAMPLE_BUFFER_SIZE 0x8000
/* getopt globals (the horror...) */ /* getopt globals (the horror...) */
extern char * optarg; 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); 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)) { 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."); fprintf(stderr,"I could play a nonlooped track forever, but it wouldn't end well.");
goto fail; goto fail;
@ -462,15 +470,7 @@ int main(int argc, char ** argv) {
/* last init */ /* last init */
channels = vgmstream->channels; buf = malloc(SAMPLE_BUFFER_SIZE * sizeof(sample_t) * input_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);
if (!buf) { if (!buf) {
fprintf(stderr,"failed allocating output buffer\n"); fprintf(stderr,"failed allocating output buffer\n");
goto fail; goto fail;
@ -492,7 +492,7 @@ int main(int argc, char ** argv) {
/* decode forever */ /* decode forever */
while (cfg.play_forever) { while (cfg.play_forever) {
int to_get = BUFFER_SAMPLES; int to_get = SAMPLE_BUFFER_SIZE;
render_vgmstream(buf, to_get, vgmstream); render_vgmstream(buf, to_get, vgmstream);
@ -508,9 +508,9 @@ int main(int argc, char ** argv) {
/* decode */ /* decode */
for (i = 0; i < len_samples; i += BUFFER_SAMPLES) { for (i = 0; i < len_samples; i += SAMPLE_BUFFER_SIZE) {
int to_get = BUFFER_SAMPLES; int to_get = SAMPLE_BUFFER_SIZE;
if (i + BUFFER_SAMPLES > len_samples) if (i + SAMPLE_BUFFER_SIZE > len_samples)
to_get = len_samples - i; to_get = len_samples - i;
render_vgmstream(buf, to_get, vgmstream); render_vgmstream(buf, to_get, vgmstream);
@ -563,9 +563,9 @@ int main(int argc, char ** argv) {
} }
/* decode */ /* decode */
for (i = 0; i < len_samples; i += BUFFER_SAMPLES) { for (i = 0; i < len_samples; i += SAMPLE_BUFFER_SIZE) {
int to_get = BUFFER_SAMPLES; int to_get = SAMPLE_BUFFER_SIZE;
if (i + BUFFER_SAMPLES > len_samples) if (i + SAMPLE_BUFFER_SIZE > len_samples)
to_get = len_samples - i; to_get = len_samples - i;
render_vgmstream(buf, to_get, vgmstream); render_vgmstream(buf, to_get, vgmstream);

View File

@ -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) { void mixing_macro_volume(VGMSTREAM* vgmstream, double volume, uint32_t mask) {
mixing_data *data = vgmstream->mixing_data; mixing_data *data = vgmstream->mixing_data;
int ch, output_channels; int ch;
if (!data)
return;
if (mask == 0) { if (mask == 0) {
mixing_push_volume(vgmstream, -1, volume); mixing_push_volume(vgmstream, -1, volume);
return; return;
} }
output_channels = data ? data->output_channels : vgmstream->channels; for (ch = 0; ch < data->output_channels; ch++) {
for (ch = 0; ch < output_channels; ch++) {
if (!((mask >> ch) & 1)) if (!((mask >> ch) & 1))
continue; continue;
mixing_push_volume(vgmstream, ch, volume); 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) { void mixing_macro_track(VGMSTREAM* vgmstream, uint32_t mask) {
mixing_data *data = vgmstream->mixing_data; mixing_data *data = vgmstream->mixing_data;
int ch, output_channels; int ch;
if (!data)
return;
if (mask == 0) { if (mask == 0) {
return; return;
} }
output_channels = data ? data->output_channels : vgmstream->channels;
/* reverse remove all channels (easier this way as when removing channels numbers change) */ /* 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) if ((mask >> ch) & 1)
continue; continue;
mixing_push_downmix(vgmstream, ch); 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) { void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, int overlap) {
mixing_data *data = vgmstream->mixing_data; 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) */ /* set all channels (non-existant channels will be ignored) */
if (mask == 0) { if (mask == 0) {
mask = ~mask; mask = ~mask;
} }
output_channels = data ? data->output_channels : vgmstream->channels;
/* count possibly set channels */ /* count possibly set channels */
selected_channels = 0; selected_channels = 0;
for (ch = 0; ch < output_channels; ch++) { for (ch = 0; ch < data->output_channels; ch++) {
selected_channels += (mask >> ch) & 1; 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 ... */ /* add all layers in this order: ch0: 0, 0+N, 0+N*2 ... / ch1: 1, 1+N ... */
current = 0; current = 0;
for (ch = 0; ch < output_channels; ch++) { for (ch = 0; ch < data->output_channels; ch++) {
double volume = 1.0; double volume = 1.0;
if (!((mask >> ch) & 1)) 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 /* 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) */ * 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; int channel_mixes = selected_channels / max;
if (channel_mixes <= 0) /* ??? */
channel_mixes = 1;
if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */ if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */
channel_mixes += 1; 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; int current, ch, track, track_ch, track_num, output_channels;
int32_t change_pos, change_next, change_time; 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? */ if (!vgmstream->loop_flag) /* maybe force loop? */
return; return;
/* this probably only makes sense for even channels so upmix before if needed) */ /* 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) { if (output_channels % 2) {
mixing_push_upmix(vgmstream, output_channels); mixing_push_upmix(vgmstream, output_channels);
output_channels += 1; 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; int current, ch, layer, layer_ch, layer_num, loop, output_channels;
int32_t change_pos, change_time; int32_t change_pos, change_time;
if (!data)
return;
if (max <= 0 || data->output_channels <= max)
return;
if (!vgmstream->loop_flag) /* maybe force loop? */ if (!vgmstream->loop_flag) /* maybe force loop? */
return; return;
/* this probably only makes sense for even channels so upmix before if needed) */ /* 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) { if (output_channels % 2) {
mixing_push_upmix(vgmstream, output_channels); mixing_push_upmix(vgmstream, output_channels);
output_channels += 1; output_channels += 1;
@ -889,9 +901,9 @@ void mixing_setup(VGMSTREAM * vgmstream, int32_t max_sample_count) {
data->mixing_on = 1; data->mixing_on = 1;
/* a bit wonky but eh... */ /* 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->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 /* since data exists on its own memory and pointer is already set
@ -904,23 +916,22 @@ fail:
return; 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; mixing_data *data = vgmstream->mixing_data;
int input_channels, output_channels;
if (!data) goto fail; 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 (out_input_channels) *out_input_channels = input_channels;
if (data->output_channels > vgmstream->channels) if (out_output_channels) *out_output_channels = output_channels;
*input_channels = data->output_channels;
else
*input_channels = vgmstream->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; return;
fail: fail:
return; 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; mixing_data *data = vgmstream->mixing_data;
if (!data) goto fail; if (!data) goto fail;
if (max_channels <= 0)
return;
/* guess mixing the best we can */ /* guess mixing the best we can */
//todo: could use standard downmixing for known max_channels <> vgmstream->channels combos: //todo: could use standard downmixing for known max_channels <> vgmstream->channels combos:

View File

@ -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); 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 */ /* 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 */ /* sets a fadeout */
//void vgmstream_mixing_fadeout(VGMSTREAM *vgmstream, float start_second, float duration_seconds); //void vgmstream_mixing_fadeout(VGMSTREAM *vgmstream, float start_second, float duration_seconds);

View File

@ -2315,6 +2315,18 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
snprintf(temp,TEMPSIZE, "channels: %d\n", vgmstream->channels); snprintf(temp,TEMPSIZE, "channels: %d\n", vgmstream->channels);
concatn(length,desc,temp); 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) { if (vgmstream->channel_layout) {
int cl = 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; return 1;
fail: fail:
VGM_LOG("fail\n");
/* open streams will be closed in close_vgmstream(), hopefully called by the meta */ /* open streams will be closed in close_vgmstream(), hopefully called by the meta */
return 0; return 0;
} }