mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
Fix 5.1/7.1 .at3 LFE channel order [Devil May Cry 4 (PS3)]
This commit is contained in:
parent
adae35ae3a
commit
57d724c2b2
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user