Improve RIFF ATRAC3/plus decoding accuracy

This commit is contained in:
bnnm 2019-08-25 20:46:29 +02:00
parent 59ff127548
commit 22c3266727
15 changed files with 202 additions and 122 deletions

View File

@ -297,6 +297,11 @@ uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data * data);
void ffmpeg_set_channel_remapping(ffmpeg_codec_data * data, int *channels_remap);
/* ffmpeg_decoder_utils.c (helper-things) */
ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples);
/* ffmpeg_decoder_custom_opus.c (helper-things) */
typedef struct {
int channels;
int skip;
@ -307,7 +312,6 @@ typedef struct {
int channel_mapping[8];
} opus_config;
/* ffmpeg_decoder_custom_opus.c (helper-things) */
ffmpeg_codec_data * init_ffmpeg_switch_opus_config(STREAMFILE *streamFile, off_t start_offset, size_t data_size, opus_config* cfg);
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);
@ -319,7 +323,6 @@ size_t switch_opus_get_samples(off_t offset, size_t stream_size, STREAMFILE *str
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
@ -367,8 +370,6 @@ void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stre
void xma_fix_raw_samples_hb(VGMSTREAM *vgmstream, STREAMFILE *headerFile, STREAMFILE *bodyFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples);
void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, int channel_per_stream, int fix_num_samples, int fix_loop_samples);
int riff_get_fact_skip_samples(STREAMFILE * streamFile, off_t start_offset);
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
size_t ac3_bytes_to_samples(size_t bytes, int full_block_align, int channels);

View File

@ -988,24 +988,6 @@ void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * out
if(out_loop_flag) *out_loop_flag = loop_flag;
}
/* manually read from "fact" chunk */
int riff_get_fact_skip_samples(STREAMFILE * streamFile, off_t start_offset) {
off_t chunk_offset;
size_t chunk_size, fact_skip_samples = 0;
if (!find_chunk_le(streamFile, 0x66616374, start_offset + 0x0c, 0, &chunk_offset, &chunk_size)) /* find "fact" */
goto fail;
if (chunk_size == 0x8) {
fact_skip_samples = read_32bitLE(chunk_offset + 0x4, streamFile);
}
else if (chunk_size == 0xc) {
fact_skip_samples = read_32bitLE(chunk_offset + 0x8, streamFile);
}
return fact_skip_samples;
fail:
return 0; /* meh */
}
/* ******************************************** */
/* OTHER STUFF */
/* ******************************************** */

View File

