Fix 5.1/7.1 .at3 LFE channel order [Devil May Cry 4 (PS3)]

This commit is contained in:
bnnm 2019-03-30 02:15:22 +01:00
parent adae35ae3a
commit 57d724c2b2
4 changed files with 55 additions and 0 deletions

View File

@ -291,6 +291,7 @@ void free_ffmpeg(ffmpeg_codec_data *data);
void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples);
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data);
void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channels_remap);
/* ffmpeg_decoder_custom_opus.c (helper-things) */
ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);

View File

@ -28,6 +28,25 @@ static void g_init_ffmpeg() {
}
}
static void remap_audio(sample_t *outbuf, int sample_count, int channels, int channel_mappings[]) {
int ch_from,ch_to,s;
sample_t temp;
for (s = 0; s < sample_count; s++) {
for (ch_from = 0; ch_from < channels; ch_from++) {
if (ch_from > 32)
continue;
ch_to = channel_mappings[ch_from];
if (ch_to < 1 || ch_to > 32 || ch_to > channels-1 || ch_from == ch_to)
continue;
temp = outbuf[s*channels + ch_from];
outbuf[s*channels + ch_from] = outbuf[s*channels + ch_to];
outbuf[s*channels + ch_to] = temp;
}
}
}
/* converts codec's samples (can be in any format, ex. Ogg's float32) to PCM16 */
static void convert_audio_pcm16(sample_t *outbuf, const uint8_t *inbuf, int fullSampleCount, int bitsPerSample, int floatingPoint) {
int s;
@ -656,6 +675,8 @@ end:
/* convert native sample format into PCM16 outbuf */
samplesReadNow = bytesRead / (bytesPerSample * channels);
convert_audio_pcm16(outbuf, data->sampleBuffer, samplesReadNow * channels, data->bitsPerSample, data->floatingPoint);
if (data->channel_remap_set)
remap_audio(outbuf, samplesReadNow, data->channels, data->channel_remap);
/* clean buffer when requested more samples than possible */
if (endOfAudio && samplesReadNow < samples_to_do) {
@ -814,4 +835,19 @@ uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data) {
return (uint32_t)data->codecCtx->channel_layout; /* uint64 but there ain't so many speaker mappings */
}
/* yet another hack to fix codecs that encode channels in different order and reorder on decoder
* but FFmpeg doesn't do it automatically
* (maybe should be done via mixing, but could clash with other stuff?) */
void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channel_remap) {
int i;
if (data->channels > 32)
return;
for (i = 0; i < data->channels; i++) {
data->channel_remap[i] = channel_remap[i];
}
data->channel_remap_set = 1;
}
#endif

View File

@ -608,6 +608,21 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
ffmpeg_set_skip_samples(ffmpeg_data, fact_sample_skip);
}
/* LFE channel should be reordered on decode, but FFmpeg doesn't do it automatically:
* - 6ch: FL FR FC BL BR LFE > FL FR FC LFE BL BR
* - 8ch: FL FR FC BL BR SL SR LFE > FL FR FC LFE BL BR SL SR
* (ATRAC3Plus only, 5/7ch can't be encoded) */
if (ffmpeg_data->channels == 6) {
/* LFE BR BL > LFE BL BR > same */
int channel_remap[] = { 0, 1, 2, 5, 5, 5, };
ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap);
}
else if (ffmpeg_data->channels == 8) {
/* LFE BR SL SR BL > LFE BL SL SR BR > LFE BL BR SR SL > LFE BL BR SL SR > same */
int channel_remap[] = { 0, 1, 2, 7, 7, 7, 7, 7};
ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap);
}
/* RIFF loop/sample values are absolute (with skip samples), adjust */
if (loop_flag) {
loop_start_smpl -= (int32_t)ffmpeg_data->skipSamples;

View File

@ -1205,6 +1205,9 @@ typedef struct {
int64_t skipSamples; // number of start samples that will be skipped (encoder delay), for looping adjustments
int streamCount; // number of FFmpeg audio streams
int channel_remap_set;
int channel_remap[32]; /* map of channel > new position */
/*** internal state ***/
// Intermediate byte buffer
uint8_t *sampleBuffer;