From d7c5c3feaf85c8cb72c117d38f44f6e64e18c7c5 Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 27 Sep 2018 23:31:03 +0200 Subject: [PATCH] Improve UE4Opus/EAOpus encoder delay calculations --- src/coding/coding.h | 7 +++-- src/coding/ffmpeg_decoder_custom_opus.c | 36 ++++++++++++++++++++++--- src/meta/ea_eaac.c | 3 ++- src/meta/ue4opus.c | 12 +++------ 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/coding/coding.h b/src/coding/coding.h index 75d88d70..8afd4385 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -279,9 +279,12 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples); ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate); ffmpeg_codec_data * init_ffmpeg_ue4_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate); ffmpeg_codec_data * init_ffmpeg_ea_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate); -size_t ffmpeg_make_opus_header(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate); + size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile); -size_t ue4_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile); + +size_t switch_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile); +size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile); +size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile); #endif diff --git a/src/coding/ffmpeg_decoder_custom_opus.c b/src/coding/ffmpeg_decoder_custom_opus.c index a94507f8..a2adb18f 100644 --- a/src/coding/ffmpeg_decoder_custom_opus.c +++ b/src/coding/ffmpeg_decoder_custom_opus.c @@ -511,8 +511,38 @@ static size_t custom_opus_get_samples(off_t offset, size_t data_size, int sample size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile) { return custom_opus_get_samples(offset, data_size, sample_rate, streamFile, OPUS_SWITCH); } -size_t ue4_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile) { - return custom_opus_get_samples(offset, data_size, sample_rate, streamFile, OPUS_UE4); + + +static size_t custom_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile, opus_type_t type) { + uint8_t buf[4]; + size_t skip_size; + + switch(type) { + case OPUS_SWITCH: + skip_size = 0x08; + break; + case OPUS_UE4: + skip_size = 0x02; + break; + case OPUS_EA: + skip_size = 0x02; + break; + default: + return 0; + } + + /* encoder delay seems fixed to 1/8 of samples per frame, but may need more testing */ + read_streamfile(buf, offset+skip_size, 0x04, streamFile); /* at least 0x02 */ + return opus_get_packet_samples(buf, 0x04) / 8; +} +size_t switch_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) { + return custom_opus_get_encoder_delay(offset, streamFile, OPUS_SWITCH); +} +size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) { + return custom_opus_get_encoder_delay(offset, streamFile, OPUS_UE4); +} +size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) { + return custom_opus_get_encoder_delay(offset, streamFile, OPUS_EA); } @@ -541,11 +571,9 @@ fail: ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) { return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_SWITCH); } - ffmpeg_codec_data * init_ffmpeg_ue4_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) { return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_UE4); } - ffmpeg_codec_data * init_ffmpeg_ea_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate) { return init_ffmpeg_custom_opus(streamFile, start_offset, data_size, channels, skip, sample_rate, OPUS_EA); } diff --git a/src/meta/ea_eaac.c b/src/meta/ea_eaac.c index 7940718c..d00ab1a6 100644 --- a/src/meta/ea_eaac.c +++ b/src/meta/ea_eaac.c @@ -666,7 +666,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST #ifdef VGM_USE_FFMPEG case EAAC_CODEC_EAOPUS: { /* EAOpus (unknown FourCC) [FIFA 17 (PC), FIFA 19 (Switch)]*/ - int skip = 0;//todo + int skip = 0; size_t data_size; /* We'll remove EA blocks and pass raw data to FFmpeg Opus decoder */ @@ -674,6 +674,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST temp_streamFile = setup_eaac_streamfile(streamData, eaac.version, eaac.codec, eaac.streamed,0,0, eaac.stream_offset); if (!temp_streamFile) goto fail; + skip = ea_opus_get_encoder_delay(0x00, temp_streamFile); data_size = get_streamfile_size(temp_streamFile); vgmstream->codec_data = init_ffmpeg_ea_opus(temp_streamFile, 0x00,data_size, vgmstream->channels, skip, vgmstream->sample_rate); diff --git a/src/meta/ue4opus.c b/src/meta/ue4opus.c index 6e13f5a7..516dac08 100644 --- a/src/meta/ue4opus.c +++ b/src/meta/ue4opus.c @@ -26,14 +26,12 @@ VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) { /* 0x0f(2): frame count */ loop_flag = 0; - /* UE4Opus encodes 60ms (music) or 120ms (voice) frames, and encoder delay seems 1/8 - * of samples per frame (may be more complex but wave looks ok-ish) */ - //todo does UE4 actually care about encoder delay? - skip = (60 * 48000 / 1000) / 8; /* 48000 is the internal/resampled rate */ - start_offset = 0x11; data_size = get_streamfile_size(streamFile) - start_offset; + /* usually uses 60ms for music (delay of 360 samples) */ + skip = ue4_opus_get_encoder_delay(start_offset, streamFile); + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count, loop_flag); @@ -49,10 +47,6 @@ VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) { if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - - if (vgmstream->num_samples == 0) { - vgmstream->num_samples = ue4_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile) - skip; - } } #else goto fail;