@ -52,6 +52,14 @@ static void remap_audio(sample_t *outbuf, int sample_count, int channels, int ch
}
}
static void invert_audio(sample_t *outbuf, int sample_count, int channels) {
int i;
for (i = 0; i < sample_count*channels; i++) {
outbuf[i] = -outbuf[i];
}
}
/* 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;
@ -728,6 +736,8 @@ end:
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);
if (data->invert_audio_set)
invert_audio(outbuf, samplesReadNow, data->channels);
/* clean buffer when requested more samples than possible */
if (endOfAudio && samplesReadNow < samples_to_do) {

View File

@ -0,0 +1,118 @@
#include "coding.h"
#ifdef VGM_USE_FFMPEG
/* init ATRAC3/plus while adding some fixes */
ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples) {
ffmpeg_codec_data *ffmpeg_data = NULL;
int is_at3 = 0, is_at3p = 0, codec;
size_t riff_size;
int fact_samples, skip_samples, implicit_skip;
off_t fact_offset = 0;
size_t fact_size = 0;
/* some simplified checks just in case */
if (read_32bitBE(offset + 0x00,sf) != 0x52494646) /* "RIFF" */
goto fail;
riff_size = read_32bitLE(offset + 0x04,sf) + 0x08;
codec = (uint16_t)read_16bitLE(offset + 0x14, sf);
switch(codec) {
case 0x0270: is_at3 = 1; break;
case 0xFFFE: is_at3p = 1; break;
default: goto fail;
}
/* init file + apply fixes to FFmpeg decoding (with these fixes should be
* sample-accurate vs official tools, except usual +-1 float-to-pcm conversion) */
ffmpeg_data = init_ffmpeg_offset(sf, offset, riff_size);
if (!ffmpeg_data) goto fail;
/* well behaved .at3 define "fact" but official tools accept files without it */
if (find_chunk_le(sf,0x66616374,offset + 0x0c,0, &fact_offset, &fact_size)) { /* "fact" */
if (fact_size == 0x08) { /* early AT3 (mainly PSP games) */
fact_samples = read_32bitLE(fact_offset + 0x00, sf);
skip_samples = read_32bitLE(fact_offset + 0x04, sf); /* base skip samples */
}
else if (fact_size == 0x0c) { /* late AT3 (mainly PS3 games and few PSP games) */
fact_samples = read_32bitLE(fact_offset + 0x00, sf);
/* 0x04: base skip samples, ignored by decoder */
skip_samples = read_32bitLE(fact_offset + 0x08, sf); /* skip samples with implicit skip of 184 added */
}
else {
VGM_LOG("ATRAC3: unknown fact size\n");
goto fail;
}
}
else {
fact_samples = 0; /* tools output 0 samples in this case unless loop end is defined */
if (is_at3)
skip_samples = 1024; /* 1 frame */
else if (is_at3p)
skip_samples = 2048; /* 1 frame */
else
skip_samples = 0;
}
/* implicit skip: official tools skip this even with encoder delay forced to 0. Maybe FFmpeg decodes late,
* but when forcing tools to decode all frame samples it always ends a bit before last frame, so maybe it's
* really an internal skip, since encoder adds extra frames so fact num_samples + encoder delay + implicit skip
* never goes past file. Same for all bitrate/channels, not added to loops. */
if (is_at3) {
implicit_skip = 69;
}
else if (is_at3p && fact_size == 0x08) {
implicit_skip = 184*2;
}
else if (is_at3p && fact_size == 0x0c) {
implicit_skip = 184; /* first 184 is already added to delay vs field at 0x08 */
}
else if (is_at3p) {
implicit_skip = 184; /* default for unknown sizes */
}
else {
implicit_skip = 0;
}
/* FFmpeg reads this but just in case they fiddle with it in the future */
ffmpeg_data->totalSamples = fact_samples;
/* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame)
* FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples + implicit_skip);
/* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */
if (is_at3) {
ffmpeg_data->invert_audio_set = 1;
}
/* multichannel fix: LFE channel should be reordered on decode (ATRAC3Plus only, only 1/2/6/8ch exist):
* - 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 */
if (is_at3p && 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 (is_at3p && 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);
}
if (out_samples)
*out_samples = fact_samples;
return ffmpeg_data;
fail:
return NULL;
}
#endif

View File

@ -1919,7 +1919,7 @@
>
</File>
<File
RelativePath=".\coding\ffmpeg_decoder_utils_ea_schl.c"
RelativePath=".\coding\ffmpeg_decoder_utils.c"
>
</File>
<File

View File

@ -144,6 +144,7 @@
<ClCompile Include="coding\circus_decoder.c" />
<ClCompile Include="coding\coding_utils.c" />
<ClCompile Include="coding\ffmpeg_decoder.c" />
<ClCompile Include="coding\ffmpeg_decoder_utils.c" />
<ClCompile Include="coding\ffmpeg_decoder_custom_opus.c" />
<ClCompile Include="coding\lsf_decoder.c" />
<ClCompile Include="coding\mp4_aac_decoder.c" />

View File

@ -1558,6 +1558,9 @@
<ClCompile Include="coding\ffmpeg_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\ffmpeg_decoder_utils.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\ffmpeg_decoder_custom_opus.c">
<Filter>coding\Source Files</Filter>
</ClCompile>

View File

@ -1169,8 +1169,6 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
#ifdef VGM_USE_FFMPEG
case EA_CODEC2_ATRAC3PLUS: {
ffmpeg_codec_data *ffmpeg_data;
/* regular ATRAC3plus chunked in SCxx blocks, including RIFF header [Medal of Honor Heroes 2 (PSP)] */
if (!is_bnk) {
STREAMFILE* temp_streamFile = NULL;
@ -1181,22 +1179,17 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
start_offset = 0x00; /* must point to the custom streamfile's beginning */
ea->stream_size = get_streamfile_size(temp_streamFile);
ffmpeg_data = init_ffmpeg_offset(temp_streamFile, start_offset, get_streamfile_size(temp_streamFile));
vgmstream->codec_data = init_ffmpeg_atrac3_riff(temp_streamFile, start_offset, NULL);
close_streamfile(temp_streamFile);
if (!ffmpeg_data) goto fail;
}
else {
size_t riff_size = read_32bitLE(start_offset + 0x04, streamFile) + 0x08;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, riff_size);
if (!ffmpeg_data) goto fail;
/* memory file without blocks */
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, NULL);
}
vgmstream->codec_data = ffmpeg_data;
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (ffmpeg_data->skipSamples <= 0) /* in case FFmpeg didn't get them */
ffmpeg_set_skip_samples(ffmpeg_data, riff_get_fact_skip_samples(streamFile, start_offset));
break;
}
#endif

