diff --git a/src/formats.c b/src/formats.c index 2b3f7ee5..dd95321a 100644 --- a/src/formats.c +++ b/src/formats.c @@ -924,7 +924,7 @@ static const meta_info meta_info_list[] = { {meta_GTD, "GTD/GHS header"}, {meta_TA_AAC_X360, "tri-Ace AAC (X360) header"}, {meta_TA_AAC_PS3, "tri-Ace AAC (PS3) header"}, - {meta_TA_AAC_VORBIS, "tri-Ace AAC (Mobile Vorbis) header"}, + {meta_TA_AAC_MOBILE, "tri-Ace AAC (Mobile) header"}, {meta_PS3_MTA2, "Konami MTA2 header"}, {meta_NGC_ULW, "Criterion ULW raw header"}, {meta_PC_XA30, "Reflections XA30 PC header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index c6af2edd..74021c9d 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -646,6 +646,7 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps3_mta2(STREAMFILE *streamFile); diff --git a/src/meta/ta_aac.c b/src/meta/ta_aac.c index 0c30a87e..c6ce49f0 100644 --- a/src/meta/ta_aac.c +++ b/src/meta/ta_aac.c @@ -210,7 +210,7 @@ fail: } /* Android/iOS Variants (Star Ocean Anamnesis (APK v1.9.2), Heaven x Inferno (iOS)) */ -VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile) { #ifdef VGM_USE_VORBIS off_t start_offset; int8_t codec_id; @@ -232,7 +232,7 @@ VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) { ogg_vorbis_meta_info_t ovmi = {0}; VGMSTREAM * result = NULL; - ovmi.meta_type = meta_TA_AAC_VORBIS; + ovmi.meta_type = meta_TA_AAC_MOBILE; ovmi.loop_start = read_32bitLE(0x140, streamFile); ovmi.loop_end = read_32bitLE(0x144, streamFile); ovmi.loop_flag = ovmi.loop_end > ovmi.loop_start; @@ -251,3 +251,65 @@ fail: #endif return NULL; } + +/* Android/iOS Variants, before they switched to Vorbis (Star Ocean Anamnesis (Android), Heaven x Inferno (iOS)) */ +VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int channel_count, loop_flag, codec; + size_t data_size; + + + /* check extension, case insensitive */ + /* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */ + if (!check_extensions(streamFile, "aac,laac,ace")) + goto fail; + + if (read_32bitLE(0x00, streamFile) != 0x41414320) /* "AAC " */ + goto fail; + + if (read_32bitLE(0xf0, streamFile) != 0x57415645) /* "WAVE" */ + goto fail; + + codec = read_8bit(0x104, streamFile); + channel_count = read_8bit(0x105, streamFile); + /* 0x106: 0x01?, 0x107: 0x10? */ + data_size = read_32bitLE(0x10c, streamFile); /* usable data only, cuts last frame */ + start_offset = read_32bitLE(0x120, streamFile); + /* 0x124: full data size */ + loop_flag = (read_32bitLE(0x134, streamFile) > 0); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(0x108, streamFile); + vgmstream->meta_type = meta_TA_AAC_MOBILE; + + switch(codec) { + case 0x0d: + if (read_32bitLE(0x144, streamFile) != 0x40) goto fail; /* frame size */ + if (read_32bitLE(0x148, streamFile) != (0x40-0x04*channel_count)*2 / channel_count) goto fail; /* frame samples */ + if (channel_count > 2) goto fail; /* unknown data layout */ + + vgmstream->coding_type = coding_YAMAHA; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = yamaha_bytes_to_samples(data_size, channel_count); + vgmstream->loop_start_sample = yamaha_bytes_to_samples(read_32bitLE(0x130, streamFile), channel_count);; + vgmstream->loop_end_sample = yamaha_bytes_to_samples(read_32bitLE(0x134, streamFile), channel_count);; + break; + + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 68f70c26..86a5d776 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -350,6 +350,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ta_aac_x360, init_vgmstream_ta_aac_ps3, init_vgmstream_ta_aac_mobile, + init_vgmstream_ta_aac_mobile_vorbis, init_vgmstream_ps3_mta2, init_vgmstream_ngc_ulw, init_vgmstream_pc_xa30, diff --git a/src/vgmstream.h b/src/vgmstream.h index 8594c508..f063b1af 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -618,7 +618,7 @@ typedef enum { meta_GTD, /* Knights Contract (X360/PS3), Valhalla Knights 3 (PSV) */ meta_TA_AAC_X360, /* tri-Ace AAC (Star Ocean 4, End of Eternity, Infinite Undiscovery) */ meta_TA_AAC_PS3, /* tri-Ace AAC (Star Ocean International, Resonance of Fate) */ - meta_TA_AAC_VORBIS, /* tri-Ace AAC (Star Ocean Anamnesis, Heaven x Inferno) */ + meta_TA_AAC_MOBILE, /* tri-Ace AAC (Star Ocean Anamnesis, Heaven x Inferno) */ meta_PS3_MTA2, /* Metal Gear Solid 4 MTA2 */ meta_NGC_ULW, /* Burnout 1 (GC only) */ meta_PC_XA30, /* Driver - Parallel Lines (PC) */