diff --git a/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj index bf528f3fc..e3b3ad16e 100644 --- a/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj @@ -129,7 +129,6 @@ 836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */; }; 836F6F5318BDC2190095E648 /* ps2_iab_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */; }; 836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */; }; - 836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */; }; 836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1918BDC2180095E648 /* scd_int_layout.c */; }; 836F6F5718BDC2190095E648 /* str_snds_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1A18BDC2180095E648 /* str_snds_blocked.c */; }; 836F6F5818BDC2190095E648 /* thp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1B18BDC2180095E648 /* thp_blocked.c */; }; @@ -234,7 +233,6 @@ 836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9018BDC2180095E648 /* ps2_adsc.c */; }; 836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9118BDC2180095E648 /* ps2_ass.c */; }; 836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9218BDC2180095E648 /* ps2_ast.c */; }; - 836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9318BDC2180095E648 /* ps2_aus.c */; }; 836F6FD018BDC2190095E648 /* ps2_b1s.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9418BDC2180095E648 /* ps2_b1s.c */; }; 836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9518BDC2180095E648 /* ps2_bg00.c */; }; 836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9618BDC2180095E648 /* ps2_bmdx.c */; }; @@ -304,7 +302,6 @@ 836F701918BDC2190095E648 /* psx_cdxa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDD18BDC2190095E648 /* psx_cdxa.c */; }; 836F701A18BDC2190095E648 /* psx_fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDE18BDC2190095E648 /* psx_fag.c */; }; 836F701B18BDC2190095E648 /* psx_gms.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDF18BDC2190095E648 /* psx_gms.c */; }; - 836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE018BDC2190095E648 /* psx_str_mgav.c */; }; 836F701D18BDC2190095E648 /* raw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE118BDC2190095E648 /* raw.c */; }; 836F701E18BDC2190095E648 /* redspark.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE218BDC2190095E648 /* redspark.c */; }; 836F701F18BDC2190095E648 /* riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE318BDC2190095E648 /* riff.c */; }; @@ -439,6 +436,9 @@ 83E56BA51F2EE3520026BC60 /* vorbis_custom_utils_ogl.c in Sources */ = {isa = PBXBuildFile; fileRef = 83E56BA01F2EE3500026BC60 /* vorbis_custom_utils_ogl.c */; }; 83EDE5D81A70951A005F5D84 /* mca.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EDE5D61A70951A005F5D84 /* mca.c */; }; 83EDE5D91A70951A005F5D84 /* btsnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EDE5D71A70951A005F5D84 /* btsnd.c */; }; + 83EED5D3203A8BC7008BEB45 /* ea_swvr.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D1203A8BC7008BEB45 /* ea_swvr.c */; }; + 83EED5D4203A8BC7008BEB45 /* aus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D2203A8BC7008BEB45 /* aus.c */; }; + 83EED5D6203A8BD7008BEB45 /* blocked_ea_swvr.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */; }; 83F4129C1E93313C002E37D0 /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83F4128F1E932F9A002E37D0 /* Vorbis.framework */; }; 83F5F8831908D0A400C8E65F /* fsb5.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F5F8821908D0A400C8E65F /* fsb5.c */; }; 83FF0EBC1E93282100C58054 /* wwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FF0EBB1E93282100C58054 /* wwise.c */; }; @@ -691,7 +691,6 @@ 836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adm_blocked.c; sourceTree = ""; }; 836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_iab_blocked.c; sourceTree = ""; }; 836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_strlr_blocked.c; sourceTree = ""; }; - 836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_mgav_blocked.c; sourceTree = ""; }; 836F6E1918BDC2180095E648 /* scd_int_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_int_layout.c; sourceTree = ""; }; 836F6E1A18BDC2180095E648 /* str_snds_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds_blocked.c; sourceTree = ""; }; 836F6E1B18BDC2180095E648 /* thp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp_blocked.c; sourceTree = ""; }; @@ -796,7 +795,6 @@ 836F6E9018BDC2180095E648 /* ps2_adsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adsc.c; sourceTree = ""; }; 836F6E9118BDC2180095E648 /* ps2_ass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ass.c; sourceTree = ""; }; 836F6E9218BDC2180095E648 /* ps2_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ast.c; sourceTree = ""; }; - 836F6E9318BDC2180095E648 /* ps2_aus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_aus.c; sourceTree = ""; }; 836F6E9418BDC2180095E648 /* ps2_b1s.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_b1s.c; sourceTree = ""; }; 836F6E9518BDC2180095E648 /* ps2_bg00.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bg00.c; sourceTree = ""; }; 836F6E9618BDC2180095E648 /* ps2_bmdx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bmdx.c; sourceTree = ""; }; @@ -866,7 +864,6 @@ 836F6EDD18BDC2190095E648 /* psx_cdxa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_cdxa.c; sourceTree = ""; }; 836F6EDE18BDC2190095E648 /* psx_fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_fag.c; sourceTree = ""; }; 836F6EDF18BDC2190095E648 /* psx_gms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_gms.c; sourceTree = ""; }; - 836F6EE018BDC2190095E648 /* psx_str_mgav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_str_mgav.c; sourceTree = ""; }; 836F6EE118BDC2190095E648 /* raw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw.c; sourceTree = ""; }; 836F6EE218BDC2190095E648 /* redspark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = redspark.c; sourceTree = ""; }; 836F6EE318BDC2190095E648 /* riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = riff.c; sourceTree = ""; }; @@ -997,6 +994,9 @@ 83E56BA01F2EE3500026BC60 /* vorbis_custom_utils_ogl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_ogl.c; sourceTree = ""; }; 83EDE5D61A70951A005F5D84 /* mca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mca.c; sourceTree = ""; }; 83EDE5D71A70951A005F5D84 /* btsnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = btsnd.c; sourceTree = ""; }; + 83EED5D1203A8BC7008BEB45 /* ea_swvr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_swvr.c; sourceTree = ""; }; + 83EED5D2203A8BC7008BEB45 /* aus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aus.c; sourceTree = ""; }; + 83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_swvr.c; sourceTree = ""; }; 83F412871E932F9A002E37D0 /* Vorbis.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Vorbis.xcodeproj; path = ../Vorbis/macosx/Vorbis.xcodeproj; sourceTree = ""; }; 83F5F8821908D0A400C8E65F /* fsb5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fsb5.c; sourceTree = ""; }; 83FF0EBB1E93282100C58054 /* wwise.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wwise.c; sourceTree = ""; }; @@ -1224,6 +1224,7 @@ 8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */, 8349A8E41FE6253800E26435 /* blocked_ea_schl.c */, 8349A8E71FE6253900E26435 /* blocked_ea_sns.c */, + 83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */, 8349A8E51FE6253800E26435 /* blocked_ivaud.c */, 8349A8E61FE6253900E26435 /* blocked_vawx.c */, 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */, @@ -1244,7 +1245,6 @@ 836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */, 836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */, 836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */, - 836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */, 831BD1201EEE1D2A00198540 /* rws_blocked.c */, 836F6E1918BDC2180095E648 /* scd_int_layout.c */, 836F6E1A18BDC2180095E648 /* str_snds_blocked.c */, @@ -1280,6 +1280,7 @@ 836F6E3518BDC2180095E648 /* ast.c */, 83A21F80201D8980000F04B9 /* atsl3.c */, 83A21F7C201D897F000F04B9 /* atx.c */, + 83EED5D2203A8BC7008BEB45 /* aus.c */, 83AA5D201F6E2F9B0020821C /* awc.c */, 836F6E3618BDC2180095E648 /* baf.c */, 8349A8F81FE6257E00E26435 /* bar_streamfile.h */, @@ -1308,6 +1309,7 @@ 8349A8F71FE6257E00E26435 /* ea_eaac.c */, 830165981F256BD000CA0941 /* ea_schl_fixed.c */, 836F6E4618BDC2180095E648 /* ea_schl.c */, + 83EED5D1203A8BC7008BEB45 /* ea_swvr.c */, 836F6E4818BDC2180095E648 /* emff.c */, 836F6E4918BDC2180095E648 /* exakt_sc.c */, 836F6E4A18BDC2180095E648 /* excitebots.c */, @@ -1406,7 +1408,6 @@ 836F6E9018BDC2180095E648 /* ps2_adsc.c */, 836F6E9118BDC2180095E648 /* ps2_ass.c */, 836F6E9218BDC2180095E648 /* ps2_ast.c */, - 836F6E9318BDC2180095E648 /* ps2_aus.c */, 836F6E9418BDC2180095E648 /* ps2_b1s.c */, 836F6E9518BDC2180095E648 /* ps2_bg00.c */, 836F6E9618BDC2180095E648 /* ps2_bmdx.c */, @@ -1481,7 +1482,6 @@ 836F6EDD18BDC2190095E648 /* psx_cdxa.c */, 836F6EDE18BDC2190095E648 /* psx_fag.c */, 836F6EDF18BDC2190095E648 /* psx_gms.c */, - 836F6EE018BDC2190095E648 /* psx_str_mgav.c */, 836F6EE118BDC2190095E648 /* raw.c */, 836F6EE218BDC2190095E648 /* redspark.c */, 836F6EE318BDC2190095E648 /* riff.c */, @@ -1802,6 +1802,7 @@ 8349A8DF1FE6251F00E26435 /* vorbis_custom_utils_vid1.c in Sources */, 83A21F8D201D8982000F04B9 /* sqex_sead.c in Sources */, 839B54571EEE1DA000048A2D /* rws_blocked.c in Sources */, + 83EED5D3203A8BC7008BEB45 /* ea_swvr.c in Sources */, 839B54521EEE1D9600048A2D /* ngc_ulw.c in Sources */, 836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */, 836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */, @@ -1915,7 +1916,9 @@ 836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */, 8349A8ED1FE6253900E26435 /* blocked_ea_sns.c in Sources */, 836F6F6F18BDC2190095E648 /* akb.c in Sources */, + 83EED5D6203A8BD7008BEB45 /* blocked_ea_swvr.c in Sources */, 8349A9181FE6258200E26435 /* ea_1snh.c in Sources */, + 83EED5D4203A8BC7008BEB45 /* aus.c in Sources */, 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */, 83709E071ECBC1A4005C03D3 /* mss.c in Sources */, 836F6F8F18BDC2190095E648 /* his.c in Sources */, @@ -1969,9 +1972,7 @@ 836F705218BDC2190095E648 /* zwdsp.c in Sources */, 836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */, 836F6FFF18BDC2190095E648 /* ps2_strlr.c in Sources */, - 836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */, 836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */, - 836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */, 8349A8EC1FE6253900E26435 /* blocked_vawx.c in Sources */, 836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */, 836F700418BDC2190095E648 /* ps2_vas.c in Sources */, @@ -2123,7 +2124,6 @@ 836F6FEA18BDC2190095E648 /* ps2_msa.c in Sources */, 836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */, 836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */, - 836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */, 83345A4F1F8AEB2800B2EAA4 /* nub_xma.c in Sources */, 836F6F7618BDC2190095E648 /* brstm.c in Sources */, 836F700718BDC2190095E648 /* ps2_vgv.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index dbca81d47..d3a350f8d 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -32,8 +32,9 @@ void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); -size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels); size_t ima_bytes_to_samples(size_t bytes, int channels); +size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels); +size_t xbox_ima_bytes_to_samples(size_t bytes, int channels); size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset); /* ngc_dsp_decoder */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c index 0e3652626..df24db802 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c @@ -403,7 +403,7 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header, for (i = 0; i < data->formatCtx->nb_streams; ++i) { stream = data->formatCtx->streams[i]; - if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (stream->codecpar && stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { streamCount++; /* select Nth audio stream if specified, or first one */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_switch_opus.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_switch_opus.c index 5bc1835e1..c44fd0afd 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_switch_opus.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_switch_opus.c @@ -169,7 +169,7 @@ size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, uint8_t buf[4]; size_t block_size = read_32bitBE(offset, streamFile); - read_streamfile(buf, offset+4, 4, streamFile); + read_streamfile(buf, offset+8, 4, streamFile); num_samples += get_opus_samples_per_frame(buf, sample_rate); offset += 0x08 + block_size; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c index 6cc343e7b..bdb09b4e8 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c @@ -272,46 +272,126 @@ void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * } /* ************************************ */ -/* MS IMA */ +/* MS-IMA */ /* ************************************ */ -/* IMA with frames with header and custom sizes */ -void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { - int i, sample_count; +/* IMA with variable-sized frames, header and custom nibble layout (outputs non-aligned number of samples). + * Officially defined in "Microsoft Multimedia Standards Update" doc (RIFFNEW.pdf). */ +void decode_ms_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i, samples_read = 0, samples_done = 0, max_samples; - int32_t hist1 = stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; + int32_t hist1;// = stream->adpcm_history1_32; + int step_index;// = stream->adpcm_step_index; - //internal interleave (configurable size), mixed channels (4 byte per ch) - int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels; + /* internal interleave (configurable size), mixed channels (4 byte per ch) */ + int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1; first_sample = first_sample % block_samples; - //normal header (per channel) - if (first_sample == 0) { - off_t header_offset = stream->offset + 4*channel; + /* normal header (hist+step+reserved per channel) */ + { + off_t header_offset = stream->offset + 0x04*channel; - hist1 = read_16bitLE(header_offset,stream->streamfile); - step_index = read_8bit(header_offset+2,stream->streamfile); - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; + hist1 = read_16bitLE(header_offset+0x00,stream->streamfile); + step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */ + if (step_index < 0) step_index = 0; + if (step_index > 88) step_index = 88; + + /* write header sample */ + if (samples_read >= first_sample && samples_done < samples_to_do) { + outbuf[samples_done * channelspacing] = (short)hist1; + samples_done++; + } + samples_read++; } - for (i=first_sample,sample_count=0; ioffset + 4*channel + 4*vgmstream->channels + i/8*4*vgmstream->channels + (i%8)/2; - int nibble_shift = (i&1?4:0); //low nibble first + max_samples = (block_samples - samples_read); + if (max_samples > samples_to_do + first_sample - samples_done) + max_samples = samples_to_do + first_sample - samples_done; /* for smaller last block */ + + /* decode nibbles (layout: alternates 4*2 nibbles per channel) */ + for (i = 0; i < max_samples; i++) { + off_t byte_offset = stream->offset + 0x04*vgmstream->channels + 0x04*channel + 0x04*vgmstream->channels*(i/8) + (i%8)/2; + int nibble_shift = (i&1?4:0); /* low nibble first */ std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); + + if (samples_read >= first_sample && samples_done < samples_to_do) { + outbuf[samples_done * channelspacing] = (short)(hist1); + samples_done++; + } + samples_read++; } - //internal interleave: increment offset on complete frame - if (i == block_samples) stream->offset += vgmstream->interleave_block_size; + /* internal interleave: increment offset on complete frame */ + if (first_sample + samples_done == block_samples) { + stream->offset += vgmstream->interleave_block_size; + } - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_index; + //stream->adpcm_history1_32 = hist1; + //stream->adpcm_step_index = step_index; } -/* MS IMA with fixed frame size and custom multichannel nibble layout. +/* Reflection's MS-IMA (some layout info from XA2WAV by Deniz Oezmen) */ +void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i, samples_read = 0, samples_done = 0, max_samples; + + int32_t hist1;// = stream->adpcm_history1_32; + int step_index;// = stream->adpcm_step_index; + + /* internal interleave (configurable size), mixed channels (4 byte per ch) */ + int block_channel_size = (vgmstream->interleave_block_size - 0x04*vgmstream->channels) / vgmstream->channels; + int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1; + first_sample = first_sample % block_samples; + + /* normal header (hist+step+reserved per channel) */ + { + off_t header_offset = stream->offset + 0x04*channel; + + hist1 = read_16bitLE(header_offset+0x00,stream->streamfile); + step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */ + if (step_index < 0) step_index = 0; + if (step_index > 88) step_index = 88; + + /* write header sample */ + if (samples_read >= first_sample && samples_done < samples_to_do) { + outbuf[samples_done * channelspacing] = (short)hist1; + samples_done++; + } + samples_read++; + } + + max_samples = (block_samples - samples_read); + if (max_samples > samples_to_do + first_sample - samples_done) + max_samples = samples_to_do + first_sample - samples_done; /* for smaller last block */ + + /* decode nibbles (layout: all nibbles from one channel, then other channels) */ + for (i = 0; i < max_samples; i++) { + off_t byte_offset = stream->offset + 0x04*vgmstream->channels + block_channel_size*channel + i/2; + int nibble_shift = (i&1?4:0); /* low nibble first */ + + std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + + if (samples_read >= first_sample && samples_done < samples_to_do) { + outbuf[samples_done * channelspacing] = (short)(hist1); + samples_done++; + } + samples_read++; + } + + /* internal interleave: increment offset on complete frame */ + if (first_sample + samples_done == block_samples) { + stream->offset += vgmstream->interleave_block_size; + } + + //stream->adpcm_history1_32 = hist1; + //stream->adpcm_step_index = step_index; +} + +/* ************************************ */ +/* XBOX-IMA */ +/* ************************************ */ + +/* MS-IMA with fixed frame size, skips last sample per channel (for aligment) and custom multichannel nibble layout. * For multichannel the layout is (I think) mixed stereo channels (ex. 6ch: 2ch + 2ch + 2ch) */ void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { int i, sample_count; @@ -351,19 +431,19 @@ void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * o } //internal interleave: increment offset on complete frame - if (channelspacing==1) { - if(offset-stream->offset==32+3) // ?? - stream->offset+=36; + if (channelspacing==1) { /* mono */ + if (offset-stream->offset == 32+3) // ?? + stream->offset += 0x24; } else { - if(offset-stream->offset==64+(4*(channel%2))+3) // ?? - stream->offset+=36*channelspacing; + if (offset-stream->offset == 64+(4*(channel%2))+3) // ?? + stream->offset += 0x24*channelspacing; } stream->adpcm_history1_32 = hist1; stream->adpcm_step_index = step_index; } -/* mono XBOX ADPCM for interleave */ +/* mono XBOX-IMA ADPCM for interleave */ void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { int i, sample_count = 0, num_frame; int32_t hist1 = stream->adpcm_history1_32; @@ -565,6 +645,7 @@ void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelsp stream->adpcm_step_index = step_index; } +/* XBOX-IMA with modified data layout */ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { int i, sample_count; @@ -572,7 +653,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o int step_index = stream->adpcm_step_index; //internal interleave - int block_samples = (36 - 4) * 2; /* block size - header, 2 samples per byte */ + int block_samples = (0x24 - 4) * 2; /* block size - header, 2 samples per byte */ first_sample = first_sample % block_samples; //interleaved header (all hist per channel + all step_index per channel) @@ -601,7 +682,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o stream->adpcm_step_index = step_index; } - +/* XBOX-IMA with modified data layout */ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { int i, sample_count = 0; @@ -638,7 +719,6 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); outbuf[sample_count] = (short)(hist1); sample_count+=channelspacing; - //todo atenuation: apparently from hcs's analysis Wwise IMA decodes nibbles slightly different, reducing dbs } } @@ -648,45 +728,23 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * stream->adpcm_history1_32 = hist1; stream->adpcm_step_index = step_index; } +//todo atenuation: apparently from hcs's analysis Wwise IMA expands nibbles slightly different, reducing clipping/dbs +/* +From Wwise_v2015.1.6_Build5553_SDK.Linux +<_ZN13CAkADPCMCodec12DecodeSampleEiii>: + 10: 83 e0 07 and $0x7,%eax ; sample + 13: 01 c0 add %eax,%eax ; sample*2 + 15: 83 c0 01 add $0x1,%eax ; sample*2+1 + 18: 0f af 45 e4 imul -0x1c(%rbp),%eax ; (sample*2+1)*scale + 1c: 8d 50 07 lea 0x7(%rax),%edx ; result+7 + 1f: 85 c0 test %eax,%eax ; result negative? + 21: 0f 48 c2 cmovs %edx,%eax ; adjust if negative to fix rounding for below division + 24: c1 f8 03 sar $0x3,%eax ; (sample*2+1)*scale/8 -/* Reflection's MS-IMA (some layout info from XA2WAV) */ -void decode_ref_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { - int i, sample_count; - - int32_t hist1 = stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - //internal interleave (configurable size), mixed channels (4 byte per ch) - int block_channel_size = (vgmstream->interleave_block_size - 4*vgmstream->channels) / vgmstream->channels; - int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels; - first_sample = first_sample % block_samples; - - //normal header (per channel) - if (first_sample == 0) { - off_t header_offset = stream->offset + 4*channel; - - hist1 = read_16bitLE(header_offset,stream->streamfile); - step_index = read_8bit(header_offset+2,stream->streamfile); - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - //layout: all nibbles from one channel, then all nibbles from other - for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + block_channel_size*channel + i/2; - int nibble_shift = (i&1?4:0); //low nibble first - - std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); - } - - //internal interleave: increment offset on complete frame - if (i == block_samples) stream->offset += vgmstream->interleave_block_size; - - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_index; -} +Different rounding model vs IMA's shift-and-add (also "adjust" step may be unnecessary). +*/ +/* MS-IMA with possibly the XBOX-IMA model of even number of samples per block (more tests are needed) */ void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { int i, sample_count; @@ -785,17 +843,24 @@ void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci } -size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) { - /* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */ - return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels - + ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0); -} - size_t ima_bytes_to_samples(size_t bytes, int channels) { /* 2 samples per byte (2 nibbles) in stereo or mono config */ return bytes * 2 / channels; } +size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) { + /* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */ + return (bytes / block_align) * ((block_align - 0x04*channels) * 2 / channels + 1) + + ((bytes % block_align) ? (((bytes % block_align) - 0x04*channels) * 2 / channels + 1) : 0); +} + +size_t xbox_ima_bytes_to_samples(size_t bytes, int channels) { + int block_align = 0x24 * channels; + /* XBOX IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */ + return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels + + ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0); //todo probably not possible (aligned) +} + size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset) { int version, big_endian, header_samples; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c index c50f6d85e..c8d827f18 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c @@ -530,8 +530,8 @@ static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* VGM_LOG("MPEG EAL3: written 0x%lx but expected less than 0x%x at 0x%lx\n", os->b_off/8, expected_frame_size, os->info_offset); } else { - /* fill ancillary data (ignored) */ - memset(os->buf + os->b_off/8, 0x77, expected_frame_size - os->b_off/8); + /* fill ancillary data (should be ignored, but 0x00 seems to improve mpg123's free bitrate detection) */ + memset(os->buf + os->b_off/8, 0x00, expected_frame_size - os->b_off/8); } os->b_off = expected_frame_size*8; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c index 04a9add09..e3b7ef0a8 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c @@ -21,10 +21,6 @@ static const int ADPCMCoeffs[7][2] = { 392, -232 } }; -long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) { - return bytes/block_size*((block_size-(7-1)*channels)*2/channels); -} - void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) { VGMSTREAMCHANNEL *ch1,*ch2; int i; @@ -161,3 +157,8 @@ void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_s } } } + +long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) { + return (bytes / block_size) * (block_size - (7-1)*channels) * 2 / channels + + ((bytes % block_size) ? ((bytes % block_size) - (7-1)*channels) * 2 / channels : 0); +} diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 08b683cf0..445b64e3c 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -470,8 +470,8 @@ static const coding_info coding_info_list[] = { {coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (mono/interleave)"}, {coding_3DS_IMA, "3DS IMA 4-bit ADPCM"}, {coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"}, - {coding_XBOX, "XBOX 4-bit IMA ADPCM"}, - {coding_XBOX_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"}, + {coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"}, + {coding_XBOX_IMA_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"}, {coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"}, {coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"}, {coding_RAD_IMA, "Radical 4-bit IMA ADPCM"}, @@ -564,7 +564,7 @@ static const layout_info layout_info_list[] = { {layout_gsb_blocked, "GSB blocked"}, {layout_thp_blocked, "THP Movie Audio blocked"}, {layout_filp_blocked, "FILp blocked"}, - {layout_psx_mgav_blocked, "MGAV blocked"}, + {layout_blocked_ea_swvr, "blocked (EA SWVR)"}, {layout_ps2_adm_blocked, "ADM blocked"}, {layout_dsp_bdsp_blocked, "DSP blocked"}, {layout_blocked_ivaud, "blocked (IVAUD)"}, @@ -641,7 +641,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_STR, "assumed STR + STH File by .str & .sth extension"}, {meta_PS2_ILD, "ILD header"}, {meta_PS2_PNB, "assumed PNB (PsychoNauts Bgm File) by .pnb extension"}, - {meta_XBOX_WAVM, "assumed Xbox WAVM file by .wavm extension"}, + {meta_XBOX_WAVM, "Xbox WAVM raw header"}, {meta_XBOX_RIFF, "Microsoft XWAV RIFF header"}, {meta_DSP_STR, "assumed Conan Gamecube STR File by .str extension"}, {meta_EA_SCHL, "Electronic Arts SCHl header (variable)"}, @@ -717,7 +717,7 @@ static const meta_info meta_info_list[] = { {meta_DC_STR, "Sega Stream Asset Builder header"}, {meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"}, {meta_XBOX_XMU, "XMU header"}, - {meta_XBOX_XVAS, "assumed TMNT file by .xvas extension"}, + {meta_XBOX_XVAS, "Konami .XVAS header"}, {meta_PS2_XA2, "Acclaim XA2 Header"}, {meta_DC_IDVI, "Capcom IDVI header"}, {meta_KRAW, "Geometry Wars: Galaxies KRAW header"}, @@ -838,7 +838,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_ADSC, "ADSC Header"}, {meta_NGC_DSP_MPDS, "MPDS DSP header"}, {meta_DSP_STR_IG, "Infogrames dual dsp header"}, - {meta_PSX_MGAV, "Electronic Arts RVWS header"}, + {meta_EA_SWVR, "Electronic Arts SWVR header"}, {meta_PS2_B1S, "B1S header"}, {meta_PS2_WAD, "WAD header"}, {meta_DSP_XIII, "XIII dsp header"}, @@ -955,6 +955,7 @@ static const meta_info meta_info_list[] = { {meta_XWC, "Starbreeze XWC header"}, {meta_SQEX_SAB, "Square-Enix SAB header"}, {meta_SQEX_MAB, "Square-Enix MAB header"}, + {meta_OGG_L2SD, "Ogg Vorbis (L2SD)"}, #ifdef VGM_USE_MP4V2 {meta_MP4, "AAC header"}, diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c index b8bd1c60e..b6b1530f4 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c @@ -128,8 +128,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * case layout_blocked_ivaud: block_update_ivaud(vgmstream->next_block_offset,vgmstream); break; - case layout_psx_mgav_blocked: - psx_mgav_block_update(vgmstream->next_block_offset,vgmstream); + case layout_blocked_ea_swvr: + block_update_ea_swvr(vgmstream->next_block_offset,vgmstream); break; case layout_ps2_adm_blocked: ps2_adm_block_update(vgmstream->next_block_offset,vgmstream); diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c index e71844d0e..eea96ffd5 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c @@ -149,7 +149,6 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) { for (i = 0; i < vgmstream->channels; i++) { off_t channel_start = read_32bit(block_offset + 0x0C + (0x04*i),streamFile); vgmstream->ch[i].offset = block_offset + 0x0C + (0x04*vgmstream->channels) + channel_start; - VGM_LOG("ch=%x, off=%lx\n", i, vgmstream->ch[i].offset); } /* read ADPCM history before each channel if needed (not actually read in sx.exe) */ diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c index 12afab007..dda45807d 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c @@ -7,6 +7,8 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) { STREAMFILE* streamFile = vgmstream->ch[0].streamfile; uint32_t block_size, block_samples; size_t file_size = get_streamfile_size(streamFile); + off_t channel_start; + size_t channel_interleave; int i; /* always BE */ @@ -26,9 +28,26 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) { * - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */ block_size &= 0x00FFFFFF; + switch(vgmstream->coding_type) { + case coding_NGC_DSP: + /* 0x04: unknown (0x00/02), 0x08: some size?, 0x34: null? */ + channel_start = read_32bitBE(block_offset+0x08+0x00,streamFile); + channel_interleave = read_32bitBE(block_offset+0x08+0x0c,streamFile); + /* guessed as all known EA DSP only have one block with subheader (maybe changes coefs every block?) */ + if (channel_start >= 0x40) { + dsp_read_coefs_be(vgmstream,streamFile, block_offset+0x08+0x10,0x28); + dsp_read_hist_be (vgmstream,streamFile, block_offset+0x08+0x30,0x28);//todo guessed and doesn't fix clicks in full loops + } + break; + + default: + channel_start = 0x00; + channel_interleave = 0x00; + break; + } + for (i = 0; i < vgmstream->channels; i++) { - off_t channel_start = 0x00; - vgmstream->ch[i].offset = block_offset + 0x08 + channel_start; + vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i*channel_interleave; /* also fix first offset (for EALayer3) */ if (block_offset == vgmstream->ch[i].channel_start_offset) { diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_swvr.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_swvr.c new file mode 100644 index 000000000..d4206b5c5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_swvr.c @@ -0,0 +1,18 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream) { + STREAMFILE* streamFile = vgmstream->ch[0].streamfile; + int i; + int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bit(vgmstream->current_block_offset+0x04,streamFile)-0x1C; + vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i); + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/layout.h b/Frameworks/vgmstream/vgmstream/src/layout/layout.h index 41a40c4a9..466281eff 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/layout.h +++ b/Frameworks/vgmstream/vgmstream/src/layout/layout.h @@ -46,7 +46,7 @@ void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream); void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream); -void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream); void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream); diff --git a/Frameworks/vgmstream/vgmstream/src/layout/psx_mgav_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/psx_mgav_blocked.c deleted file mode 100644 index e2a3d21a6..000000000 --- a/Frameworks/vgmstream/vgmstream/src/layout/psx_mgav_blocked.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* set up for the block at the given offset */ -void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset+0x04,vgmstream->ch[0].streamfile)-0x1C; - vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C; - vgmstream->current_block_size/=vgmstream->channels; - - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i); - - } -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ads.c b/Frameworks/vgmstream/vgmstream/src/meta/ads.c index f3a8c091a..692531ec0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ads.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ads.c @@ -6,38 +6,33 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; - int loop_flag; - int channel_count; - int identifer_byte; + int loop_flag, channel_count, codec; + /* check extension, case insensitive */ if (!check_extensions(streamFile,"ads")) goto fail; - /* check dhSS Header */ - if (read_32bitBE(0x00,streamFile) != 0x64685353) + if (read_32bitBE(0x00,streamFile) != 0x64685353) /* "dhSS" */ goto fail; - - /* check dbSS Header */ - if (read_32bitBE(0x20,streamFile) != 0x64625353) + if (read_32bitBE(0x20,streamFile) != 0x64625353) /* "dbSS" */ goto fail; loop_flag = 1; channel_count = read_32bitBE(0x10,streamFile); - if (channel_count > 0x2) + if (channel_count > 2) goto fail; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - identifer_byte = read_32bitBE(0x08,streamFile); - switch (identifer_byte) { + vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); + + codec = read_32bitBE(0x08,streamFile); + switch (codec) { case 0x00000020: /* GC */ start_offset = 0x28 + 0x60 * channel_count; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); vgmstream->coding_type = coding_NGC_DSP; vgmstream->num_samples = read_32bitBE(0x28,streamFile); if (loop_flag) { @@ -45,9 +40,9 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) { vgmstream->loop_end_sample = vgmstream->num_samples; } - if (channel_count == 1){ + if (channel_count == 1) { vgmstream->layout_type = layout_none; - } else if (channel_count == 2){ + } else if (channel_count == 2) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile); } @@ -57,10 +52,8 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) { case 0x00000021: /* Xbox */ start_offset = 0x28; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); - vgmstream->coding_type = coding_XBOX_int; - vgmstream->num_samples = (read_32bitBE(0x24,streamFile) / 36 *64 / vgmstream->channels)-64; // to avoid the "pop" at the loop point + vgmstream->coding_type = coding_XBOX_IMA_int; + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitBE(0x24,streamFile), vgmstream->channels); vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave; vgmstream->interleave_block_size = 0x24; if (loop_flag) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/atx.c b/Frameworks/vgmstream/vgmstream/src/meta/atx.c index a58a88337..e540baa36 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/atx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/atx.c @@ -42,7 +42,7 @@ static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) { size_t filename_len; int i, num_segments = 0; size_t riff_size; -VGM_LOG("1\n"); + if (read_16bitLE(0x1c,streamFile) != 0) goto fail; /* this must be first segment */ if (read_16bitLE(0x1e,streamFile) < 1 || read_16bitLE(0x1e,streamFile) > ATX_MAX_SEGMENTS) goto fail; @@ -57,7 +57,7 @@ VGM_LOG("1\n"); for (i = 0; i < num_segments; i++) { off_t subfile_offset; size_t subfile_size; -VGM_LOG("loop\n"); + filename[filename_len - 5] = ('0'+i+1); /* ghetto digit conversion */ new_streamFile = open_stream_name(streamFile, filename); if (!new_streamFile) goto fail; @@ -69,7 +69,7 @@ VGM_LOG("loop\n"); /* parse block/segment header (other Media.Vision's files use it too) */ subfile_offset = read_32bitLE(0x08,segment_streamFiles[i]); /* header size */ subfile_size = read_32bitLE(0x14,segment_streamFiles[i]); /* can be 0 in other containers */ -VGM_LOG("subfile: %lx, %x\n", subfile_offset, subfile_size); + if (read_16bitLE(0x1c,segment_streamFiles[i]) != i) goto fail; /* segment sequence */ /* 0x04: block size (should match subfile_size in .ATX) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_aus.c b/Frameworks/vgmstream/vgmstream/src/meta/aus.c similarity index 97% rename from Frameworks/vgmstream/vgmstream/src/meta/ps2_aus.c rename to Frameworks/vgmstream/vgmstream/src/meta/aus.c index 24bb3883f..26a571634 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_aus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aus.c @@ -31,7 +31,7 @@ VGMSTREAM * init_vgmstream_aus(STREAMFILE *streamFile) { vgmstream->num_samples = read_32bitLE(0x08,streamFile); if(read_16bitLE(0x06,streamFile)==0x02) { - vgmstream->coding_type = coding_XBOX; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type=layout_none; } else { vgmstream->coding_type = coding_PSX; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/awc.c b/Frameworks/vgmstream/vgmstream/src/meta/awc.c index a102d1b47..ab73b6cdd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/awc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/awc.c @@ -37,9 +37,6 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) { if (!parse_awc_header(streamFile, &awc)) goto fail; - if (awc.is_encrypted) - goto fail; - /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(awc.channel_count, 0); @@ -156,6 +153,10 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) { if (flags & 0x00080000) /* encrypted data chunk (most of GTA5 PC) */ awc->is_encrypted = 1; + if (awc->is_encrypted) { + VGM_LOG("AWC: encrypted data found\n"); + goto fail; + } /* Music when the first id is 0 (base/fake entry with info for all channels), sfx pack otherwise. * sfx = N single streams, music = N-1 interleaved mono channels (even for MP3/XMA). @@ -267,7 +268,7 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) { /* If music, data is divided into blocks of block_chunk size with padding. * Each block has a header/seek table and interleaved data for all channels */ if (awc->is_music && read_32bit(awc->stream_offset, streamFile) != 0) { - VGM_LOG("AWC: music found, but block doesn't start with seek table\n"); + VGM_LOG("AWC: music found, but block doesn't start with seek table at %lx\n", awc->stream_offset); goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c index 534350afe..d693e5b1a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -15,10 +15,15 @@ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile) { if (!check_extensions(streamFile,"snr")) goto fail; - /* SNR headers normally need an external SNS file, but some have data */ + /* SNR headers normally need an external SNS file, but some have data [Burnout Paradise, NFL2013 (iOS)] */ if (get_streamfile_size(streamFile) > 0x10) { - /* SNR with data (flag 0x40 not set), seen in Burnout Paradise, NFL2013 iOS */ - off_t start_offset = (read_32bitBE(0x08, streamFile) == 0) ? 0x0c : 0x08; + off_t start_offset; + + switch(read_8bit(0x04,streamFile)) { /* flags */ + case 0x60: start_offset = 0x10; break; + case 0x20: start_offset = 0x0c; break; + default: start_offset = 0x08; break; + } vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x00, start_offset, meta_EA_SNR_SNS); if (!vgmstream) goto fail; @@ -31,11 +36,11 @@ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile) { if (!vgmstream) goto fail; } - if (streamData) close_streamfile(streamData); + close_streamfile(streamData); return vgmstream; fail: - if (streamData) close_streamfile(streamData); + close_streamfile(streamData); return NULL; } @@ -119,7 +124,8 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST sample_rate = (uint16_t)read_16bitBE(header_offset + 0x02,streamHead); flags = (uint8_t)read_8bit(header_offset + 0x04,streamHead); /* upper nibble only? */ num_samples = (uint32_t)read_32bitBE(header_offset + 0x04,streamHead) & 0x00FFFFFF; - /* optional, in some headers: 0x08: null? 0x0c: varies (ex. null, full size) */ + /* rest is optional, depends on flags header used (ex. SNU and SPS may have bigger headers): + * &0x20: 1 int (usually 0x00), &0x00/40: nothing, &0x60: 2 ints (usually 0x00 and 0x14) */ /* V0: SNR+SNS, V1: SPR+SPS (not apparent differences) */ if (version != 0 && version != 1) { @@ -166,14 +172,14 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST /* EA decoder list and known internal FourCCs */ switch(codec) { - case 0x02: /* "P6B0": PCM16BE (NBA Jam Wii) */ + case 0x02: /* "P6B0": PCM16BE [NBA Jam (Wii)] */ vgmstream->coding_type = coding_PCM16_int; vgmstream->codec_endian = 1; vgmstream->layout_type = layout_blocked_ea_sns; break; #ifdef VGM_USE_FFMPEG - case 0x03: { /* "EXm0": EA-XMA (Dante's Inferno X360) */ + case 0x03: { /* "EXm0": EA-XMA [Dante's Inferno (X360)] */ uint8_t buf[0x100]; int bytes, block_size, block_count; size_t stream_size, virtual_size; @@ -200,15 +206,15 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST } #endif - case 0x04: /* "Xas1": EA-XAS (Dead Space PC/PS3) */ + case 0x04: /* "Xas1": EA-XAS [Dead Space (PC/PS3)] */ vgmstream->coding_type = coding_EA_XAS; vgmstream->layout_type = layout_blocked_ea_sns; break; #ifdef VGM_USE_MPEG - case 0x05: /* "EL31": EALayer3 v1 (Need for Speed: Hot Pursuit PS3) */ - case 0x06: /* "L32P": EALayer3 v2 "PCM" (Battlefield 1943 PS3) */ - case 0x07: { /* "L32S": EALayer3 v2 "Spike" (Dante's Inferno PS3) */ + case 0x05: /* "EL31": EALayer3 v1 [Need for Speed: Hot Pursuit (PS3)] */ + case 0x06: /* "L32P": EALayer3 v2 "PCM" [Battlefield 1943 (PS3)] */ + case 0x07: { /* "L32S": EALayer3 v2 "Spike" [Dante's Inferno (PS3)] */ mpeg_custom_config cfg = {0}; off_t mpeg_start_offset = start_offset + 0x08; mpeg_custom_t type = (codec == 0x05 ? MPEG_EAL31b : (codec == 0x06) ? MPEG_EAL32P : MPEG_EAL32S); @@ -222,7 +228,13 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST } #endif -#if 0 //todo unknown variation + case 0x08: /* "Gca0"?: DSP [Need for Speed: Nitro sfx (Wii)] */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_blocked_ea_sns; + /* DSP coefs are read in the blocks */ + break; + +#if 0 //todo buffered ATRAC9 #ifdef VGM_USE_ATRAC9 case 0x0a: { /* EATrax */ atrac9_config cfg = {0}; @@ -241,8 +253,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST #endif case 0x00: /* "NONE" (internal 'codec not set' flag) */ - case 0x01: /* not used/reserved? Gca0/MP30/P6L0/P2B0/P2L0/P8S0/P8U0/PFN0? */ - case 0x08: /* ? */ + case 0x01: /* not used/reserved? /MP30/P6L0/P2B0/P2L0/P8S0/P8U0/PFN0? */ case 0x09: /* EASpeex (libspeex variant, base versions vary: 1.0.5, 1.2beta3) */ case 0x0b: /* ? */ case 0x0c: /* EAOpus (inside each SNS/SPS block is 16b frame size + standard? Opus packet) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index e8cfa8a9a..c6986f66d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -292,7 +292,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ break; case EA_CODEC2_XBOXADPCM: /* XBOX IMA (interleaved mono) */ - vgmstream->coding_type = coding_XBOX_int; + vgmstream->coding_type = coding_XBOX_IMA_int; break; case EA_CODEC2_GCADPCM: /* DSP */ @@ -342,7 +342,6 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ case EA_CODEC2_MT10: /* MicroTalk (10:1 compression) */ case EA_CODEC2_MT5: /* MicroTalk (5:1 compression) */ vgmstream->coding_type = coding_EA_MT; - VGM_LOG("mt: codec=%x, cv=%x, v=%x\n", ea->codec2, ea->codec_version, ea->version); vgmstream->codec_data = init_ea_mt(vgmstream->channels, ea->version == EA_VERSION_V3); if (!vgmstream->codec_data) goto fail; break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_swvr.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_swvr.c new file mode 100644 index 000000000..8c9969470 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_swvr.c @@ -0,0 +1,80 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + + +/* SWVR - from EA games [Future Cop L.A.P.D. (PS/PC), Freekstyle (PS2/GC), EA Sports Supercross (PS)] */ +VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag = 0, channel_count; + int big_endian; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + + + /* check extension */ + if (!check_extensions(streamFile,"str")) + goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) == 0x53575652) { /* "SWVR" (GC) */ + big_endian = 1; + read_32bit = read_32bitBE; + } + else if (read_32bitBE(0x00,streamFile) == 0x52565753) { /* "RVWS" (PS/PS2) */ + big_endian = 0; + read_32bit = read_32bitLE; + } + else { + goto fail; + } + + + start_offset = read_32bit(0x04,streamFile); + loop_flag = 1; + channel_count = 2; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = 16000; + vgmstream->codec_endian = big_endian; + + vgmstream->meta_type = meta_EA_SWVR; + vgmstream->layout_type = layout_blocked_ea_swvr; + + vgmstream->coding_type = coding_PSX; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + + + /* calculate samples */ + { + off_t current_chunk = start_offset; + + vgmstream->num_samples = 0; + while ((current_chunk + start_offset) < (get_streamfile_size(streamFile))) { + uint32_t block_id = (read_32bit(current_chunk,streamFile)); + if (block_id == 0x5641474D) { /* "VAGM" */ + block_update_ea_swvr(start_offset,vgmstream); + vgmstream->num_samples += vgmstream->current_block_size/16*28; + current_chunk += vgmstream->current_block_size + 0x1C; + } + current_chunk += 0x10; + } + } + + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c index 6a6bbf53b..1e55bc7e7 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c @@ -288,7 +288,7 @@ VGMSTREAM * init_vgmstream_fsb(STREAMFILE *streamFile) { /* FSOUND_IMAADPCMSTEREO is "noninterleaved, true stereo IMA", but doesn't seem to be any different * (found in FSB4: Shatter, Blade Kitten (PC), Hard Corps: Uprising (PS3)) */ - vgmstream->coding_type = coding_XBOX; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; /* "interleaved header" IMA, only used with >2ch (ex. Blade Kitten 6ch) * or (seemingly) when flag is used (ex. Dead to Rights 2 (Xbox) 2ch in FSB3.1 */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c index 0d79502b1..99bf7d516 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c @@ -237,7 +237,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { break; case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */ - vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX; + vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX_IMA; vgmstream->layout_type = layout_none; break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/genh.c b/Frameworks/vgmstream/vgmstream/src/meta/genh.c index d0a451da8..ea67480af 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/genh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/genh.c @@ -84,7 +84,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { /* type to coding conversion */ switch (genh.codec) { case PSX: coding = coding_PSX; break; - case XBOX: coding = coding_XBOX; break; + case XBOX: coding = coding_XBOX_IMA; break; case NGC_DTK: coding = coding_NGC_DTK; break; case PCM16BE: coding = coding_PCM16BE; break; case PCM16LE: coding = coding_PCM16LE; break; @@ -194,7 +194,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { vgmstream->interleave_block_size = genh.interleave; vgmstream->layout_type = layout_none; break; - case coding_XBOX: + case coding_XBOX_IMA: vgmstream->layout_type = layout_none; break; case coding_NGC_DTK: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 8088dc7c6..89e049d6f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -490,7 +490,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mss.c b/Frameworks/vgmstream/vgmstream/src/meta/mss.c index 3f67310b8..c7a1d15e2 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mss.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mss.c @@ -18,6 +18,8 @@ VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) { loop_flag = 0; channel_count = read_16bitLE(0x16,streamFile); + if (read_32bitLE(0x18,streamFile) == 0x4800 && vgmstream->channels > 2) + channel_count = 2; //todo add support for interleave stereo streams /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); @@ -36,14 +38,12 @@ VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) { /* no other way to know */ if (vgmstream->interleave_block_size == 0x4800) { /* interleaved stereo streams (2ch 0x4800 + 2ch 0x4800 = 4ch) */ - vgmstream->coding_type = coding_XBOX; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_interleave; /* header values are somehow off? */ data_size = get_streamfile_size(streamFile); - vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, 0x24*vgmstream->channels, vgmstream->channels); - - vgmstream->channels = 2; //todo add support for interleave stereo streams + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); } else { /* 0x800 interleave */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c index 71d4b9a5e..dd9a58cd3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c @@ -232,7 +232,8 @@ VGMSTREAM * init_vgmstream_ngc_mdsp_std(STREAMFILE *streamFile) { vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave_shortblock; vgmstream->meta_type = meta_DSP_STD; vgmstream->interleave_block_size = header.block_size * 8; - vgmstream->interleave_smallblock_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8; + if (vgmstream->interleave_block_size) + vgmstream->interleave_smallblock_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8; for (i = 0; i < channel_count; i++) { if (read_dsp_header(&header, header_size * i, streamFile)) goto fail; @@ -620,7 +621,11 @@ VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) { ch0_header.loop_flag != ch1_header.loop_flag || ch0_header.loop_start_offset != ch1_header.loop_start_offset || ch0_header.loop_end_offset != ch1_header.loop_end_offset - ) goto fail; + ) { + /* Timesplitters 2 GC's ts2_atom_smasher_44_fx.mss differs slightly in samples but plays ok */ + if (meta_type != meta_DSP_MSS) + goto fail; + } if (ch0_header.loop_flag) { off_t loop_off; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c b/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c index 9b6bd83fd..7794f77b1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c @@ -9,7 +9,7 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { int loop_flag = 0, channel_count; int num_samples = 0, loop_start = 0, loop_end = 0; off_t offset = 0, data_offset; - size_t data_size; + size_t data_size, skip = 0; /* check extension, case insensitive */ if ( !check_extensions(streamFile,"opus,lopus,nop")) /* no relation to Ogg Opus */ @@ -53,6 +53,7 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { channel_count = read_8bit(offset + 0x09, streamFile); /* 0x0a: packet size if CBR, 0 if VBR */ data_offset = offset + read_32bitLE(offset + 0x10, streamFile); + skip = read_32bitLE(offset + 0x1c, streamFile); if ((uint32_t)read_32bitLE(data_offset, streamFile) != 0x80000004) goto fail; @@ -77,10 +78,9 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG { uint8_t buf[0x100]; - size_t bytes, skip; + size_t bytes; ffmpeg_custom_config cfg; - - skip = 0; //todo + ffmpeg_codec_data *ffmpeg_data; bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate); if (bytes <= 0) goto fail; @@ -88,14 +88,21 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { memset(&cfg, 0, sizeof(ffmpeg_custom_config)); cfg.type = FFMPEG_SWITCH_OPUS; - vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg); - if (!vgmstream->codec_data) goto fail; + ffmpeg_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + if (ffmpeg_data->skipSamples <= 0) { + ffmpeg_set_skip_samples(ffmpeg_data, skip); + } - if (vgmstream->num_samples == 0) - vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile); + if (vgmstream->num_samples == 0) { + vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, + vgmstream->sample_rate, streamFile) - skip; + } } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c index a0a72ff22..79704ec14 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c @@ -156,6 +156,26 @@ static void isd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo } } +static void l2sd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) { + size_t bytes_read = size*nmemb; + ogg_vorbis_streamfile * const ov_streamfile = datasource; + int i; + char *header_id = "OggS"; + + /* First "OggS" is changed */ + { + for (i = 0; i < bytes_read; i++) { + if (ov_streamfile->offset+i < 0x04) { + /* replace key in the first 4 bytes with "OggS" */ + ((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4]; + } + else { + break; + } + } + } +} + /* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { @@ -169,6 +189,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { int is_psychic = 0; int is_sngw = 0; int is_isd = 0; + int is_l2sd = 0; /* check extension */ @@ -195,6 +216,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { is_psychic = 1; inf.decryption_callback = psychic_ogg_decryption_callback; } + else if (read_32bitBE(0x00,streamFile) == 0x4C325344) { /* "L2SD" [Lineage II Chronicle 4 (PC)] */ + is_l2sd = 1; + inf.decryption_callback = l2sd_ogg_decryption_callback; + } else if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */ goto fail; /* not known (ex. Wwise) */ } @@ -251,6 +276,8 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { inf.meta_type = meta_OGG_SNGW; } else if (is_isd) { inf.meta_type = meta_OGG_ISD; + } else if (is_l2sd) { + inf.meta_type = meta_OGG_L2SD; } else { inf.meta_type = meta_OGG_VORBIS; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_str_mgav.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_str_mgav.c deleted file mode 100644 index 0951fc101..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/psx_str_mgav.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../util.h" - -/* STR (Future Cop L.A.P.D.) */ -VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - off_t current_chunk; - char filename[PATH_LIMIT]; - int loop_flag = 0; - int channel_count; - int dataBuffer = 0; - int i; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("str",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x52565753) /* "RVWS" */ - goto fail; - - loop_flag = 1; - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x4,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 16000; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_psx_mgav_blocked; - vgmstream->meta_type = meta_PSX_MGAV; - - /* open the file for reading */ - { - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - } - } - - // calculate samples - current_chunk = start_offset; - vgmstream->num_samples = 0; - while ((current_chunk + start_offset) < (get_streamfile_size(streamFile))) - { - dataBuffer = (read_32bitBE(current_chunk,streamFile)); - if (dataBuffer == 0x4D474156) /* "MGAV" */ - { - psx_mgav_block_update(start_offset,vgmstream); - vgmstream->num_samples += vgmstream->current_block_size/16*28; - current_chunk += vgmstream->current_block_size + 0x1C; - } - current_chunk += 0x10; - } - - - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 00520b3f5..04d0cc14a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -126,18 +126,18 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk fmt->coding_type = coding_MSADPCM; break; - case 0x11: /* MS IMA ADPCM */ + case 0x11: /* MS IMA ADPCM [Layton Brothers: Mystery Room (iOS/Android)] */ if (fmt->bps != 4) goto fail; fmt->coding_type = coding_MS_IMA; break; - case 0x69: /* MS IMA ADPCM (XBOX) - Rayman Raving Rabbids 2 (PC) */ + case 0x69: /* XBOX IMA ADPCM [Rayman Raving Rabbids 2 (PC) --maybe waa/wac/wam/wad?] */ if (fmt->bps != 4) goto fail; - fmt->coding_type = coding_MS_IMA; + fmt->coding_type = coding_XBOX_IMA; break; - case 0x007A: /* MS IMA ADPCM (LA Rush, Psi Ops PC) */ - /* 0x007A is apparently "Voxware SC3" but in .MED it's just MS-IMA */ + case 0x007A: /* MS IMA ADPCM [LA Rush (PC), Psi Ops (PC)] */ + /* 0x007A is apparently "Voxware SC3" but in .MED it's just MS-IMA (0x11) */ if (!check_extensions(streamFile,"med")) goto fail; @@ -228,8 +228,8 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { size_t file_size, riff_size, data_size = 0; off_t start_offset = 0; - int fact_sample_count = -1; - int fact_sample_skip = -1; + int fact_sample_count = 0; + int fact_sample_skip = 0; int loop_flag = 0; long loop_start_ms = -1; @@ -246,9 +246,10 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { int at3 = 0; /* Sony ATRAC3 / ATRAC3plus */ int at9 = 0; /* Sony ATRAC9 */ - /* check extension, case insensitive - * .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC) */ - if ( check_extensions(streamFile, "wav,lwav,da,cd,med") ) { + + /* check extension */ + /* .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC), .snd: Layton Brothers (iOS/Android) */ + if ( check_extensions(streamFile, "wav,lwav,da,cd,med,snd") ) { ; } else if ( check_extensions(streamFile, "mwv") ) { @@ -355,7 +356,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { mwv_ctrl_offset = current_chunk; break; case 0x66616374: /* fact */ - if (sns && chunk_size == 0x10) { + if (chunk_size == 0x04) { /* standard, usually found with ADPCM */ + fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile); + } else if (sns && chunk_size == 0x10) { fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile); } else if ((at3 || at9) && chunk_size == 0x08) { fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile); @@ -380,13 +383,14 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { if (!FormatChunkFound || !DataChunkFound) goto fail; + //todo improve detection using fmt sizes/values as Wwise's don't match the RIFF standard /* JUNK is an optional Wwise chunk, and Wwise hijacks the MSADPCM/MS_IMA/XBOX IMA ids (how nice). * To ensure their stuff is parsed in wwise.c we reject their JUNK, which they put almost always. * As JUNK is legal (if unusual) we only reject those codecs. * (ex. Cave PC games have PCM16LE + JUNK + smpl created by "Samplitude software") */ if (JunkFound && check_extensions(streamFile,"wav,lwav") /* for some .MED IMA */ - && (fmt.coding_type==coding_MSADPCM || fmt.coding_type==coding_MS_IMA)) + && (fmt.coding_type==coding_MSADPCM /*|| fmt.coding_type==coding_MS_IMA*/ || fmt.coding_type==coding_XBOX_IMA)) goto fail; @@ -409,9 +413,11 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { case coding_PCM16LE: vgmstream->num_samples = pcm_bytes_to_samples(data_size, fmt.channel_count, 16); break; + case coding_PCM8_U_int: vgmstream->num_samples = pcm_bytes_to_samples(data_size, vgmstream->channels, 8); break; + case coding_L5_555: if (!mwv) goto fail; vgmstream->num_samples = data_size / 0x12 / fmt.channel_count * 32; @@ -437,12 +443,22 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { } break; + case coding_MSADPCM: - vgmstream->num_samples = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); + vgmstream->num_samples = fact_sample_count ? fact_sample_count : + msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); break; + case coding_MS_IMA: - vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); + vgmstream->num_samples = fact_sample_count ? fact_sample_count : + ms_ima_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); break; + + case coding_XBOX_IMA: + vgmstream->num_samples = fact_sample_count ? fact_sample_count : + xbox_ima_bytes_to_samples(data_size, fmt.channel_count); + break; + case coding_NGC_DSP: if (!sns) goto fail; if (fact_sample_count <= 0) goto fail; @@ -531,6 +547,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { switch (fmt.coding_type) { case coding_MSADPCM: case coding_MS_IMA: + case coding_XBOX_IMA: #ifdef VGM_USE_FFMPEG case coding_FFmpeg: #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c index 34d041569..ca1beed1c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c @@ -142,74 +142,44 @@ fail: } - /* RSD2XADP */ VGMSTREAM * init_vgmstream_rsd2xadp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int loop_flag, channel_count; + size_t data_size; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("rsd",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x0,streamFile) != 0x52534432) /* RSD2 */ - goto fail; - if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */ + /* check extension */ + if (!check_extensions(streamFile,"rsd")) goto fail; + if (read_32bitBE(0x00,streamFile) != 0x52534432) /* RSD2 */ + goto fail; + if (read_32bitBE(0x04,streamFile) != 0x58414450) /* XADP */ + goto fail; + + start_offset = read_32bitLE(0x18,streamFile); /* not sure about this */ + data_size = get_streamfile_size(streamFile); loop_flag = 0; - channel_count = read_32bitLE(0x8,streamFile); + channel_count = read_32bitLE(0x08,streamFile); - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x18,streamFile); /* not sure about this */ - vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x10,streamFile); - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = loop_flag; - vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; - } + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_RSD2XADP; - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - - if (vgmstream->coding_type == coding_XBOX) { - vgmstream->layout_type=layout_none; - vgmstream->ch[i].channel_start_offset=start_offset; - } else { - vgmstream->ch[i].channel_start_offset= - start_offset+vgmstream->interleave_block_size*i; - } - vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; - - } - } - - return vgmstream; + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; fail: - /* clean up anything we may have opened */ - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } @@ -968,72 +938,44 @@ fail: return NULL; } -/* RSD6XADP */ +/* RSD6XADP - from Crash Tag Team Racing (Xbox) */ VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int loop_flag, channel_count; + size_t data_size; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("rsd",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ - goto fail; - if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */ + /* check extension */ + if (!check_extensions(streamFile,"rsd")) goto fail; + if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */ + goto fail; + + start_offset = 0x800; + data_size = get_streamfile_size(streamFile) - start_offset; loop_flag = 0; channel_count = read_32bitLE(0x8,streamFile); - - /* build the VGMSTREAM */ + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x10,streamFile); - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = loop_flag; - vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; - } + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); + + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_RSD6XADP; - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - - if (vgmstream->coding_type == coding_XBOX) { - vgmstream->layout_type=layout_none; - vgmstream->ch[i].channel_start_offset=start_offset; - } else { - vgmstream->ch[i].channel_start_offset= - start_offset+vgmstream->interleave_block_size*i; - } - vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; - - } - } - - return vgmstream; + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; fail: - /* clean up anything we may have opened */ - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rws.c b/Frameworks/vgmstream/vgmstream/src/meta/rws.c index 3594eb45f..0f4796f1d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rws.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rws.c @@ -189,13 +189,13 @@ VGMSTREAM * init_vgmstream_rws(STREAMFILE *streamFile) { vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channel_count); break; - case 0x936538EF: /* MS-IMA PC (936538EF 11B62D43 957FA71A DE44227A) */ - case 0x2BA22F63: /* MS-IMA Xbox (2BA22F63 DD118F45 AA27A5C3 46E9790E) */ + case 0x936538EF: /* XBOX-IMA PC (936538EF 11B62D43 957FA71A DE44227A) */ + case 0x2BA22F63: /* XBOX-IMA Xbox (2BA22F63 DD118F45 AA27A5C3 46E9790E) */ /* ex. Broken Sword 3 (PC), Jacked (PC/Xbox), Burnout 2 (Xbox) */ - vgmstream->coding_type = coding_XBOX; - vgmstream->interleave_block_size = 0; /* uses regular XBOX/MS-IMA interleave */ + vgmstream->coding_type = coding_XBOX_IMA; /* PC and Xbox share the same data */ + vgmstream->interleave_block_size = 0; - vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, 0x24 * channel_count, channel_count); + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channel_count); break; default: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sab.c b/Frameworks/vgmstream/vgmstream/src/meta/sab.c index 8532e4787..6ce952b1c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sab.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sab.c @@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) { vgmstream->meta_type = meta_SAB; switch(codec) { - case 0x01: + case 0x01: /* PC */ vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = is_stream ? align : 0x02; @@ -66,7 +66,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) { break; - case 0x04: + case 0x04: /* PS2 */ vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = is_stream ? align : 0x10; @@ -76,14 +76,14 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) { vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, vgmstream->channels); break; - case 0x08: - vgmstream->coding_type = is_stream ? coding_XBOX_int : coding_XBOX; + case 0x08: /* Xbox */ + vgmstream->coding_type = is_stream ? coding_XBOX_IMA_int : coding_XBOX_IMA; vgmstream->layout_type = is_stream ? layout_interleave : layout_none; vgmstream->interleave_block_size = is_stream ? align : 0x00; - vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, 0x24*vgmstream->channels, vgmstream->channels); - vgmstream->loop_start_sample = ms_ima_bytes_to_samples(loop_start, 0x24*vgmstream->channels, vgmstream->channels); - vgmstream->loop_end_sample = ms_ima_bytes_to_samples(loop_end, 0x24*vgmstream->channels, vgmstream->channels); + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, vgmstream->channels); + vgmstream->loop_start_sample = xbox_ima_bytes_to_samples(loop_start, vgmstream->channels); + vgmstream->loop_end_sample = xbox_ima_bytes_to_samples(loop_end, vgmstream->channels); break; default: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/seg.c b/Frameworks/vgmstream/vgmstream/src/meta/seg.c index 1a15ceda4..7aa3cbea5 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/seg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/seg.c @@ -1,7 +1,8 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* SEG (found in Eragon) */ + +/* SEG - found in Eragon */ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; @@ -24,7 +25,7 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) { } else if (read_32bitBE(0x04,streamFile) == 0x78627800) /* "xbx\0" */ { - coding = coding_XBOX; + coding = coding_XBOX_IMA; } else goto fail; @@ -60,9 +61,9 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) { vgmstream->interleave_block_size = 0x2000; } } - else if (coding_XBOX == coding) + else if (coding_XBOX_IMA == coding) { - vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)/36/channel_count*64; + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x0C,streamFile)-start_offset, channel_count); vgmstream->meta_type = meta_XBOX_SEG; vgmstream->layout_type = layout_none; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c index 203fbd9d5..7c524c06b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c @@ -12,12 +12,12 @@ static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb, VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - off_t start_offset, tables_offset, meta_offset, post_meta_offset; + off_t start_offset, tables_offset, meta_offset, post_meta_offset, name_offset = 0; int32_t stream_size, subheader_size, loop_start, loop_end; - int total_subsongs, target_subsong = streamFile->stream_index; int loop_flag = 0, channel_count, codec, sample_rate; - int aux_chunk_count; + int version, target_entry, aux_chunk_count; + int total_subsongs, target_subsong = streamFile->stream_index; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; @@ -33,24 +33,25 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { read_32bitBE(0x04,streamFile) != 0x53534346) /* "SSCF" */ goto fail; - if (read_32bitBE(0x08,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */ - read_32bitBE(0x08,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */ + if (read_8bit(0x0c,streamFile) == 0x01) { /* big endian flag */ //size_offset = 0x14; read_32bit = read_32bitBE; read_16bit = read_16bitBE; - } - else if (read_32bitLE(0x08,streamFile) == 2 || /* version 2/3 LE, as seen in FFXIV for PC (and others) */ - read_32bitLE(0x08,streamFile) == 3) { + } else { //size_offset = 0x10; read_32bit = read_32bitLE; read_16bit = read_16bitLE; } - else { - goto fail; - } - /* 0x0c: probably 0=LE, 1=BE */ - /* 0x0d: unknown (always 0x04) */ + /* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */ + if (read_8bit(0x0d,streamFile) != 0x04) + goto fail; + + /* v2: FFXIII demo (PS3), FFT0 test files (PC); v3: common; v4: Kingdom Hearts 2.8 (PS4) */ + version = read_32bit(0x08,streamFile); + if (version != 2 && version != 3 && version != 4) + goto fail; + tables_offset = read_16bit(0x0e,streamFile); /* usually 0x30 or 0x20 */ #if 0 @@ -74,7 +75,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { /* 0x14: always null? */ /* 0x18: table5? (unknown) start offset? */ /* 0x1c: unknown, often null */ - /* each table entry is an uint32_t offset */ + /* each table entry is an uint32_t offset; after entries there is padding */ /* if a table isn't present entries is 0 and offset points to next table */ /* find meta_offset in table3 (headers) and total subsongs */ @@ -89,14 +90,16 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { /* manually find subsongs as entries can be dummy (ex. sfx banks in FF XIV or FF Type-0) */ for (i = 0; i < headers_entries; i++) { - off_t header_offset = read_32bit(headers_offset + i*0x04,streamFile); + off_t entry_offset = read_32bit(headers_offset + i*0x04,streamFile); - if (read_32bit(header_offset+0x0c,streamFile) == -1) + if (read_32bit(entry_offset+0x0c,streamFile) == -1) continue; /* codec -1 when dummy */ total_subsongs++; - if (!meta_offset && total_subsongs == target_subsong) - meta_offset = header_offset; + if (!meta_offset && total_subsongs == target_subsong) { + meta_offset = entry_offset; + target_entry = i; + } } if (meta_offset == 0) goto fail; /* SCD can contain 0 entries too */ @@ -129,10 +132,24 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { post_meta_offset += read_32bit(post_meta_offset+0x04, streamFile); } + /* find name if possible */ + if (version == 4) { + int info_entries = read_16bit(tables_offset+0x00,streamFile); + int headers_entries = read_16bit(tables_offset+0x04,streamFile); + off_t info_offset = tables_offset+0x20; + + /* not very exact as table1 and table3 entries may differ in V3, not sure about V4 */ + if (info_entries == headers_entries) { + off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,streamFile); + name_offset = entry_offset+0x30; + } + } + #ifdef VGM_USE_VORBIS /* special case using init_vgmstream_ogg_vorbis */ if (codec == 0x06) { + VGMSTREAM *ogg_vgmstream; uint8_t ogg_version, ogg_byte; vgm_vorbis_info_t inf = {0}; @@ -176,7 +193,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } /* actual Ogg init */ - return init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + if (ogg_vgmstream && name_offset) + read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile); + return ogg_vgmstream; } #endif @@ -189,6 +209,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->num_streams = total_subsongs; vgmstream->stream_size = stream_size; vgmstream->meta_type = meta_SQEX_SCD; + if (name_offset) + read_string(vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile); switch (codec) { case 0x01: /* PCM */ @@ -319,7 +341,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } #ifdef VGM_USE_FFMPEG - case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx] */ + case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */ ffmpeg_codec_data *ffmpeg_data = NULL; uint8_t buf[200]; int32_t bytes; @@ -373,6 +395,27 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } #endif +#ifdef VGM_USE_ATRAC9 + case 0x16: { /* ATRAC9 [Kingdom Hearts 2.8 (PS4)] */ + atrac9_config cfg = {0}; + + /* post header has various typical ATRAC9 values */ + cfg.channels = vgmstream->channels; + cfg.config_data = read_32bit(post_meta_offset+0x0c,streamFile); + cfg.encoder_delay = read_32bit(post_meta_offset+0x18,streamFile); + + vgmstream->codec_data = init_atrac9(&cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_ATRAC9; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = read_32bit(post_meta_offset+0x10,streamFile); /* loop values above are also weird and ignored */ + vgmstream->loop_start_sample = read_32bit(post_meta_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start + vgmstream->loop_end_sample = read_32bit(post_meta_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end + break; + } +#endif + case -1: /* used for dummy entries */ default: VGM_LOG("SCD: unknown codec 0x%x\n", codec); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c index 2c98eaa2b..cd2cbf5cc 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c @@ -2,13 +2,14 @@ #include "../coding/coding.h" -static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size); +static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, int encryption, size_t header_size, size_t key_start); -/* SABF/MABF - Square Enix's "Sead" audio games [Dragon Quest Builders (PS3), Dissidia Opera Omnia (mobile), FF XV (PS4)] */ +/* SABF/MABF - Square Enix's "sead" audio games [Dragon Quest Builders (PS3), Dissidia Opera Omnia (mobile), FF XV (PS4)] */ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) { VGMSTREAM * vgmstream = NULL; - off_t start_offset, mtrl_offset, meta_offset, post_meta_offset; //, info_offset, name_offset = 0; - size_t stream_size, subheader_size; //, name_size = 0; + off_t start_offset, tables_offset, mtrl_offset, meta_offset, post_meta_offset; //, info_offset, name_offset = 0; + size_t stream_size, descriptor_size, subheader_size, special_size; //, name_size = 0; + int loop_flag = 0, channel_count, codec, sample_rate, loop_start, loop_end; int is_sab = 0, is_mab = 0; @@ -36,38 +37,43 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) { // goto fail; /* 0x04(1): version? (usually 0x02, rarely 0x01, ex FF XV title) */ /* 0x05(1): 0x00/01? */ - /* 0x06(2): chunk size? (usually 0x10, rarely 0x20) */ - if (read_16bitBE(0x06,streamFile) < 0x100) { /* use size as no apparent flag */ + /* 0x06(2): version? (usually 0x10, rarely 0x20) */ + if (read_16bitBE(0x06,streamFile) < 0x100) { /* use some value as no apparent flag */ read_32bit = read_32bitBE; read_16bit = read_16bitBE; } else { read_32bit = read_32bitLE; read_16bit = read_16bitLE; } - /* 0x08(1): ?, 0x09(1): ?, 0x0a(2): ? */ + /* 0x08(1): version 0x04?, 0x0a(2): ? */ + descriptor_size = read_8bit(0x09,streamFile); + if (read_32bit(0x0c,streamFile) != get_streamfile_size(streamFile)) goto fail; - /* 0x10(10): file descriptor ("BGM", "Music", "SE", etc) */ + /* 0x10(n): file descriptor ("BGM", "Music", "SE", etc, long names are ok), padded */ + tables_offset = 0x10 + (descriptor_size + 0x01); /* string null seems counted for padding */ + if (tables_offset % 0x10) + tables_offset += 0x10 - (tables_offset % 0x10); /** offset tables **/ if (is_sab) { - if (read_32bitBE(0x20,streamFile) != 0x736E6420) goto fail; /* "snd " (info) */ - if (read_32bitBE(0x30,streamFile) != 0x73657120) goto fail; /* "seq " (unknown) */ - if (read_32bitBE(0x40,streamFile) != 0x74726B20) goto fail; /* "trk " (unknown) */ - if (read_32bitBE(0x50,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */ - //info_offset = read_32bit(0x28,streamFile); - //seq_offset = read_32bit(0x38,streamFile); - //trk_offset = read_32bit(0x48,streamFile); - mtrl_offset = read_32bit(0x58,streamFile); + if (read_32bitBE(tables_offset+0x00,streamFile) != 0x736E6420) goto fail; /* "snd " (info) */ + if (read_32bitBE(tables_offset+0x10,streamFile) != 0x73657120) goto fail; /* "seq " (unknown) */ + if (read_32bitBE(tables_offset+0x20,streamFile) != 0x74726B20) goto fail; /* "trk " (unknown) */ + if (read_32bitBE(tables_offset+0x30,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */ + //info_offset = read_32bit(tables_offset+0x08,streamFile); + //seq_offset = read_32bit(tables_offset+0x18,streamFile); + //trk_offset = read_32bit(tables_offset+0x28,streamFile); + mtrl_offset = read_32bit(tables_offset+0x38,streamFile); } else if (is_mab) { - if (read_32bitBE(0x20,streamFile) != 0x6D757363) goto fail; /* "musc" (info) */ - if (read_32bitBE(0x30,streamFile) != 0x696E7374) goto fail; /* "inst" (unknown) */ - if (read_32bitBE(0x40,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */ - //info_offset = read_32bit(0x28,streamFile); - //inst_offset = read_32bit(0x38,streamFile); - mtrl_offset = read_32bit(0x48,streamFile); + if (read_32bitBE(tables_offset+0x00,streamFile) != 0x6D757363) goto fail; /* "musc" (info) */ + if (read_32bitBE(tables_offset+0x10,streamFile) != 0x696E7374) goto fail; /* "inst" (unknown) */ + if (read_32bitBE(tables_offset+0x20,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */ + //info_offset = read_32bit(tables_offset+0x08,streamFile); + //inst_offset = read_32bit(tables_offset+0x18,streamFile); + mtrl_offset = read_32bit(tables_offset+0x28,streamFile); } else { goto fail; @@ -114,7 +120,7 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) { loop_end = read_32bit(meta_offset+0x10,streamFile); subheader_size = read_32bit(meta_offset+0x14,streamFile); /* including subfile header */ stream_size = read_32bit(meta_offset+0x18,streamFile); /* not including subfile header */ - /* 0x1c: null? */ + special_size = read_32bit(meta_offset+0x1c,streamFile); loop_flag = (loop_end > 0); post_meta_offset = meta_offset + 0x20; @@ -122,7 +128,7 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) { /** info section (get stream name) **/ //if (is_sab) { //todo load name based on entry id - /* "snd ": unknown flags/sizes and name */ + /* "snd " */ /* 0x08(2): file number within descriptor */ /* 0x1a(2): base_entry size (-0x10?) */ //name_size = read_32bit(snd_offset+0x20,streamFile); @@ -130,7 +136,11 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) { /* 0x24(4): unique id? (referenced in "seq" section) */ //} //else if (is_mab) { - /* "musc": unknown flags sizes and names, another format */ + /* "musc" */ + //looks like a "music cue" section, pointing to one subsection per "material". + // ex. one cue may point to 3 named subsongs/sections. + // some common header info from all materials is repeated (ex. sample rate), while other + // (loops, maybe proper num_samples) are listed per material but don't always match thei header //} @@ -161,6 +171,37 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) { break; } +#ifdef VGM_USE_VORBIS + case 0x03: { /* OGG [Final Fantasy XV Benchmark sfx (PC)] */ + VGMSTREAM *ogg_vgmstream = NULL; + vgm_vorbis_info_t inf = {0}; + off_t subfile_offset = post_meta_offset + subheader_size; + char filename[PATH_LIMIT]; + + streamFile->get_name(streamFile,filename,sizeof(filename)); + + inf.layout_type = layout_ogg_vorbis; + inf.meta_type = vgmstream->meta_type; + inf.total_subsongs = total_subsongs; + inf.stream_size = stream_size; + /* post header has some kind of repeated values, config/table? */ + + ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, subfile_offset, &inf); + if (ogg_vgmstream) { + ogg_vgmstream->num_streams = vgmstream->num_streams; + ogg_vgmstream->stream_size = vgmstream->stream_size; + + close_vgmstream(vgmstream); + return ogg_vgmstream; + } + else { + goto fail; + } + + break; + } +#endif + #ifdef VGM_USE_ATRAC9 case 0x04: { /* ATRAC9 [Dragon Quest Builders (Vita), Final Fantaxy XV (PS4)] */ atrac9_config cfg = {0}; @@ -170,12 +211,12 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) { cfg.channels = vgmstream->channels; cfg.config_data = read_32bit(post_meta_offset+0x0c,streamFile); cfg.encoder_delay = read_32bit(post_meta_offset+0x18,streamFile); -VGM_LOG("1\n"); + vgmstream->codec_data = init_atrac9(&cfg); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_ATRAC9; vgmstream->layout_type = layout_none; -VGM_LOG("2\n"); + vgmstream->sample_rate = read_32bit(post_meta_offset+0x1c,streamFile); /* SAB's sample rate can be different but it's ignored */ vgmstream->num_samples = read_32bit(post_meta_offset+0x10,streamFile); /* loop values above are also weird and ignored */ vgmstream->loop_start_sample = read_32bit(post_meta_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start @@ -185,7 +226,7 @@ VGM_LOG("2\n"); #endif #ifdef VGM_USE_MPEG - case 0x06: { /* MSF subfile (MPEG mode) [Dragon Quest Builders (PS3)] */ + case 0x06: { /* MSF subfile (MPEG mode) [Dragon Quest Builders (PS3)] */ mpeg_codec_data *mpeg_data = NULL; mpeg_custom_config cfg = {0}; @@ -210,10 +251,14 @@ VGM_LOG("2\n"); STREAMFILE *temp_streamFile = NULL; off_t subfile_offset = post_meta_offset + 0x10; size_t subfile_size = stream_size + subheader_size - 0x10; - /* post header has 0x10 unknown + HCA header */ + /* post header: values from the HCA header, in file endianness + HCA header */ + size_t key_start = special_size & 0xff; + size_t header_size = read_16bit(post_meta_offset+0x02, streamFile); + int encryption = read_16bit(post_meta_offset+0x0c, streamFile); //maybe 8bit? + /* encryption type 0x01 found in Final Fantasy XII TZA (PS4/PC) */ - temp_streamFile = setup_sead_hca_streamfile(streamFile, subfile_offset, subfile_size); + temp_streamFile = setup_sead_hca_streamfile(streamFile, subfile_offset, subfile_size, encryption, header_size, key_start); if (!temp_streamFile) goto fail; temp_vgmstream = init_vgmstream_hca(temp_streamFile); @@ -249,7 +294,49 @@ fail: return NULL; } -static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size) { + +typedef struct { + size_t header_size; + size_t key_start; +} sead_decryption_data; + +/* Encrypted HCA */ +static size_t sead_decryption_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, sead_decryption_data* data) { + /* Found in FFXII_TZA.exe (same key in SCD Ogg V3) */ + static const uint8_t encryption_key[0x100] = { + 0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F + 0x32, 0x52, 0x16, 0x1B, 0x3C, 0xA1, 0x54, 0x7B, 0x1B, 0x97, 0xA6, 0x93, 0x1A, 0x4B, 0xAA, 0xA6, // 10-1F + 0x7A, 0x7B, 0x1B, 0x97, 0xA6, 0xF7, 0x02, 0xBB, 0xAA, 0xA6, 0xBB, 0xF7, 0x2A, 0x51, 0xBE, 0x03, // 20-2F + 0xF4, 0x2A, 0x51, 0xBE, 0x03, 0xF4, 0x2A, 0x51, 0xBE, 0x12, 0x06, 0x56, 0x27, 0x32, 0x32, 0x36, // 30-3F + 0x32, 0xB2, 0x1A, 0x3B, 0xBC, 0x91, 0xD4, 0x7B, 0x58, 0xFC, 0x0B, 0x55, 0x2A, 0x15, 0xBC, 0x40, // 40-4F + 0x92, 0x0B, 0x5B, 0x7C, 0x0A, 0x95, 0x12, 0x35, 0xB8, 0x63, 0xD2, 0x0B, 0x3B, 0xF0, 0xC7, 0x14, // 50-5F + 0x51, 0x5C, 0x94, 0x86, 0x94, 0x59, 0x5C, 0xFC, 0x1B, 0x17, 0x3A, 0x3F, 0x6B, 0x37, 0x32, 0x32, // 60-6F + 0x30, 0x32, 0x72, 0x7A, 0x13, 0xB7, 0x26, 0x60, 0x7A, 0x13, 0xB7, 0x26, 0x50, 0xBA, 0x13, 0xB4, // 70-7F + 0x2A, 0x50, 0xBA, 0x13, 0xB5, 0x2E, 0x40, 0xFA, 0x13, 0x95, 0xAE, 0x40, 0x38, 0x18, 0x9A, 0x92, // 80-8F + 0xB0, 0x38, 0x00, 0xFA, 0x12, 0xB1, 0x7E, 0x00, 0xDB, 0x96, 0xA1, 0x7C, 0x08, 0xDB, 0x9A, 0x91, // 90-9F + 0xBC, 0x08, 0xD8, 0x1A, 0x86, 0xE2, 0x70, 0x39, 0x1F, 0x86, 0xE0, 0x78, 0x7E, 0x03, 0xE7, 0x64, // A0-AF + 0x51, 0x9C, 0x8F, 0x34, 0x6F, 0x4E, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, // B0-BF + 0x41, 0xFC, 0x3B, 0x70, 0x71, 0x64, 0x33, 0x32, 0x12, 0x32, 0x32, 0x36, 0x70, 0x34, 0x2B, 0x56, // C0-CF + 0x22, 0x70, 0x3A, 0x13, 0xB7, 0x26, 0x60, 0xBA, 0x1B, 0x94, 0xAA, 0x40, 0x38, 0x00, 0xFA, 0xB2, // D0-DF + 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x12, 0x32, 0xB2, 0x32, 0x32, 0x32, 0x32, 0x75, 0xA3, 0x26, 0x7B, // E0-EF + 0x83, 0x26, 0xF9, 0x83, 0x2E, 0xFF, 0xE3, 0x16, 0x7D, 0xC0, 0x1E, 0x63, 0x21, 0x07, 0xE3, 0x01, // F0-FF + }; + size_t bytes_read; + int i; + + bytes_read = streamfile->read(streamfile, dest, offset, length); + + /* decrypt data (xor) */ + if (offset >= data->header_size) { + for (i = 0; i < bytes_read; i++) { + dest[i] ^= encryption_key[(data->key_start + (offset - data->header_size) + i) % 0x100]; + } + } + + return bytes_read; +} + +static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, int encryption, size_t header_size, size_t key_start) { STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; /* setup subfile */ @@ -261,6 +348,18 @@ static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfi if (!new_streamFile) goto fail; temp_streamFile = new_streamFile; + if (encryption) { + sead_decryption_data io_data = {0}; + size_t io_data_size = sizeof(sead_decryption_data); + + io_data.header_size = header_size; + io_data.key_start = key_start; + + new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, sead_decryption_read); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + } + new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,"hca"); if (!new_streamFile) goto fail; temp_streamFile = new_streamFile; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sxd.c b/Frameworks/vgmstream/vgmstream/src/meta/sxd.c index 13801cad6..224dc80ac 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sxd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sxd.c @@ -5,12 +5,12 @@ /* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; + STREAMFILE * streamHeader = NULL, *streamData = NULL; off_t start_offset, chunk_offset, first_offset = 0x60, name_offset = 0; size_t chunk_size, stream_size = 0; - int is_separate; - int loop_flag, channels, codec; + int is_dual, is_external; + int loop_flag, channels, codec, location; int sample_rate, num_samples, loop_start_sample, loop_end_sample; uint32_t at9_config_data = 0; int total_subsongs, target_subsong = streamFile->stream_index; @@ -19,10 +19,10 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { /* check extension, case insensitive */ /* .sxd: header+data (SXDF), .sxd1: header (SXDF) + .sxd2 = data (SXDS) */ if (!check_extensions(streamFile,"sxd,sxd2")) goto fail; - is_separate = !check_extensions(streamFile,"sxd"); + is_dual = !check_extensions(streamFile,"sxd"); /* sxd1+sxd2: use sxd1 as header; otherwise use the current file as header */ - if (is_separate) { + if (is_dual) { if (read_32bitBE(0x00,streamFile) != 0x53584453) /* "SXDS" */ goto fail; streamHeader = open_stream_ext(streamFile, "sxd1"); @@ -50,10 +50,10 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { table_offset = chunk_offset + 0x08 + 4*(target_subsong-1); header_offset = table_offset + read_32bitLE(table_offset,streamHeader); - /* 0x00(4): type/location? (00/01=sxd/RAM?, 02/03=sxd2/stream?) */ - codec = read_8bit (header_offset+0x04,streamHeader); - channels = read_8bit (header_offset+0x05,streamHeader); - sample_rate = read_32bitLE(header_offset+0x08,streamHeader); + location = read_32bitLE(header_offset+0x00,streamHeader); + codec = read_8bit (header_offset+0x04,streamHeader); + channels = read_8bit (header_offset+0x05,streamHeader); + sample_rate = read_32bitLE(header_offset+0x08,streamHeader); /* 0x0c(4): unknown size? (0x4000/0x3999/0x3333/etc, not related to extra data) */ /* 0x10(4): ? + volume? + pan? (can be 0 for music) */ num_samples = read_32bitLE(header_offset+0x14,streamHeader); @@ -69,7 +69,7 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { off_t max_offset = chunk_offset + chunk_size; /* manually try to find certain tag, no idea about the actual format - * (most variable in Soul Sacrifice; extra size isn't found in the SXD AFAIK) */ + * (most variable in Soul Sacrifice; extra data size isn't found in the header AFAIK) */ while (extra_offset < max_offset) { uint32_t tag = read_32bitBE(extra_offset, streamHeader); if (tag == 0x0A010000 || tag == 0x0A010600) { @@ -85,16 +85,33 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { loop_flag = loop_start_sample != -1 && loop_end_sample != -1; - /* from current offset in sxd, absolute in sxd2 */ - if (is_separate) { - start_offset = stream_offset; + /* usually sxd=header+data and sxd1=header + sxd2=data, but rarely sxd1 contain data [The Last Guardian (PS4)] */ + switch(location) { /* might not be exact but seems the only difference in TLG */ + case 0x00: /* some Chaos Rings 2 sfx */ + case 0x01: /* most common */ + case 0x05: /* some Gradity Rush 2 sfx */ + is_external = 0; /* RAM asset? */ + break; + + case 0x02: /* some Chaos Rings 3 sfx */ + case 0x03: /* most common */ + is_external = 1; /* stream asset? */ + break; + + default: + VGM_LOG("SXD: unknown location 0x%x\n", location); + goto fail; + } + + if (is_external) { + start_offset = stream_offset; /* absolute if external */ } else { - start_offset = header_offset+0x24 + stream_offset; + start_offset = header_offset+0x24 + stream_offset; /* from current entry offset if internal */ } } /* get stream name (NAME is tied to REQD/cues, and SFX cues repeat WAVEs, but should work ok for streams) */ - if (is_separate && find_chunk_le(streamHeader, 0x4E414D45,first_offset,0, &chunk_offset,NULL)) { /* "NAME" */ + if (is_dual && find_chunk_le(streamHeader, 0x4E414D45,first_offset,0, &chunk_offset,NULL)) { /* "NAME" */ /* table: relative offset (32b) + hash? (32b) + cue index (32b) */ int i; int num_entries = read_16bitLE(chunk_offset+0x04,streamHeader); /* can be bigger than streams */ @@ -107,6 +124,22 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { } } + if (is_external && !is_dual) { + VGM_LOG("SXD: found single sxd with external data\n"); + goto fail; + } + + if (is_external) { + streamData = streamFile; + } else { + streamData = streamHeader; + } + + if (start_offset > get_streamfile_size(streamData)) { + VGM_LOG("SXD: wrong location?\n"); + goto fail; + } + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels,loop_flag); @@ -136,7 +169,7 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { break; #ifdef VGM_USE_ATRAC9 - case 0x42: { /* ATRAC9 [Soul Sacrifice (Vita), Freedom Wars (Vita)] */ + case 0x42: { /* ATRAC9 [Soul Sacrifice (Vita), Freedom Wars (Vita), Gravity Rush 2 (PS4)] */ atrac9_config cfg = {0}; cfg.channels = vgmstream->channels; @@ -157,14 +190,14 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) { /* open the file for reading */ - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream,streamData,start_offset)) goto fail; - if (is_separate && streamHeader) close_streamfile(streamHeader); + if (is_dual) close_streamfile(streamHeader); return vgmstream; fail: - if (is_separate && streamHeader) close_streamfile(streamHeader); + if (is_dual) close_streamfile(streamHeader); close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index ee5ddcfd2..82d6e560f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -95,7 +95,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { /* type to coding conversion */ switch (txth.codec) { case PSX: coding = coding_PSX; break; - case XBOX: coding = coding_XBOX; break; + case XBOX: coding = coding_XBOX_IMA; break; case NGC_DTK: coding = coding_NGC_DTK; break; case PCM16BE: coding = coding_PCM16BE; break; case PCM16LE: coding = coding_PCM16LE; break; @@ -205,7 +205,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { vgmstream->interleave_block_size = txth.interleave; vgmstream->layout_type = layout_none; break; - case coding_XBOX: + case coding_XBOX_IMA: vgmstream->layout_type = layout_none; break; case coding_NGC_DTK: @@ -474,7 +474,6 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h else if (0==strcmp(key,"interleave")) { if (0==strcmp(val,"half_size")) { txth->interleave = txth->data_size / txth->channels; - VGM_LOG("int=%x, ds=%x\n", txth->interleave, txth->data_size); } else { if (!parse_num(streamFile,val, &txth->interleave)) goto fail; @@ -635,7 +634,7 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) { if (!txth->interleave) return 0; return ms_ima_bytes_to_samples(bytes, txth->interleave, txth->channels); case XBOX: - return ms_ima_bytes_to_samples(bytes, 0x24 * txth->channels, txth->channels); + return xbox_ima_bytes_to_samples(bytes, txth->channels); case NGC_DSP: return dsp_bytes_to_samples(bytes, txth->channels); case PSX: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c index 486ace356..c1d7e3c0d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c @@ -78,7 +78,8 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { switch(((uint64_t)platform << 32) | type) { case 0x57696E2070636D20: /* "Win pcm " */ - case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4)*/ + case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4) */ + case 0x4E78202070636D20: /* "Nx pcm " (Nx = Switch) */ /* chunks: "data" */ vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; @@ -162,7 +163,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { #endif #ifdef VGM_USE_ATRAC9 - case 0x5649544161743920: { /*"VITAat9 "*/ + case 0x5649544161743920: { /* "VITAat9 " */ /* chunks: "fact" (equivalent to a RIFF "fact", num_samples + skip_samples), "data" */ atrac9_config cfg = {0}; @@ -181,6 +182,48 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { } #endif +#ifdef VGM_USE_FFMPEG + case 0x4E7820204E782020: { /* "Nx Nx " */ + /* chunks: "MARK" (optional seek table), "STRG" (optional description) */ + uint8_t buf[0x100]; + size_t bytes, skip, opus_size; + ffmpeg_custom_config cfg = {0}; + + /* a standard Switch Opus header */ + skip = read_32bitLE(start_offset + 0x1c, streamFile); + opus_size = read_32bitLE(start_offset + 0x10, streamFile) + 0x08; + start_offset += opus_size; + data_size -= opus_size; + + cfg.type = FFMPEG_SWITCH_OPUS; + + bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate); + if (bytes <= 0) goto fail; + + vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + if (((ffmpeg_codec_data*)vgmstream->codec_data)->skipSamples <= 0) + ffmpeg_set_skip_samples(vgmstream->codec_data, skip); + + { + off_t chunk_offset = off + 0x20 + 0xc; /* after "fmt" */ + while (chunk_offset < header_size) { + if (read_32bitBE(chunk_offset,streamFile) == 0x4164496E) { /*"AdIn" additional info */ + off_t adin_offset = read_32bitLE(chunk_offset+0x04,streamFile); + vgmstream->num_samples = read_32bitLE(adin_offset,streamFile); + break; + } + chunk_offset += 0xc; + } + } + + break; + } +#endif + default: VGM_LOG("RAKI: unknown platform %x and type %x\n", platform, type); goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c index d0ad0272c..ad0d9abb0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -119,6 +119,7 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { start_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_size + sb.section3_size; start_offset += sb.stream_offset; } + //;VGM_LOG("start offset=%lx, external=%i\n", start_offset, sb.is_external); /* build the VGMSTREAM */ @@ -154,9 +155,9 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { break; case RAW_XBOX: - vgmstream->coding_type = coding_XBOX; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; - vgmstream->num_samples = ms_ima_bytes_to_samples(sb.stream_size, 0x24*sb.channels,sb.channels); + vgmstream->num_samples = xbox_ima_bytes_to_samples(sb.stream_size, sb.channels); break; case RAW_DSP: @@ -886,5 +887,21 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) return 1; } + /* Surf's Up (2007)(PC) */ + if (sb->version == 0x00190005 && is_sb0) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x74; + + sb->external_flag_offset = 0x28; /* maybe 0x2c */ + sb->channels_offset = 0x3c; + sb->sample_rate_offset = 0x40; + sb->num_samples_offset = 0x48; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x58; + + sb->has_extra_name_flag = 1; + return 1; + } + return 0; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/waa_wac_wad_wam.c b/Frameworks/vgmstream/vgmstream/src/meta/waa_wac_wad_wam.c index 0ca8df892..0b7b50d4e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/waa_wac_wad_wam.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/waa_wac_wad_wam.c @@ -1,146 +1,146 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" + /* const short wad_coef[16][2] = { - {0x4002,0x2003}, - {0x2016,0xc600}, - {0xC600,0x98ab}, - {0x96bf,0x29c5}, - {0x2003,0x0081}, - {0x0e00,0x2004}, - {0x8e01,0xc500}, - {0x70bf,0x8128}, - {0x288e,0xc600}, - {0x016e,0x0e5b}, - {0xbe20,0x2003}, - {0x03c6,0xc600}, - {0x0048,0xe85a}, - {0xbe28,0x28c6}, - {0xc600,0x00F6}, - {0xbeab,0x5520} + {0x4002,0x2003}, + {0x2016,0xc600}, + {0xC600,0x98ab}, + {0x96bf,0x29c5}, + {0x2003,0x0081}, + {0x0e00,0x2004}, + {0x8e01,0xc500}, + {0x70bf,0x8128}, + {0x288e,0xc600}, + {0x016e,0x0e5b}, + {0xbe20,0x2003}, + {0x03c6,0xc600}, + {0x0048,0xe85a}, + {0xbe28,0x28c6}, + {0xc600,0x00F6}, + {0xbeab,0x5520} };*/ const short wad_coef[16] = { - 0x04ab, 0xfced, - 0x0789, 0xfedf, - 0x09a2, 0xfae5, - 0x0c90, 0xfac1, - 0x084d, 0xfaa4, - 0x0982, 0xfdf7, - 0x0af6, 0xfafa, - 0x0be6, 0xfbf5 + 0x04ab, 0xfced, + 0x0789, 0xfedf, + 0x09a2, 0xfae5, + 0x0c90, 0xfac1, + 0x084d, 0xfaa4, + 0x0982, 0xfdf7, + 0x0af6, 0xfafa, + 0x0be6, 0xfbf5 }; -/* WAC - WAD - WAM (Beyond Good & Evil GC/PS2/Xbox/Wii) */ -/* Note: A "Flat Layout" has no interleave */ +/* WAC/WAD/WAM/WAA - from Beyond Good & Evil (PS2/Xbox/GC/Wii) */ VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - int i; + int i; off_t start_offset; int loop_flag; - int channel_count; - int coef1_start; - int coef2_start; - int second_channel_start = -1; + int channel_count; + int coef1_start; + int coef2_start; + int second_channel_start = -1; // Check file extensions streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("waa",filename_extension(filename)) && - strcasecmp("wac",filename_extension(filename)) && - strcasecmp("wad",filename_extension(filename)) && - strcasecmp("wam",filename_extension(filename))) goto fail; + strcasecmp("wac",filename_extension(filename)) && + strcasecmp("wad",filename_extension(filename)) && + strcasecmp("wam",filename_extension(filename))) goto fail; /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */ - read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */ - read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt\0x20" */ - read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */ - goto fail; + if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */ + read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */ + read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt " */ + read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */ + goto fail; - /* files don't contain looping information, - so the looping is not done depending on extension. - wam and waa contain ambient sounds and music, so often they contain - looped music. Change extension to wac or wad to make the sound non-looping. - */ + /* files don't contain looping information, + so the looping is not done depending on extension. + wam and waa contain ambient sounds and music, so often they contain + looped music. Change extension to wac or wad to make the sound non-looping. + */ loop_flag = strcasecmp("wac",filename_extension(filename)) && - strcasecmp("wad",filename_extension(filename)); + strcasecmp("wad",filename_extension(filename)); channel_count = (uint16_t)read_16bitLE(0x16,streamFile); - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* Check what encoder is needed */ - //FIXME: //PC version uses pcm, but which encoder? + /* Check what encoder is needed */ + //FIXME: //PC version uses pcm, but which encoder? - vgmstream->channels = channel_count; + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x18,streamFile); - vgmstream->meta_type = meta_WAA_WAC_WAD_WAM; + vgmstream->meta_type = meta_WAA_WAC_WAD_WAM; vgmstream->layout_type = layout_none; - switch((uint16_t)read_16bitLE(0x14,streamFile)) { + switch((uint16_t)read_16bitLE(0x14,streamFile)) { case 0x0069: // XBOX IMA ADPCM - start_offset = 0x2E; - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/36/channel_count*64; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/36/channel_count*64; - } + start_offset = 0x2E; + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x2A,streamFile), channel_count); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = xbox_ima_bytes_to_samples(read_32bitLE(0x2A,streamFile),channel_count); + } break; case 0xFFFF: // PS2 ADPCM - start_offset = 0x2E; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/16*28/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/16*28/channel_count; - } + start_offset = 0x2E; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/16*28/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/16*28/channel_count; + } second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+start_offset; break; case 0xFFFE: // GameCube/WII DSP - start_offset = 0x5C; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))*14/8/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))*14/8/channel_count; - } - if(read_16bitLE(0x24,streamFile)==0x00)//is a wii file with no coeff table - { - //FIXME: WII version of WAM/WAD/WAC need some coeff table from somewhere - for (i=0;i<16;i++) - vgmstream->ch[0].adpcm_coef[i] = wad_coef[i]; - if (channel_count == 2) { - for (i=0;i<16;i++) - vgmstream->ch[1].adpcm_coef[i] = wad_coef[i]; - } - goto fail; - } - else - { - second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+0x8A; - /* Retrieveing the coef tables */ - coef1_start = 0x2E; - coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C; + start_offset = 0x5C; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))*14/8/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))*14/8/channel_count; + } + if(read_16bitLE(0x24,streamFile)==0x00)//is a wii file with no coeff table + { + //FIXME: WII version of WAM/WAD/WAC need some coeff table from somewhere + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = wad_coef[i]; + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = wad_coef[i]; + } + goto fail; + } + else + { + second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+0x8A; + /* Retrieveing the coef tables */ + coef1_start = 0x2E; + coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C; - { - int i; - for (i=0;i<16;i++) - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile); - if (channel_count == 2) { - for (i=0;i<16;i++) - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile); - } - } - } + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile); + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile); + } + } + } break; - default: - goto fail; - } + default: + goto fail; + } @@ -154,7 +154,7 @@ VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) { for (i=0;ich[i].streamfile = file; - if (vgmstream->coding_type == coding_XBOX) { + if (vgmstream->coding_type == coding_XBOX_IMA) { /* xbox interleaving is a little odd */ vgmstream->ch[i].channel_start_offset=start_offset; } else { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wvs.c b/Frameworks/vgmstream/vgmstream/src/meta/wvs.c index 163d93cf4..354a55955 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wvs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wvs.c @@ -1,68 +1,50 @@ #include "meta.h" -#include "../util.h" - -/* - WVS (found in Metal Arms - Glitch in the System) - XBOX and GameCube -*/ +#include "../coding/coding.h" +/* WVS - found in Metal Arms - Glitch in the System (Xbox) */ VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag, channel_count; + size_t data_size; - int loop_flag=0; - int channel_count; - int i; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("wvs",filename_extension(filename))) goto fail; + /* check extension */ + if (!check_extensions(streamFile,"wvs")) + goto fail; - if((read_16bitLE(0x0C,streamFile)!=0x69) && - (read_16bitLE(0x08,streamFile)!=0x4400) && - (read_32bitLE(0x0,streamFile)!=get_streamfile_size(streamFile)+0x20)) - goto fail; + if (read_16bitLE(0x0C,streamFile) != 0x69 && /* codec */ + read_16bitLE(0x08,streamFile) != 0x4400) + goto fail; - /* Loop seems to be set if offset(0x0A) == 0x472C */ - loop_flag = (read_16bitLE(0x0A,streamFile)==0x472C); + start_offset = 0x20; + data_size = read_32bitLE(0x00,streamFile); + loop_flag = (read_16bitLE(0x0a,streamFile) == 0x472C); /* loop seems to be like this */ + channel_count = read_16bitLE(0x0e,streamFile); /* always stereo files */ - /* Always stereo files */ - channel_count=read_16bitLE(0x0E,streamFile); - - /* build the VGMSTREAM */ + if (data_size + start_offset != get_streamfile_size(streamFile)) + goto fail; + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - /* allways 2 channels @ 44100 Hz */ - vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = read_32bitLE(0,streamFile) / 36 * 64 / vgmstream->channels; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_XBOX_WVS; - if(loop_flag) { - vgmstream->loop_start_sample=0; - vgmstream->loop_end_sample=vgmstream->num_samples; - } - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); - vgmstream->ch[i].offset = 0x20; - - if (!vgmstream->ch[i].streamfile) goto fail; - } - } + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } @@ -75,7 +57,7 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; int loop_flag; - int channel_count; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -94,7 +76,7 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) { vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ + /* fill in the vital statistics */ start_offset = 0x60; if (channel_count == 1) { @@ -103,8 +85,8 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) { vgmstream->sample_rate = 44100; } - vgmstream->channels = channel_count; - + vgmstream->channels = channel_count; + vgmstream->coding_type = coding_NGC_DSP; vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/8/channel_count*14; //(read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14; if (loop_flag) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c index bf5e97bc2..8cd588f8d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c @@ -194,11 +194,12 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { break; case IMA: /* common */ - /* slightly modified MS IMA with interleaved sub-blocks and LE/BE header */ + /* slightly modified XBOX-IMA with interleaved sub-blocks and LE/BE header */ /* Wwise uses common codecs (ex. 0x0002 MSADPCM) so this parser should go AFTER riff.c avoid misdetection */ if (ww.bits_per_sample != 4) goto fail; + if (ww.block_align != 0x24 * ww.channels) goto fail; vgmstream->coding_type = coding_WWISE_IMA; vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = ww.block_align; @@ -207,7 +208,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { if (ww.truncated) /* enough to get real samples */ ww.data_size = ww.file_size - ww.data_offset; - vgmstream->num_samples = ms_ima_bytes_to_samples(ww.data_size, ww.block_align, ww.channels); + vgmstream->num_samples = xbox_ima_bytes_to_samples(ww.data_size, ww.channels); break; #ifdef VGM_USE_VORBIS diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xau.c b/Frameworks/vgmstream/vgmstream/src/meta/xau.c index 8e12db044..ab663dc8b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xau.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xau.c @@ -58,11 +58,11 @@ VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) { goto fail; vgmstream->sample_rate = read_32bitLE(0x58, streamFile); - vgmstream->num_samples = ms_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), read_16bitLE(0x60, streamFile), channel_count); + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), channel_count); vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; - vgmstream->coding_type = coding_XBOX; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_ims.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_ims.c index 08721d659..89aeef604 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xbox_ims.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_ims.c @@ -29,8 +29,8 @@ VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile) { /* fill in the vital statistics */ vgmstream->channels = channel_count; vgmstream->sample_rate = read_16bitLE(0x06,streamFile) & 0xffff; - vgmstream->coding_type = coding_XBOX; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_matx_blocked; vgmstream->meta_type = meta_XBOX_MATX; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_wavm.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_wavm.c index 0f0853d68..ec1c41062 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xbox_wavm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_wavm.c @@ -1,62 +1,37 @@ #include "meta.h" -#include "../util.h" - -/* WAVM - - WAVM is an headerless format which can be found on XBOX - known extensions : WAVM - - 2008-05-23 - Fastelbja : First version ... -*/ +#include "../coding/coding.h" +/* WAVM - headerless format which can be found on XBOX */ VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + off_t start_offset = 0; + int loop_flag, channel_count; - int loop_flag=0; - int channel_count; - int i; + /* check extension */ + if (!check_extensions(streamFile,"wavm")) + goto fail; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("wavm",filename_extension(filename))) goto fail; - - /* No loop on wavm */ - loop_flag = 0; + start_offset = 0; + loop_flag = 0; + channel_count = 2; - /* Always stereo files */ - channel_count=2; - - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - /* allways 2 channels @ 44100 Hz */ - vgmstream->channels = 2; vgmstream->sample_rate = 44100; + vgmstream->num_samples = xbox_ima_bytes_to_samples(get_streamfile_size(streamFile), vgmstream->channels); - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) / 36 * 64 / vgmstream->channels); + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_XBOX_WAVM; - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); - vgmstream->ch[i].offset = 0; - - if (!vgmstream->ch[i].streamfile) goto fail; - } - } + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } - diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xmu.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xmu.c index 337674c7f..63f5faea5 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xmu.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xmu.c @@ -1,65 +1,44 @@ #include "meta.h" -#include "../util.h" - -/* XMU - - XMU (found in Alter Echo) -*/ +#include "../coding/coding.h" +/* XMU- found in Alter Echo (Xbox) */ VGMSTREAM * init_vgmstream_xbox_xmu(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + size_t start_offset; + int loop_flag, channel_count; + size_t data_size; - int loop_flag=0; - int channel_count; - int i; + /* check extension */ + if (!check_extensions(streamFile,"xmu")) + goto fail; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xmu",filename_extension(filename))) goto fail; + if (read_32bitBE(0x00,streamFile) != 0x584D5520 && /* "XMU " */ + read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */ + goto fail; - if((read_32bitBE(0x00,streamFile)!=0x584D5520) && - (read_32bitBE(0x08,streamFile)!=0x46524D54)) - goto fail; + start_offset = 0x800; + channel_count=read_8bit(0x14,streamFile); /* always stereo files */ + loop_flag = read_8bit(0x16,streamFile); /* no Loop found atm */ + data_size = read_32bitLE(0x7FC,streamFile); /* next to "DATA" */ - /* No Loop found atm */ - loop_flag = read_8bit(0x16,streamFile);; - - /* Always stereo files */ - channel_count=read_8bit(0x14,streamFile); - - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = read_32bitLE(0x7FC,streamFile) / 36 * 64 / vgmstream->channels; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_XBOX_XMU; - if(loop_flag) { - vgmstream->loop_start_sample=0; - vgmstream->loop_end_sample=vgmstream->num_samples; - } - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); - vgmstream->ch[i].offset = 0x800; - - if (!vgmstream->ch[i].streamfile) goto fail; - } - } - + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xvas.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xvas.c index a17298c3a..21ea9be49 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xvas.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xvas.c @@ -1,72 +1,52 @@ #include "meta.h" #include "../layout/layout.h" -#include "../util.h" - -/* XVAS - - XVAS (found in TMNT 2 & TMNT 3)) -*/ +#include "../coding/coding.h" +/* XVAS - found in TMNT 2 & TMNT 3 (Xbox) */ VGMSTREAM * init_vgmstream_xbox_xvas(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag, channel_count; + size_t data_size; - int loop_flag=0; - int channel_count; - int i; + /* check extension */ + if (!check_extensions(streamFile,"xvas")) + goto fail; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xvas",filename_extension(filename))) goto fail; + if (read_32bitLE(0x00,streamFile) != 0x69 && /* codec */ + read_32bitLE(0x08,streamFile) != 0x48) /* block size (probably 0x24 for mono) */ + goto fail; - if((read_32bitLE(0x00,streamFile)!=0x69) && - (read_32bitLE(0x08,streamFile)!=0x48)) - goto fail; + start_offset = 0x800; + channel_count = read_32bitLE(0x04,streamFile); /* always stereo files */ + loop_flag = (read_32bitLE(0x14,streamFile) == read_32bitLE(0x24,streamFile)); + data_size = read_32bitLE(0x24,streamFile); + data_size -= (data_size / 0x20000) * 0x20; /* blocks of 0x20000 with padding */ - /* No Loop found atm */ - loop_flag = (read_32bitLE(0x14,streamFile)==read_32bitLE(0x24,streamFile)); - - /* Always stereo files */ - channel_count=read_32bitLE(0x04,streamFile); - - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x0c,streamFile); + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); + if(loop_flag) { + size_t loop_size = read_32bitLE(0x10,streamFile); + loop_size -= (loop_size / 0x20000) * 0x20; + vgmstream->loop_start_sample = xbox_ima_bytes_to_samples(loop_size, vgmstream->channels); + vgmstream->loop_end_sample = vgmstream->num_samples; + } - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = read_32bitLE(0x24,streamFile); - vgmstream->num_samples -= ((vgmstream->num_samples/0x20000)*0x20); - vgmstream->num_samples = vgmstream->num_samples / 36 * 64 / vgmstream->channels; - + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_xvas_blocked; vgmstream->meta_type = meta_XBOX_XVAS; - if(loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile); - vgmstream->loop_start_sample -= ((vgmstream->loop_start_sample/0x20000)*0x20); - vgmstream->loop_start_sample = vgmstream->loop_start_sample / 36 * 64 / vgmstream->channels; - vgmstream->loop_end_sample=vgmstream->num_samples; - } - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); - vgmstream->ch[i].offset = 0x800; + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; - if (!vgmstream->ch[i].streamfile) goto fail; - } - } - - xvas_block_update(0x800,vgmstream); + xvas_block_update(start_offset,vgmstream); return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xwav.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xwav.c index 45f55c52f..735a11203 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xwav.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xwav.c @@ -1,107 +1,91 @@ #include "meta.h" -#include "../util.h" - -/* XWAV - - XWAV use the common RIFF/WAVE format with Codec ID = 0x0069 - It has been renamed to xwav to avoid vgmstream to handle all RIFF/WAV format - known extensions : XWAV - - 2008-05-24 - Fastelbja : First version ... -*/ +#include "../coding/coding.h" +/* XWAV - renamed WAV with XBOX-IMA + * (could be parsed as RIFF/.lwav but has a custom loop chunk and multichannel) */ VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - int loop_flag=0; - int channel_count; + int loop_flag, channel_count; off_t start_offset; - int i,j=0; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xwav",filename_extension(filename))) goto fail; + /* check extension */ + if (!check_extensions(streamFile,"xwav")) + goto fail; - /* Check for headers */ - if(!((read_32bitBE(0x00,streamFile)==0x52494646) && - (read_32bitBE(0x08,streamFile)==0x57415645) && - (read_32bitBE(0x0C,streamFile)==0x666D7420) && - (read_16bitLE(0x14,streamFile)==0x0069))) - goto fail; + /* check for headers */ + if(!((read_32bitBE(0x00,streamFile) == 0x52494646) && /* "RIFF" */ + (read_32bitBE(0x08,streamFile) == 0x57415645) && /* "WAVE" */ + (read_32bitBE(0x0C,streamFile) == 0x666D7420) && /* "fmt " */ + (read_16bitLE(0x14,streamFile) == 0x0069))) /* codec */ + goto fail; - /* No loop on wavm */ - if(read_32bitBE(0x28,streamFile)==0x77736D70) - loop_flag = 1; - else - loop_flag = 0; - - /* Always stereo files */ - channel_count=read_16bitLE(0x16,streamFile); - - /* build the VGMSTREAM */ + /* loop chunk found on Koei/Omega Force games [Crimson Sea, Dynasty Warriors 5] */ + loop_flag = (read_32bitBE(0x28,streamFile) == 0x77736D70); /* "wsmp" */ + channel_count = read_16bitLE(0x16,streamFile); + + /* search for "data" */ + start_offset = 0x1C; + do { + if (read_32bitBE(start_offset,streamFile)==0x64617461) + break; + start_offset += 0x04; + } while (start_offset < (off_t)get_streamfile_size(streamFile)); + + if (start_offset >= (off_t)get_streamfile_size(streamFile)) + goto fail; + start_offset += 0x04; + + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* hack for loop wave found on Dynasty warriors */ - if(loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x4C,streamFile); - vgmstream->loop_end_sample = vgmstream->loop_start_sample + read_32bitLE(0x50,streamFile); - } - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset,streamFile), vgmstream->channels); vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x4C,streamFile); + vgmstream->loop_end_sample = vgmstream->loop_start_sample + read_32bitLE(0x50,streamFile); + } - /* search for "data" */ - start_offset=0x1C; - - do { - if(read_32bitBE(start_offset,streamFile)==0x64617461) - break; - start_offset+=4; - } while (start_offset<(off_t)get_streamfile_size(streamFile)); - - if(start_offset>=(off_t)get_streamfile_size(streamFile)) - goto fail; - - start_offset+=4; - - vgmstream->coding_type = coding_XBOX; - vgmstream->num_samples = read_32bitLE(start_offset,streamFile) / 36 * 64 / vgmstream->channels; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_XBOX_RIFF; - /* open the file for reading by each channel */ + //if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + // goto fail; + //custom init { - if(channel_count>2) { - for (i=0;iget_name(streamFile,filename,sizeof(filename)); - vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36); - vgmstream->ch[i].offset = start_offset+4; + if (channel_count > 2) { /* multichannel interleaved init */ + for (i=0, ch=0;ich[i].streamfile) goto fail; - } - } else { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); - vgmstream->ch[i].offset = start_offset+4; + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x24); + vgmstream->ch[i].offset = start_offset + 0x04; - if (!vgmstream->ch[i].streamfile) goto fail; - } - } + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + else { + for (i=0; i < channel_count; i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x24); + vgmstream->ch[i].offset = start_offset + 0x04; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } } return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xnb.c b/Frameworks/vgmstream/vgmstream/src/meta/xnb.c index c0034a71e..98aac0989 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xnb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xnb.c @@ -5,9 +5,10 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; - int loop_flag = 0, channel_count; - int flags, codec, sample_rate, block_size, bps; - size_t xnb_size, data_size; + int loop_flag = 0, channel_count, num_samples = 0, loop_start = 0, loop_end = 0; + int big_endian, flags, codec, sample_rate, block_size, bps; + size_t data_size; + char platform; /* check extension, case insensitive */ @@ -17,65 +18,78 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { /* check header */ if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */ goto fail; - /* 0x04: platform: ‘w’ = Microsoft Windows, ‘m’ = Windows Phone 7, ‘x’ = Xbox 360, 'a' = Android */ + + /* XNA Studio platforms: 'w' = Windows, 'm' = Windows Phone 7, 'x' = X360 + * MonoGame extensions: 'i' = iOS, 'a' = Android, 'X' = MacOSX, 'P': PS4, etc */ + platform = read_8bit(0x03,streamFile); + big_endian = (platform == 'x'); if (read_8bit(0x04,streamFile) != 0x05) /* XNA 4.0 version only */ goto fail; flags = read_8bit(0x05,streamFile); - if (flags & 0x80) goto fail; /* compressed with XMemCompress */ - //if (flags & 0x01) goto fail; /* XMA/big endian flag? */ + //if (flags & 0x01) goto fail; /* "HiDef profile" content (no actual difference) */ + if (flags & 0x80) goto fail; /* compressed with LZX/XMemCompress (at 0x0a is decompressed size) */ + if (flags & 0x40) goto fail; /* compressed with LZ4, MonoGame extension [ex. Square Heroes (PS4)] */ + + /* full size */ + if (read_32bitLE(0x06,streamFile) != get_streamfile_size(streamFile)) + goto fail; - /* "check for truncated XNB" (???) */ - xnb_size = read_32bitLE(0x06,streamFile); - if (get_streamfile_size(streamFile) < xnb_size) goto fail; /* XNB contains "type reader" class references to parse "shared resource" data (can be any implemented filetype) */ { char reader_name[255+1]; - off_t current_chunk = 0xa; + off_t current_offset = 0x0a; int reader_string_len; uint32_t fmt_chunk_size; const char * type_sound = "Microsoft.Xna.Framework.Content.SoundEffectReader"; /* partial "fmt" chunk or XMA */ //const char * type_song = "Microsoft.Xna.Framework.Content.SongReader"; /* just references a companion .wma */ /* type reader count, accept only one for now */ - if (read_8bit(current_chunk++, streamFile) != 1) + if (read_8bit(current_offset++, streamFile) != 1) goto fail; - reader_string_len = read_8bit(current_chunk++, streamFile); /* doesn't count null */ + reader_string_len = read_8bit(current_offset++, streamFile); /* doesn't count null */ if (reader_string_len > 255) goto fail; /* check SoundEffect type string */ - if (read_string(reader_name,reader_string_len+1,current_chunk,streamFile) != reader_string_len) + if (read_string(reader_name,reader_string_len+1,current_offset,streamFile) != reader_string_len) goto fail; if ( strcmp(reader_name, type_sound) != 0 ) goto fail; - current_chunk += reader_string_len + 1; - current_chunk += 4; /* reader version */ + current_offset += reader_string_len + 1; + current_offset += 4; /* reader version */ /* shared resource count */ - if (read_8bit(current_chunk++, streamFile) != 1) + if (read_8bit(current_offset++, streamFile) != 1) goto fail; /* shared resource: partial "fmt" chunk */ - fmt_chunk_size = read_32bitLE(current_chunk, streamFile); - current_chunk += 4; + fmt_chunk_size = read_32bitLE(current_offset, streamFile); + current_offset += 4; { - codec = read_16bitLE(current_chunk+0x00, streamFile); - channel_count = read_16bitLE(current_chunk+0x02, streamFile); - sample_rate = read_32bitLE(current_chunk+0x04, streamFile); - block_size = read_16bitLE(current_chunk+0x0c, streamFile); - bps = read_16bitLE(current_chunk+0x0e, streamFile); + int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE; + int16_t (*read_16bit)(off_t,STREAMFILE*) = big_endian ? read_16bitBE : read_16bitLE; + + codec = read_16bit(current_offset+0x00, streamFile); + channel_count = read_16bit(current_offset+0x02, streamFile); + sample_rate = read_32bit(current_offset+0x04, streamFile); + block_size = read_16bit(current_offset+0x0c, streamFile); + bps = read_16bit(current_offset+0x0e, streamFile); + + if (codec == 0x166) { + xma2_parse_fmt_chunk_extra(streamFile, current_offset, &loop_flag, &num_samples, &loop_start, &loop_end, big_endian); + } } - current_chunk += fmt_chunk_size; + current_offset += fmt_chunk_size; - data_size = read_32bitLE(current_chunk, streamFile); - current_chunk += 4; + data_size = read_32bitLE(current_offset, streamFile); + current_offset += 4; - start_offset = current_chunk; + start_offset = current_offset; } @@ -87,14 +101,14 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { vgmstream->meta_type = meta_XNB; switch (codec) { - case 0x01: + case 0x01: /* Dragon's Blade (Android) */ vgmstream->coding_type = bps == 8 ? coding_PCM8_U_int : coding_PCM16LE; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = block_size / channel_count; vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, bps); break; - case 0x02: + case 0x02: /* White Noise Online (PC) */ vgmstream->coding_type = coding_MSADPCM; vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = block_size; @@ -108,6 +122,29 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, block_size, channel_count); break; +#ifdef VGM_USE_FFMPEG + case 0x166: { /* Terraria (X360) */ + uint8_t buf[0x100]; + int32_t bytes, block_size, block_count; + + block_size = 0x10000; /* guessed */ + block_count = data_size / block_size + (data_size % block_size ? 1 : 0); + + bytes = ffmpeg_make_riff_xma2(buf,0x100, num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + if (bytes <= 0) goto fail; + + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + break; + } +#endif + default: VGM_LOG("XNB: unknown codec 0x%x\n", codec); goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c index 88335d956..383b31cc6 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -295,11 +295,11 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { } } else if (xwb.version <= XACT1_1_MAX && xwb.codec == XBOX_ADPCM) { - xwb.block_align = 0x24 * xwb.channels; - xwb.num_samples = ms_ima_bytes_to_samples(xwb.stream_size, xwb.block_align, xwb.channels); + xwb.block_align = 0x24 * xwb.channels; /* not really needed... */ + xwb.num_samples = xbox_ima_bytes_to_samples(xwb.stream_size, xwb.channels); if (xwb.loop_flag) { - xwb.loop_start_sample = ms_ima_bytes_to_samples(xwb.loop_start, xwb.block_align, xwb.channels); - xwb.loop_end_sample = ms_ima_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.block_align, xwb.channels); + xwb.loop_start_sample = xbox_ima_bytes_to_samples(xwb.loop_start, xwb.channels); + xwb.loop_end_sample = xbox_ima_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.channels); } } else if (xwb.version <= XACT2_2_MAX && xwb.codec == MS_ADPCM && xwb.loop_flag) { @@ -367,7 +367,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { break; case XBOX_ADPCM: /* Silent Hill 4 (Xbox) */ - vgmstream->coding_type = coding_XBOX; + vgmstream->coding_type = coding_XBOX_IMA; vgmstream->layout_type = layout_none; break; @@ -798,7 +798,6 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head /* get name offset */ for (i = start_sound; i < xsb.xsb_sounds_count; i++) { xsb_sound *s = &(xsb.xsb_sounds[i]); - VGM_LOG("wa=%i, sel=%i, si=%i vs ti=%i\n", s->wavebank, cfg__selected_wavebank, s->stream_index, target_stream); if (s->wavebank == cfg__selected_wavebank-1 && s->stream_index == target_stream-1){ name_offset = s->name_offset; diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.h b/Frameworks/vgmstream/vgmstream/src/streamfile.h index 4d0aba655..49818e9ca 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.h @@ -15,8 +15,11 @@ #include #include "streamtypes.h" #include "util.h" +#if defined(ANDROID) +#include +#endif -#if defined(__MSVCRT__) || defined(_MSC_VER) +#if (defined(__MSVCRT__) || defined(_MSC_VER)) && !defined(ANDROID) #include #define fseeko fseek #define ftello ftell diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 3677f6fc3..c9d883605 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -265,7 +265,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_adsc, init_vgmstream_ngc_dsp_mpds, init_vgmstream_dsp_str_ig, - init_vgmstream_psx_mgav, + init_vgmstream_ea_swvr, init_vgmstream_ngc_dsp_sth_str1, init_vgmstream_ngc_dsp_sth_str2, init_vgmstream_ngc_dsp_sth_str3, @@ -968,7 +968,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_thp_blocked: case layout_filp_blocked: case layout_blocked_ivaud: - case layout_psx_mgav_blocked: + case layout_blocked_ea_swvr: case layout_ps2_adm_blocked: case layout_dsp_bdsp_blocked: case layout_tra_blocked: @@ -1010,11 +1010,17 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_CRI_ADX_enc_8: case coding_CRI_ADX_enc_9: return (vgmstream->interleave_block_size - 2) * 2; - case coding_L5_555: - return 32; + case coding_NGC_DSP: case coding_NGC_DSP_subint: return 14; + case coding_NGC_AFC: + return 16; + case coding_NGC_DTK: + return 28; + case coding_G721: + return 1; + case coding_PCM16LE: case coding_PCM16LE_XOR_int: case coding_PCM16BE: @@ -1052,12 +1058,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_NWA5: case coding_SASSC: return 1; - case coding_NDS_IMA: - case coding_DAT4_IMA: - return (vgmstream->interleave_block_size-4)*2; - case coding_NGC_DTK: - return 28; - case coding_G721: + case coding_IMA: case coding_DVI_IMA: case coding_SNDS_IMA: @@ -1067,22 +1068,36 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_IMA_int: case coding_DVI_IMA_int: case coding_3DS_IMA: - case coding_AICA: return 2; - case coding_NGC_AFC: - return 16; + case coding_XBOX_IMA: + case coding_XBOX_IMA_int: + case coding_FSB_IMA: + return 64; + case coding_APPLE_IMA4: + return 64; + case coding_MS_IMA: + case coding_REF_IMA: + return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1; + case coding_RAD_IMA: + case coding_WWISE_IMA: + return (vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels; + case coding_NDS_IMA: + case coding_DAT4_IMA: + return (vgmstream->interleave_block_size - 0x04) * 2; + case coding_AWC_IMA: + return (0x800 - 0x04) * 2; + case coding_RAD_IMA_mono: + return 32; + + case coding_XA: case coding_PSX: case coding_PSX_badflags: case coding_PSX_bmdx: case coding_HEVAG: - case coding_XA: return 28; case coding_PSX_cfg: return (vgmstream->interleave_block_size - 1) * 2; /* decodes 1 byte into 2 bytes */ - case coding_XBOX: - case coding_XBOX_int: - case coding_FSB_IMA: - return 64; + case coding_EA_XA: case coding_EA_XA_int: case coding_EA_XA_V2: @@ -1090,24 +1105,20 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { return 28; case coding_EA_XAS: return 128; - case coding_WS: - /* only works if output sample size is 8 bit, which always is for WS ADPCM */ - return vgmstream->ws_output_size; + case coding_MSADPCM: return (vgmstream->interleave_block_size-(7-1)*vgmstream->channels)*2/vgmstream->channels; - case coding_APPLE_IMA4: - return 64; - case coding_MS_IMA: - case coding_RAD_IMA: - case coding_WWISE_IMA: - case coding_REF_IMA: - return (vgmstream->interleave_block_size-4*vgmstream->channels)*2/vgmstream->channels; - case coding_AWC_IMA: - return (0x800-4)*2; - case coding_RAD_IMA_mono: - return 32; + case coding_WS: /* only works if output sample size is 8 bit, which always is for WS ADPCM */ + return vgmstream->ws_output_size; + case coding_AICA: + return 2; case coding_NDS_PROCYON: return 30; + case coding_L5_555: + return 32; + case coding_LSF: + return 54; + #ifdef VGM_USE_G7221 case coding_G7221C: return 32000/50; @@ -1120,18 +1131,15 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { #endif #ifdef VGM_USE_FFMPEG case coding_FFmpeg: - { - ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; - if (data) { - /* must know the full block size for edge loops */ - return data->sampleBufferBlock; + if (vgmstream->codec_data) { + ffmpeg_codec_data *data = (ffmpeg_codec_data*)vgmstream->codec_data; + return data->sampleBufferBlock; /* must know the full block size for edge loops */ + } + else { + return 0; } - return 0; - } break; #endif - case coding_LSF: - return 54; case coding_MTAF: return 128*2; case coding_MTA2: @@ -1168,17 +1176,23 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_CRI_ADX_enc_8: case coding_CRI_ADX_enc_9: return vgmstream->interleave_block_size; - case coding_L5_555: - return 18; + case coding_NGC_DSP: return 0x08; case coding_NGC_DSP_subint: return 0x08 * vgmstream->channels; + case coding_NGC_AFC: + return 0x09; + case coding_NGC_DTK: + return 0x20; + case coding_G721: + return 0; + case coding_PCM16LE: case coding_PCM16LE_XOR_int: case coding_PCM16BE: case coding_PCM16_int: - return 2; + return 0x02; case coding_PCM8: case coding_PCM8_U: case coding_PCM8_int: @@ -1187,9 +1201,10 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_ULAW: case coding_ULAW_int: case coding_ALAW: - return 1; + return 0x01; case coding_PCMFLOAT: - return 4; + return 0x04; + case coding_SDX2: case coding_SDX2_int: case coding_CBD2: @@ -1200,7 +1215,14 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_NWA4: case coding_NWA5: case coding_SASSC: - return 1; + return 0x01; + + case coding_IMA: + case coding_IMA_int: + case coding_DVI_IMA: + case coding_DVI_IMA_int: + case coding_3DS_IMA: + return 0x01; case coding_MS_IMA: case coding_RAD_IMA: case coding_NDS_IMA: @@ -1212,30 +1234,28 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return 0x800; case coding_RAD_IMA_mono: return 0x14; - case coding_NGC_DTK: - return 32; - case coding_G721: case coding_SNDS_IMA: case coding_OTNS_IMA: return 0; case coding_UBI_IMA: /* variable (PCM then IMA) */ return 0; - case coding_NGC_AFC: - return 9; + case coding_XBOX_IMA: + case coding_XBOX_IMA_int: + case coding_FSB_IMA: + return 0x24; + case coding_APPLE_IMA4: + return 0x22; + + case coding_XA: + return 0x0e*vgmstream->channels; case coding_PSX: case coding_PSX_badflags: case coding_PSX_bmdx: case coding_HEVAG: - case coding_NDS_PROCYON: - return 16; + return 0x10; case coding_PSX_cfg: return vgmstream->interleave_block_size; - case coding_XA: - return 14*vgmstream->channels; - case coding_XBOX: - case coding_XBOX_int: - case coding_FSB_IMA: - return 36; + case coding_EA_XA: return 0x1E; case coding_EA_XA_int: @@ -1246,20 +1266,20 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return 0; /* variable (ADPCM frames of 0x0f or PCM frames of 0x3d) */ case coding_EA_XAS: return 0x4c*vgmstream->channels; + + case coding_MSADPCM: + return vgmstream->interleave_block_size; case coding_WS: return vgmstream->current_block_size; - case coding_IMA: - case coding_IMA_int: - case coding_DVI_IMA: - case coding_DVI_IMA_int: - case coding_3DS_IMA: - return 0x01; case coding_AICA: - return 1; - case coding_APPLE_IMA4: - return 34; + return 0x01; + case coding_NDS_PROCYON: + return 0x10; + case coding_L5_555: + return 0x12; case coding_LSF: - return 28; + return 0x1C; + #ifdef VGM_USE_G7221 case coding_G7221C: case coding_G7221: @@ -1273,7 +1293,6 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { #ifdef VGM_USE_FFMPEG case coding_FFmpeg: #endif - case coding_MSADPCM: case coding_MTAF: return vgmstream->interleave_block_size; case coding_MTA2: @@ -1286,7 +1305,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_ATRAC9: return 0; /* varies with config data, usually 0x100-200 */ #endif - default: + default: /* Vorbis, MPEG, ACM, etc */ return 0; } } @@ -1475,14 +1494,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; - case coding_XBOX: + case coding_XBOX_IMA: for (chan=0;chanchannels;chan++) { decode_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, samples_to_do,chan); } break; - case coding_XBOX_int: + case coding_XBOX_IMA_int: for (chan=0;chanchannels;chan++) { decode_xbox_ima_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index c8131ad90..d498196bc 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -134,8 +134,8 @@ typedef enum { coding_DVI_IMA_int, /* DVI IMA ADPCM (mono/interleave, high nibble first) */ coding_3DS_IMA, /* 3DS IMA ADPCM */ coding_MS_IMA, /* Microsoft IMA ADPCM */ - coding_XBOX, /* XBOX IMA ADPCM */ - coding_XBOX_int, /* XBOX IMA ADPCM (interleaved) */ + coding_XBOX_IMA, /* XBOX IMA ADPCM */ + coding_XBOX_IMA_int, /* XBOX IMA ADPCM (interleaved/mono) */ coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */ coding_RAD_IMA, /* Radical IMA ADPCM */ @@ -244,7 +244,7 @@ typedef enum { layout_gsb_blocked, layout_thp_blocked, layout_filp_blocked, - layout_psx_mgav_blocked, + layout_blocked_ea_swvr, layout_ps2_adm_blocked, layout_dsp_bdsp_blocked, layout_mxch_blocked, @@ -551,7 +551,7 @@ typedef enum { meta_DSP_DDSP, /* Various (2 dsp files stuck together */ meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */ meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */ - meta_PSX_MGAV, /* Future Cop L.A.P.D. */ + meta_EA_SWVR, /* Future Cop L.A.P.D., Freekstyle */ meta_NGC_DSP_STH_STR, /* SpongeBob Squarepants (NGC), Taz Wanted (NGC), Cubix (NGC), Tak (WII)*/ meta_PS2_B1S, /* 7 Wonders of the ancient world */ meta_PS2_WAD, /* The golden Compass */ @@ -666,6 +666,7 @@ typedef enum { meta_XWC, /* Starbreeze games */ meta_SQEX_SAB, /* Square-Enix newest middleware (sound) */ meta_SQEX_MAB, /* Square-Enix newest middleware (music) */ + meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */ #ifdef VGM_USE_MP4V2 meta_MP4, /* AAC (iOS) */