View File

@ -94,6 +94,7 @@ typedef struct {
int interleave;
int is_at3;
int is_at3p;
int is_at9;
} riff_fmt_chunk;
@ -242,11 +243,11 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
bztmp = (bztmp >> 8) | (bztmp << 8);
fmt->coding_type = coding_AT3plus;
fmt->block_size = (bztmp & 0x3FF) * 8 + 8; /* should match fmt->block_size */
fmt->is_at3 = 1;
fmt->is_at3p = 1;
break;
#elif defined(VGM_USE_FFMPEG)
fmt->coding_type = coding_FFmpeg;
fmt->is_at3 = 1;
fmt->is_at3p = 1;
break;
#else
goto fail;
@ -442,13 +443,22 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
case 0x66616374: /* "fact" */
if (chunk_size == 0x04) { /* standard, usually found with ADPCM */
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
} else if (chunk_size == 0x10 && read_32bitBE(current_chunk+0x08+0x04, streamFile) == 0x4C794E20) { /* "LyN " */
}
else if (chunk_size == 0x10 && read_32bitBE(current_chunk+0x08+0x04, streamFile) == 0x4C794E20) { /* "LyN " */
goto fail; /* parsed elsewhere */
} else if ((fmt.is_at3 || fmt.is_at9) && chunk_size == 0x08) {
}
else if ((fmt.is_at3 || fmt.is_at3p) && chunk_size == 0x08) { /* early AT3 (mainly PSP games) */
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
fact_sample_skip = read_32bitLE(current_chunk+0x0c, streamFile);
} else if ((fmt.is_at3 || fmt.is_at9) && chunk_size == 0x0c) {
fact_sample_skip = read_32bitLE(current_chunk+0x0c, streamFile); /* base skip samples */
}
else if ((fmt.is_at3 || fmt.is_at3p) && chunk_size == 0x0c) { /* late AT3 (mainly PS3 games and few PSP games) */
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
/* 0x0c: base skip samples, ignored by decoder */
fact_sample_skip = read_32bitLE(current_chunk+0x10, streamFile); /* skip samples with extra 184 */
}
else if (fmt.is_at9 && chunk_size == 0x0c) {
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
/* 0x0c: base skip samples (same as next field) */
fact_sample_skip = read_32bitLE(current_chunk+0x10, streamFile);
}
break;
@ -600,40 +610,22 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg: {
ffmpeg_codec_data *ffmpeg_data = init_ffmpeg_offset(streamFile, 0x00, streamFile->get_size(streamFile));
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
if (!fmt.is_at3 && !fmt.is_at3p) goto fail;
vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact_sample_count */
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, 0x00, NULL);
if (!vgmstream->codec_data) goto fail;
if (fmt.is_at3) {
/* the encoder introduces some garbage (not always silent) samples to skip before the stream */
/* manually set skip_samples if FFmpeg didn't do it */
if (ffmpeg_data->skipSamples <= 0) {
ffmpeg_set_skip_samples(ffmpeg_data, fact_sample_skip);
}
vgmstream->num_samples = fact_sample_count;
if (loop_flag) {
/* adjust RIFF loop/sample absolute values (with skip samples) */
loop_start_smpl -= fact_sample_skip;
loop_end_smpl -= 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;
loop_end_smpl -= (int32_t)ffmpeg_data->skipSamples;
}
/* happens with official tools when "fact" is not found */
if (vgmstream->num_samples == 0)
vgmstream->num_samples = loop_end_smpl;
}
break;
}
#endif
@ -753,7 +745,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_MSADPCM_int;
/* only works with half-interleave as frame_size and interleave are merged ATM*/
/* only works with half-interleave as frame_size and interleave are merged ATM */
for (ch = 0; ch < vgmstream->channels; ch++) {
vgmstream->ch[ch].channel_start_offset =
vgmstream->ch[ch].offset = start_offset + half_interleave*ch;

View File

@ -158,19 +158,14 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *streamFile) {
}
case 0x4154332B: { /* "AT3+" [Crash of the Titans (PSP)] */
ffmpeg_codec_data *ffmpeg_data = NULL;
int fact_samples = 0;
/* full RIFF header at start_offset */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,data_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, &fact_samples);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (ffmpeg_data->skipSamples <= 0) /* in case FFmpeg didn't get them */
ffmpeg_set_skip_samples(ffmpeg_data, riff_get_fact_skip_samples(streamFile, start_offset));
vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact samples */
vgmstream->num_samples = fact_samples;
break;
}

