Preserve channel layout when downmixing some cases

This commit is contained in:
bnnm 2022-04-09 11:32:37 +02:00
parent 1c666f27d5
commit 80d8ce2414
4 changed files with 74 additions and 14 deletions

View File

@ -7,6 +7,7 @@ typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_silence(int channels, int sample_rate, int32_t num_samples);
VGMSTREAM* init_vgmstream_silence_container(int total_subsongs);
VGMSTREAM* init_vgmstream_silence_base(VGMSTREAM* vgmstream);
VGMSTREAM* init_vgmstream_adx(STREAMFILE* sf);

View File

@ -1,7 +1,7 @@
#include "meta.h"
/* silent stream - mainly for engines that need them or dummy subsongs */
VGMSTREAM* init_vgmstream_silence(int channels, int sample_rate, int32_t num_samples) {
static VGMSTREAM* init_vgmstream_silence_internal(int channels, int sample_rate, int32_t num_samples, uint32_t channel_layout) {
VGMSTREAM* vgmstream = NULL;
if (channels <= 0)
@ -18,6 +18,7 @@ VGMSTREAM* init_vgmstream_silence(int channels, int sample_rate, int32_t num_sam
vgmstream->meta_type = meta_SILENCE;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->channel_layout = channel_layout;
vgmstream->coding_type = coding_SILENCE;
vgmstream->layout_type = layout_none;
@ -28,11 +29,15 @@ fail:
return NULL;
}
VGMSTREAM* init_vgmstream_silence(int channels, int sample_rate, int32_t num_samples) {
return init_vgmstream_silence_internal(channels, sample_rate, num_samples, 0);
}
/* silent stream - for containers that have dummy streams but it's a hassle to detect/filter out */
VGMSTREAM* init_vgmstream_silence_container(int total_subsongs) {
VGMSTREAM* vgmstream = NULL;
vgmstream = init_vgmstream_silence(0, 0, 0);
vgmstream = init_vgmstream_silence_internal(0, 0, 0, 0);
if (!vgmstream) goto fail;
vgmstream->num_streams = total_subsongs;
@ -43,3 +48,14 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
VGMSTREAM* init_vgmstream_silence_base(VGMSTREAM* v) {
if (!v)
return init_vgmstream_silence_internal(0, 0, 0, 0);
return init_vgmstream_silence_internal(
v->channels,
v->sample_rate,
0, //v->num_samples ?
v->channel_layout);
}

View File

@ -218,15 +218,12 @@ static void clean_txtp(txtp_header* txtp, int fail) {
static int parse_silents(txtp_header* txtp) {
int i;
int channels = 0;
int sample_rate = 0;
int32_t num_samples = 0;
VGMSTREAM* v_base = NULL;
/* silents use same channels as close files */
for (i = 0; i < txtp->vgmstream_count; i++) {
if (!txtp->entry[i].silent) {
channels = txtp->vgmstream[i]->channels;
sample_rate = txtp->vgmstream[i]->sample_rate;
v_base = txtp->vgmstream[i];
break;
}
}
@ -236,7 +233,7 @@ static int parse_silents(txtp_header* txtp) {
if (!txtp->entry[i].silent)
continue;
txtp->vgmstream[i] = init_vgmstream_silence(channels, sample_rate, num_samples);
txtp->vgmstream[i] = init_vgmstream_silence_base(v_base);
if (!txtp->vgmstream[i]) goto fail;
apply_settings(txtp->vgmstream[i], &txtp->entry[i]);

View File

@ -1283,7 +1283,57 @@ void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_map
/* ******************************************************************* */
void mixing_setup(VGMSTREAM * vgmstream, int32_t max_sample_count) {
static int fix_layered_channel_layout(VGMSTREAM* vgmstream) {
int i;
mixing_data* data = vgmstream->mixing_data;
layered_layout_data* layout_data;
uint32_t prev_cl;
if (vgmstream->channel_layout || vgmstream->layout_type != layout_layered)
return 0;
layout_data = vgmstream->layout_data;
/* mainly layer-v (in cases of layers-within-layers should cascade) */
if (data->output_channels != layout_data->layers[0]->channels)
return 0;
/* check all layers share layout (implicitly works as a channel check, if not 0) */
prev_cl = layout_data->layers[0]->channel_layout;
if (prev_cl == 0)
return 0;
for (i = 1; i < layout_data->layer_count; i++) {
uint32_t layer_cl = layout_data->layers[i]->channel_layout;
if (prev_cl != layer_cl)
return 0;
prev_cl = layer_cl;
}
vgmstream->channel_layout = prev_cl;
return 1;
}
/* channel layout + down/upmixing = ?, salvage what we can */
static void fix_channel_layout(VGMSTREAM* vgmstream) {
mixing_data* data = vgmstream->mixing_data;
if (fix_layered_channel_layout(vgmstream))
goto done;
/* segments should share channel layout automatically */
/* a bit wonky but eh... */
if (vgmstream->channel_layout && vgmstream->channels != data->output_channels) {
vgmstream->channel_layout = 0;
}
done:
((VGMSTREAM*)vgmstream->start_vgmstream)->channel_layout = vgmstream->channel_layout;
}
void mixing_setup(VGMSTREAM* vgmstream, int32_t max_sample_count) {
mixing_data *data = vgmstream->mixing_data;
float *mixbuf_re = NULL;
@ -1300,11 +1350,7 @@ void mixing_setup(VGMSTREAM * vgmstream, int32_t max_sample_count) {
data->mixbuf = mixbuf_re;
data->mixing_on = 1;
/* a bit wonky but eh... */
if (vgmstream->channel_layout && vgmstream->channels != data->output_channels) {
vgmstream->channel_layout = 0;
((VGMSTREAM*)vgmstream->start_vgmstream)->channel_layout = 0;
}
fix_channel_layout(vgmstream);
/* since data exists on its own memory and pointer is already set
* there is no need to propagate to start_vgmstream */