mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 00:20:47 +01:00
Update mixing code
This commit is contained in:
parent
dd1bafb201
commit
151de6a39c
@ -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);
|
||||
|
76
src/mixing.c
76
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:
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user