View File

@ -125,18 +125,13 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case 0x04: { /* ATRAC3plus [Kurohyo 1/2 (PSP), BraveStory (PSP)] */
ffmpeg_codec_data *ffmpeg_data;
/* internally has a RIFF header; but the SGXD header / sample rate has priority over it (may not match) */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, stream_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (ffmpeg_data->skipSamples <= 0) /* in case FFmpeg didn't get them */
ffmpeg_set_skip_samples(ffmpeg_data, riff_get_fact_skip_samples(streamFile, start_offset));
/* SGXD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */
/* SGXD's sample rate has priority over RIFF's sample rate (may not match) */
/* loop/sample values are relative (without skip) vs RIFF (with skip), matching "smpl" otherwise */
break;
}
#endif

View File

@ -300,7 +300,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end+1;
vgmstream->loop_end_sample = loop_end + 1;
}
for (i = 1; i < channel_count; i++) {
@ -349,29 +349,24 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->num_samples = ffmpeg_data->totalSamples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->loop_end_sample = loop_end; //todo +1?
xma_fix_raw_samples(vgmstream, streamFile, start_offset,stream_size, 0, 0,0); /* samples are ok, loops? */
break;
}
case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */
ffmpeg_codec_data *ffmpeg_data = NULL;
int fact_samples = 0;
/* full RIFF header at start_offset/extradata_offset (same) */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, &fact_samples);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact samples */
vgmstream->num_samples = fact_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
if (ffmpeg_data->skipSamples <= 0) /* in case FFmpeg didn't get them */
ffmpeg_set_skip_samples(ffmpeg_data, riff_get_fact_skip_samples(streamFile, start_offset));
/* SCD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */
vgmstream->loop_end_sample = loop_end + 1;
/* loop/sample values are relative (without skip) vs RIFF (with skip), matching "smpl" otherwise */
break;
}
#endif
@ -391,8 +386,12 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */
vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile);
vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) + 1;
if (loop_flag) {
vgmstream->loop_start_sample -= cfg.encoder_delay;
vgmstream->loop_end_sample -= cfg.encoder_delay;
}
break;
}
#endif

View File

@ -376,16 +376,10 @@ static VGMSTREAM * init_vgmstream_ubi_bao_base(ubi_bao_header * bao, STREAMFILE
}
case FMT_AT3: {
ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, bao->stream_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamData, start_offset, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (ffmpeg_data->skipSamples <= 0) /* in case FFmpeg didn't get them */
ffmpeg_set_skip_samples(ffmpeg_data, riff_get_fact_skip_samples(streamData, start_offset));
break;
}

View File

@ -566,22 +566,17 @@ static VGMSTREAM * init_vgmstream_ubi_sb_base(ubi_sb_header *sb, STREAMFILE *str
#ifdef VGM_USE_FFMPEG
case FMT_AT3: {
ffmpeg_codec_data *ffmpeg_data;
/* skip weird value (3, 4) in Brothers in Arms: D-Day (PSP) */
/* skip weird value (3 or 4) in Brothers in Arms: D-Day (PSP) */
if (read_32bitBE(start_offset+0x04,streamData) == 0x52494646) {
VGM_LOG("UBI SB: skipping unknown value 0x%x before RIFF\n", read_32bitBE(start_offset+0x00,streamData));
start_offset += 0x04;
sb->stream_size -= 0x04;
}
ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb->stream_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamData, start_offset, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (ffmpeg_data->skipSamples <= 0) /* in case FFmpeg didn't get them */
ffmpeg_set_skip_samples(ffmpeg_data, riff_get_fact_skip_samples(streamData, start_offset));
break;
}

View File

@ -1193,11 +1193,13 @@ 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
/*** internal state ***/
// config
int channel_remap_set;
int channel_remap[32]; /* map of channel > new position */
int invert_audio_set;
/*** internal state ***/
// Intermediate byte buffer
// intermediate byte buffer
uint8_t *sampleBuffer;
// max samples we can held (can be less or more than frameSize)
size_t sampleBufferBlock;