From 16e0a006f221335d71d377fa2ad1f6a48ebabb03 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sat, 16 Dec 2017 20:17:41 -0800 Subject: [PATCH] Updated VGMStream to r1050-866-g5cc215b4. --- .../vgmstream.xcodeproj/project.pbxproj | 192 ++-- .../vgmstream/vgmstream/src/coding/coding.h | 40 +- .../vgmstream/src/coding/coding_utils.c | 146 +++ .../vgmstream/src/coding/ea_mt_decoder.c | 577 ++++++++++++ .../vgmstream/src/coding/ea_xa_decoder.c | 163 ++-- .../vgmstream/src/coding/ffmpeg_decoder.c | 9 + .../src/coding/ffmpeg_decoder_utils.c | 4 +- .../src/coding/ffmpeg_decoder_utils.h | 4 + .../coding/ffmpeg_decoder_utils_bgw_atrac3.c | 58 ++ .../src/coding/ffmpeg_decoder_utils_ea_xma.c | 14 +- .../coding/ffmpeg_decoder_utils_switch_opus.c | 11 +- .../vgmstream/src/coding/g719_decoder.c | 25 + .../vgmstream/src/coding/g721_decoder.c | 12 +- .../vgmstream/src/coding/g7221_decoder.c | 26 + .../vgmstream/src/coding/ima_decoder.c | 838 +++++++++-------- .../vgmstream/src/coding/mpeg_custom_utils.c | 20 +- .../src/coding/mpeg_custom_utils_ahx.c | 29 +- .../src/coding/mpeg_custom_utils_awc.c | 2 +- .../src/coding/mpeg_custom_utils_ealayer3.c | 409 ++++---- .../vgmstream/src/coding/mpeg_decoder.c | 86 +- .../vgmstream/src/coding/mpeg_decoder.h | 5 +- .../vgmstream/src/coding/ngc_dsp_decoder.c | 29 +- .../src/coding/vorbis_custom_decoder.c | 9 +- .../src/coding/vorbis_custom_decoder.h | 3 + .../src/coding/vorbis_custom_utils_vid1.c | 152 +++ .../src/coding/vorbis_custom_utils_wwise.c | 115 +-- .../vgmstream/src/coding/xa_decoder.c | 30 +- Frameworks/vgmstream/vgmstream/src/formats.c | 200 ++-- Frameworks/vgmstream/vgmstream/src/formats.h | 19 - .../vgmstream/vgmstream/src/layout/blocked.c | 142 +-- .../vgmstream/src/layout/blocked_dec.c | 21 + .../vgmstream/src/layout/blocked_ea_1snh.c | 83 ++ .../layout/{ea_block.c => blocked_ea_schl.c} | 75 +- .../{ea_sns_blocked.c => blocked_ea_sns.c} | 16 +- .../{ivaud_layout.c => blocked_ivaud.c} | 2 +- .../vgmstream/src/layout/blocked_vawx.c | 25 + .../vgmstream/src/layout/de2_blocked.c | 18 - .../vgmstream/src/layout/interleave_byte.c | 62 -- .../vgmstream/vgmstream/src/layout/layout.h | 19 +- .../vgmstream/src/layout/str_snds_blocked.c | 4 +- .../vgmstream/src/layout/thp_blocked.c | 4 +- .../vgmstream/src/layout/xa_blocked.c | 93 +- .../vgmstream/vgmstream/src/meta/Cstr.c | 3 +- Frameworks/vgmstream/vgmstream/src/meta/aax.c | 109 +-- .../vgmstream/src/meta/aax_streamfile.h | 87 ++ Frameworks/vgmstream/vgmstream/src/meta/adx.c | 303 +----- .../vgmstream/vgmstream/src/meta/adx_keys.h | 330 +++++++ .../src/meta/{afc_header.c => afc.c} | 0 .../vgmstream/vgmstream/src/meta/aifc.c | 6 +- Frameworks/vgmstream/vgmstream/src/meta/aix.c | 206 +--- .../vgmstream/src/meta/aix_streamfile.h | 169 ++++ Frameworks/vgmstream/vgmstream/src/meta/awc.c | 7 +- Frameworks/vgmstream/vgmstream/src/meta/bar.c | 77 ++ .../vgmstream/src/meta/bar_streamfile.h | 100 ++ .../vgmstream/vgmstream/src/meta/bcstm.c | 290 +++--- Frameworks/vgmstream/vgmstream/src/meta/bgw.c | 67 +- .../vgmstream/vgmstream/src/meta/bnsf.c | 265 ++---- .../vgmstream/vgmstream/src/meta/dc_idvi.c | 55 +- .../vgmstream/vgmstream/src/meta/dc_kcey.c | 61 +- Frameworks/vgmstream/vgmstream/src/meta/de2.c | 101 -- Frameworks/vgmstream/vgmstream/src/meta/dec.c | 183 ++++ .../vgmstream/vgmstream/src/meta/ea_1snh.c | 173 ++++ .../vgmstream/vgmstream/src/meta/ea_eaac.c | 254 +++++ .../vgmstream/vgmstream/src/meta/ea_old.c | 160 ---- .../vgmstream/vgmstream/src/meta/ea_schl.c | 29 +- .../vgmstream/src/meta/ea_schl_fixed.c | 6 +- .../vgmstream/vgmstream/src/meta/ea_snu.c | 165 ---- Frameworks/vgmstream/vgmstream/src/meta/ezw.c | 41 + Frameworks/vgmstream/vgmstream/src/meta/flx.c | 107 +++ Frameworks/vgmstream/vgmstream/src/meta/fsb.c | 9 +- .../vgmstream/vgmstream/src/meta/fsb5.c | 39 +- Frameworks/vgmstream/vgmstream/src/meta/g1l.c | 13 +- .../vgmstream/vgmstream/src/meta/genh.c | 281 +++--- .../vgmstream/vgmstream/src/meta/gh3_bar.c | 182 ---- Frameworks/vgmstream/vgmstream/src/meta/hca.c | 3 +- .../vgmstream/vgmstream/src/meta/hca_keys.h | 43 +- .../vgmstream/vgmstream/src/meta/ivaud.c | 4 +- .../vgmstream/vgmstream/src/meta/maxis_xa.c | 16 +- .../vgmstream/vgmstream/src/meta/meta.h | 60 +- .../vgmstream/vgmstream/src/meta/mn_str.c | 3 + .../vgmstream/vgmstream/src/meta/mogg.c | 42 + .../vgmstream/vgmstream/src/meta/mus_acm.c | 10 +- .../vgmstream/vgmstream/src/meta/myspd.c | 47 +- .../vgmstream/vgmstream/src/meta/naac.c | 66 ++ .../vgmstream/vgmstream/src/meta/nds_hwas.c | 4 +- .../vgmstream/vgmstream/src/meta/nds_rrds.c | 4 +- .../vgmstream/vgmstream/src/meta/nds_strm.c | 8 +- .../vgmstream/src/meta/nds_strm_ffta2.c | 16 +- .../vgmstream/src/meta/ngc_dsp_std.c | 29 +- .../vgmstream/src/meta/ngc_dsp_ygo.c | 38 +- .../vgmstream/src/meta/ngc_sck_dsp.c | 66 +- .../vgmstream/vgmstream/src/meta/ngc_vid1.c | 75 ++ .../vgmstream/vgmstream/src/meta/nsw_opus.c | 46 +- Frameworks/vgmstream/vgmstream/src/meta/omu.c | 45 + .../vgmstream/vgmstream/src/meta/pc_adp.c | 45 +- .../vgmstream/src/meta/pc_adp_otns.c | 43 + .../vgmstream/vgmstream/src/meta/pc_ast.c | 44 + .../vgmstream/vgmstream/src/meta/pc_sob.c | 82 -- Frameworks/vgmstream/vgmstream/src/meta/pcm.c | 128 --- .../vgmstream/vgmstream/src/meta/ps2_ads.c | 216 ++--- .../vgmstream/vgmstream/src/meta/ps2_filp.c | 26 +- .../vgmstream/vgmstream/src/meta/ps2_gcm.c | 10 +- .../vgmstream/vgmstream/src/meta/ps2_hsf.c | 80 +- .../vgmstream/vgmstream/src/meta/ps2_ild.c | 30 +- .../vgmstream/vgmstream/src/meta/ps2_int.c | 58 +- .../vgmstream/vgmstream/src/meta/ps2_mcg.c | 26 +- .../vgmstream/vgmstream/src/meta/ps2_mihb.c | 14 +- .../vgmstream/vgmstream/src/meta/ps2_npsf.c | 14 +- .../vgmstream/vgmstream/src/meta/ps2_pcm.c | 48 + .../vgmstream/vgmstream/src/meta/ps2_rstm.c | 48 +- .../vgmstream/vgmstream/src/meta/ps2_rxws.c | 20 +- .../vgmstream/vgmstream/src/meta/ps2_smpl.c | 61 +- .../vgmstream/vgmstream/src/meta/ps2_tk5.c | 52 +- .../vgmstream/vgmstream/src/meta/ps2_vag.c | 28 +- .../vgmstream/vgmstream/src/meta/ps2_vgs.c | 120 +-- .../vgmstream/vgmstream/src/meta/ps2_vms.c | 30 +- .../vgmstream/vgmstream/src/meta/ps2_vpk.c | 30 +- .../vgmstream/vgmstream/src/meta/ps2_xa2.c | 58 -- .../vgmstream/src/meta/ps2_xa2_rrp.c | 59 ++ .../vgmstream/vgmstream/src/meta/ps3_ivag.c | 54 +- .../vgmstream/vgmstream/src/meta/ps3_klbs.c | 122 +-- .../vgmstream/vgmstream/src/meta/ps3_msf.c | 4 +- .../vgmstream/vgmstream/src/meta/psx_cdxa.c | 193 ++-- .../vgmstream/vgmstream/src/meta/psx_fag.c | 18 +- .../vgmstream/vgmstream/src/meta/riff.c | 42 +- Frameworks/vgmstream/vgmstream/src/meta/rsd.c | 54 +- .../vgmstream/vgmstream/src/meta/rwsd.c | 4 +- .../vgmstream/vgmstream/src/meta/s14_sss.c | 119 +-- Frameworks/vgmstream/vgmstream/src/meta/sab.c | 157 ++++ .../vgmstream/vgmstream/src/meta/sat_dvi.c | 69 +- .../vgmstream/vgmstream/src/meta/scd_pcm.c | 63 ++ Frameworks/vgmstream/vgmstream/src/meta/sli.c | 2 +- .../vgmstream/vgmstream/src/meta/sqex_scd.c | 428 +++------ .../vgmstream/src/meta/sqex_scd_streamfile.h | 134 +++ .../vgmstream/vgmstream/src/meta/ss_stream.c | 203 ---- .../vgmstream/vgmstream/src/meta/ta_aac.c | 248 ++--- Frameworks/vgmstream/vgmstream/src/meta/thp.c | 102 +- Frameworks/vgmstream/vgmstream/src/meta/tun.c | 49 +- .../vgmstream/vgmstream/src/meta/txth.c | 132 +-- .../vgmstream/vgmstream/src/meta/ubi_raki.c | 7 +- .../vgmstream/vgmstream/src/meta/ubi_sb.c | 889 ++++++++++++++++++ .../vgmstream/vgmstream/src/meta/vawx.c | 7 +- Frameworks/vgmstream/vgmstream/src/meta/vsf.c | 64 -- .../vgmstream/vgmstream/src/meta/vsf_tta.c | 66 ++ Frameworks/vgmstream/vgmstream/src/meta/vxn.c | 109 +++ Frameworks/vgmstream/vgmstream/src/meta/wpd.c | 6 +- .../vgmstream/vgmstream/src/meta/ws_aud.c | 2 +- .../vgmstream/vgmstream/src/meta/wwise.c | 46 +- .../vgmstream/vgmstream/src/meta/x360_tra.c | 2 +- Frameworks/vgmstream/vgmstream/src/meta/xwb.c | 77 +- .../vgmstream/vgmstream/src/streamfile.c | 107 +-- .../vgmstream/vgmstream/src/streamfile.h | 3 +- Frameworks/vgmstream/vgmstream/src/util.c | 7 +- Frameworks/vgmstream/vgmstream/src/util.h | 24 +- .../vgmstream/vgmstream/src/vgmstream.c | 815 ++++++++-------- .../vgmstream/vgmstream/src/vgmstream.h | 257 +++-- Plugins/vgmstream/vgmstream/VGMDecoder.m | 6 +- 157 files changed, 8449 insertions(+), 5906 deletions(-) create mode 100644 Frameworks/vgmstream/vgmstream/src/coding/ea_mt_decoder.c create mode 100644 Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_bgw_atrac3.c create mode 100644 Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/formats.h create mode 100644 Frameworks/vgmstream/vgmstream/src/layout/blocked_dec.c create mode 100644 Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c rename Frameworks/vgmstream/vgmstream/src/layout/{ea_block.c => blocked_ea_schl.c} (73%) rename Frameworks/vgmstream/vgmstream/src/layout/{ea_sns_blocked.c => blocked_ea_sns.c} (65%) rename Frameworks/vgmstream/vgmstream/src/layout/{ivaud_layout.c => blocked_ivaud.c} (92%) create mode 100644 Frameworks/vgmstream/vgmstream/src/layout/blocked_vawx.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/layout/de2_blocked.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/layout/interleave_byte.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/aax_streamfile.h create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/adx_keys.h rename Frameworks/vgmstream/vgmstream/src/meta/{afc_header.c => afc.c} (100%) create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/bar.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/de2.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/dec.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ea_old.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ea_snu.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ezw.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/flx.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/gh3_bar.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/mogg.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/naac.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ngc_vid1.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/omu.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/pc_adp_otns.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/pc_ast.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/pc_sob.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/pcm.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ps2_pcm.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2_rrp.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/sab.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/scd_pcm.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ss_stream.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/vsf_tta.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/vxn.c diff --git a/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj index 6e02f3528..8796b0c67 100644 --- a/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj @@ -37,6 +37,40 @@ 83345A511F8AEB2800B2EAA4 /* nsw_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */; }; 83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4E1F8AEB2800B2EAA4 /* xvag.c */; }; 833A7A2E1ED11961003EC53E /* xau.c in Sources */ = {isa = PBXBuildFile; fileRef = 833A7A2D1ED11961003EC53E /* xau.c */; }; + 8349A8DF1FE6251F00E26435 /* vorbis_custom_utils_vid1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8DC1FE6251E00E26435 /* vorbis_custom_utils_vid1.c */; }; + 8349A8E01FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8DD1FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c */; }; + 8349A8E11FE6251F00E26435 /* ea_mt_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8DE1FE6251F00E26435 /* ea_mt_decoder.c */; }; + 8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E21FE6253800E26435 /* blocked_dec.c */; }; + 8349A8E91FE6253900E26435 /* blocked_ea_1snh.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */; }; + 8349A8EA1FE6253900E26435 /* blocked_ea_schl.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E41FE6253800E26435 /* blocked_ea_schl.c */; }; + 8349A8EB1FE6253900E26435 /* blocked_ivaud.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E51FE6253800E26435 /* blocked_ivaud.c */; }; + 8349A8EC1FE6253900E26435 /* blocked_vawx.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E61FE6253900E26435 /* blocked_vawx.c */; }; + 8349A8ED1FE6253900E26435 /* blocked_ea_sns.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E71FE6253900E26435 /* blocked_ea_sns.c */; }; + 8349A9071FE6258200E26435 /* dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8EE1FE6257C00E26435 /* dec.c */; }; + 8349A9081FE6258200E26435 /* ezw.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8EF1FE6257C00E26435 /* ezw.c */; }; + 8349A9091FE6258200E26435 /* pc_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F01FE6257C00E26435 /* pc_ast.c */; }; + 8349A90A1FE6258200E26435 /* sab.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F11FE6257D00E26435 /* sab.c */; }; + 8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F21FE6257D00E26435 /* ps2_pcm.c */; }; + 8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */; }; + 8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F41FE6257D00E26435 /* ubi_sb.c */; }; + 8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F51FE6257D00E26435 /* scd_pcm.c */; }; + 8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F61FE6257E00E26435 /* aix_streamfile.h */; }; + 8349A9101FE6258200E26435 /* ea_eaac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F71FE6257E00E26435 /* ea_eaac.c */; }; + 8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F81FE6257E00E26435 /* bar_streamfile.h */; }; + 8349A9121FE6258200E26435 /* vsf_tta.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F91FE6257E00E26435 /* vsf_tta.c */; }; + 8349A9131FE6258200E26435 /* ngc_vid1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FA1FE6257E00E26435 /* ngc_vid1.c */; }; + 8349A9141FE6258200E26435 /* omu.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FB1FE6257F00E26435 /* omu.c */; }; + 8349A9151FE6258200E26435 /* ps2_xa2_rrp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FC1FE6257F00E26435 /* ps2_xa2_rrp.c */; }; + 8349A9161FE6258200E26435 /* flx.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FD1FE6257F00E26435 /* flx.c */; }; + 8349A9171FE6258200E26435 /* pc_adp_otns.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */; }; + 8349A9181FE6258200E26435 /* ea_1snh.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FF1FE6258000E26435 /* ea_1snh.c */; }; + 8349A9191FE6258200E26435 /* afc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9001FE6258000E26435 /* afc.c */; }; + 8349A91A1FE6258200E26435 /* vxn.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9011FE6258000E26435 /* vxn.c */; }; + 8349A91B1FE6258200E26435 /* adx_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A9021FE6258100E26435 /* adx_keys.h */; }; + 8349A91C1FE6258200E26435 /* mogg.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9031FE6258100E26435 /* mogg.c */; }; + 8349A91D1FE6258200E26435 /* aax_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A9041FE6258100E26435 /* aax_streamfile.h */; }; + 8349A91E1FE6258200E26435 /* bar.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9051FE6258100E26435 /* bar.c */; }; + 8349A91F1FE6258200E26435 /* naac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9061FE6258100E26435 /* naac.c */; }; 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */ = {isa = PBXBuildFile; fileRef = 834D3A6D19F47C98001C54F6 /* g1l.c */; }; 8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8350270C1ED119D200C25929 /* ps3_mta2.c */; }; 835027131ED119E000C25929 /* mta2_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 835027121ED119E000C25929 /* mta2_decoder.c */; }; @@ -78,16 +112,12 @@ 836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0318BDC2180095E648 /* bdsp_blocked.c */; }; 836F6F4118BDC2190095E648 /* blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0418BDC2180095E648 /* blocked.c */; }; 836F6F4218BDC2190095E648 /* caf_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0518BDC2180095E648 /* caf_blocked.c */; }; - 836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0618BDC2180095E648 /* de2_blocked.c */; }; - 836F6F4418BDC2190095E648 /* ea_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0718BDC2180095E648 /* ea_block.c */; }; 836F6F4518BDC2190095E648 /* emff_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0818BDC2180095E648 /* emff_blocked.c */; }; 836F6F4618BDC2190095E648 /* filp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0918BDC2180095E648 /* filp_blocked.c */; }; 836F6F4718BDC2190095E648 /* gsb_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0A18BDC2180095E648 /* gsb_blocked.c */; }; 836F6F4818BDC2190095E648 /* halpst_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0B18BDC2180095E648 /* halpst_blocked.c */; }; 836F6F4918BDC2190095E648 /* ims_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0C18BDC2180095E648 /* ims_block.c */; }; 836F6F4A18BDC2190095E648 /* interleave.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0D18BDC2180095E648 /* interleave.c */; }; - 836F6F4B18BDC2190095E648 /* interleave_byte.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0E18BDC2180095E648 /* interleave_byte.c */; }; - 836F6F4C18BDC2190095E648 /* ivaud_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0F18BDC2180095E648 /* ivaud_layout.c */; }; 836F6F4D18BDC2190095E648 /* layout.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6E1018BDC2180095E648 /* layout.h */; }; 836F6F4F18BDC2190095E648 /* mus_acm_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1218BDC2180095E648 /* mus_acm_layout.c */; }; 836F6F5018BDC2190095E648 /* mxch_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1318BDC2180095E648 /* mxch_blocked.c */; }; @@ -109,7 +139,6 @@ 836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; }; 836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; }; 836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.c */; }; - 836F6F6A18BDC2190095E648 /* afc_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2E18BDC2180095E648 /* afc_header.c */; }; 836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; }; 836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; }; 836F6F6D18BDC2190095E648 /* aifc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3118BDC2180095E648 /* aifc.c */; }; @@ -129,12 +158,10 @@ 836F6F7B18BDC2190095E648 /* dc_idvi.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3F18BDC2180095E648 /* dc_idvi.c */; }; 836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4018BDC2180095E648 /* dc_kcey.c */; }; 836F6F7D18BDC2190095E648 /* dc_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4118BDC2180095E648 /* dc_str.c */; }; - 836F6F7E18BDC2190095E648 /* de2.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4218BDC2180095E648 /* de2.c */; }; 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4318BDC2180095E648 /* dmsg_segh.c */; }; 836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4418BDC2180095E648 /* dsp_bdsp.c */; }; 836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4518BDC2180095E648 /* dsp_sth_str.c */; }; 836F6F8218BDC2190095E648 /* ea_schl.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4618BDC2180095E648 /* ea_schl.c */; }; - 836F6F8318BDC2190095E648 /* ea_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4718BDC2180095E648 /* ea_old.c */; }; 836F6F8418BDC2190095E648 /* emff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4818BDC2180095E648 /* emff.c */; }; 836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4918BDC2180095E648 /* exakt_sc.c */; }; 836F6F8618BDC2190095E648 /* excitebots.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4A18BDC2180095E648 /* excitebots.c */; }; @@ -143,7 +170,6 @@ 836F6F8918BDC2190095E648 /* gca.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4D18BDC2180095E648 /* gca.c */; }; 836F6F8A18BDC2190095E648 /* gcsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4E18BDC2180095E648 /* gcsw.c */; }; 836F6F8B18BDC2190095E648 /* genh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4F18BDC2180095E648 /* genh.c */; }; - 836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5018BDC2180095E648 /* gh3_bar.c */; }; 836F6F8D18BDC2190095E648 /* gsp_gsb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5118BDC2180095E648 /* gsp_gsb.c */; }; 836F6F8E18BDC2190095E648 /* halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5218BDC2180095E648 /* halpst.c */; }; 836F6F8F18BDC2190095E648 /* his.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5318BDC2180095E648 /* his.c */; }; @@ -197,8 +223,6 @@ 836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8618BDC2180095E648 /* pc_mxst.c */; }; 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8718BDC2180095E648 /* pc_smp.c */; }; 836F6FC418BDC2190095E648 /* pc_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8818BDC2180095E648 /* pc_snds.c */; }; - 836F6FC518BDC2190095E648 /* pc_sob.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8918BDC2180095E648 /* pc_sob.c */; }; - 836F6FC618BDC2190095E648 /* pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8A18BDC2180095E648 /* pcm.c */; }; 836F6FC718BDC2190095E648 /* pona.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8B18BDC2180095E648 /* pona.c */; }; 836F6FC818BDC2190095E648 /* pos.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8C18BDC2180095E648 /* pos.c */; }; 836F6FC918BDC2190095E648 /* ps2_2pfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */; }; @@ -298,7 +322,6 @@ 836F702E18BDC2190095E648 /* sli.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF218BDC2190095E648 /* sli.c */; }; 836F702F18BDC2190095E648 /* spt_spd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF318BDC2190095E648 /* spt_spd.c */; }; 836F703018BDC2190095E648 /* sqex_scd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF418BDC2190095E648 /* sqex_scd.c */; }; - 836F703118BDC2190095E648 /* ss_stream.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF518BDC2190095E648 /* ss_stream.c */; }; 836F703218BDC2190095E648 /* str_asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF618BDC2190095E648 /* str_asr.c */; }; 836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; }; 836F703418BDC2190095E648 /* stx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF818BDC2190095E648 /* stx.c */; }; @@ -378,7 +401,6 @@ 839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21DF1F2EDAF000EE54D7 /* vorbis_custom_utils_sk.c */; }; 839E21EB1F2EDB0600EE54D7 /* sk_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */; }; 83A3F0741E3AD8B900D6A794 /* formats.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F0711E3AD8B900D6A794 /* formats.c */; }; - 83A3F0751E3AD8B900D6A794 /* formats.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0721E3AD8B900D6A794 /* formats.h */; settings = {ATTRIBUTES = (Public, ); }; }; 83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */; }; 83A5F75F198DF021009AF94C /* bfwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A5F75E198DF021009AF94C /* bfwav.c */; }; 83AA5D161F6E2F600020821C /* ea_xa_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */; }; @@ -387,10 +409,8 @@ 83AA5D191F6E2F600020821C /* ea_xas_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D151F6E2F600020821C /* ea_xas_decoder.c */; }; 83AA5D1D1F6E2F800020821C /* blocked_vgs.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */; }; 83AA5D1E1F6E2F800020821C /* blocked_awc.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */; }; - 83AA5D1F1F6E2F800020821C /* ea_sns_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D1C1F6E2F7F0020821C /* ea_sns_blocked.c */; }; 83AA5D241F6E2F9C0020821C /* awc.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D201F6E2F9B0020821C /* awc.c */; }; 83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AA5D211F6E2F9C0020821C /* hca_keys.h */; }; - 83AA5D261F6E2F9C0020821C /* ea_snu.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D221F6E2F9C0020821C /* ea_snu.c */; }; 83AA5D271F6E2F9C0020821C /* stm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D231F6E2F9C0020821C /* stm.c */; }; 83AB8C751E8072A100086084 /* nub_vag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C731E8072A100086084 /* nub_vag.c */; }; 83AB8C761E8072A100086084 /* x360_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C741E8072A100086084 /* x360_ast.c */; }; @@ -543,6 +563,40 @@ 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nsw_opus.c; sourceTree = ""; }; 83345A4E1F8AEB2800B2EAA4 /* xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xvag.c; sourceTree = ""; }; 833A7A2D1ED11961003EC53E /* xau.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xau.c; sourceTree = ""; }; + 8349A8DC1FE6251E00E26435 /* vorbis_custom_utils_vid1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_vid1.c; sourceTree = ""; }; + 8349A8DD1FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils_bgw_atrac3.c; sourceTree = ""; }; + 8349A8DE1FE6251F00E26435 /* ea_mt_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_mt_decoder.c; sourceTree = ""; }; + 8349A8E21FE6253800E26435 /* blocked_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_dec.c; sourceTree = ""; }; + 8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_1snh.c; sourceTree = ""; }; + 8349A8E41FE6253800E26435 /* blocked_ea_schl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_schl.c; sourceTree = ""; }; + 8349A8E51FE6253800E26435 /* blocked_ivaud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ivaud.c; sourceTree = ""; }; + 8349A8E61FE6253900E26435 /* blocked_vawx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_vawx.c; sourceTree = ""; }; + 8349A8E71FE6253900E26435 /* blocked_ea_sns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_sns.c; sourceTree = ""; }; + 8349A8EE1FE6257C00E26435 /* dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dec.c; sourceTree = ""; }; + 8349A8EF1FE6257C00E26435 /* ezw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ezw.c; sourceTree = ""; }; + 8349A8F01FE6257C00E26435 /* pc_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_ast.c; sourceTree = ""; }; + 8349A8F11FE6257D00E26435 /* sab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sab.c; sourceTree = ""; }; + 8349A8F21FE6257D00E26435 /* ps2_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_pcm.c; sourceTree = ""; }; + 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqex_scd_streamfile.h; sourceTree = ""; }; + 8349A8F41FE6257D00E26435 /* ubi_sb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_sb.c; sourceTree = ""; }; + 8349A8F51FE6257D00E26435 /* scd_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_pcm.c; sourceTree = ""; }; + 8349A8F61FE6257E00E26435 /* aix_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aix_streamfile.h; sourceTree = ""; }; + 8349A8F71FE6257E00E26435 /* ea_eaac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_eaac.c; sourceTree = ""; }; + 8349A8F81FE6257E00E26435 /* bar_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bar_streamfile.h; sourceTree = ""; }; + 8349A8F91FE6257E00E26435 /* vsf_tta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vsf_tta.c; sourceTree = ""; }; + 8349A8FA1FE6257E00E26435 /* ngc_vid1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_vid1.c; sourceTree = ""; }; + 8349A8FB1FE6257F00E26435 /* omu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = omu.c; sourceTree = ""; }; + 8349A8FC1FE6257F00E26435 /* ps2_xa2_rrp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xa2_rrp.c; sourceTree = ""; }; + 8349A8FD1FE6257F00E26435 /* flx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = flx.c; sourceTree = ""; }; + 8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_adp_otns.c; sourceTree = ""; }; + 8349A8FF1FE6258000E26435 /* ea_1snh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_1snh.c; sourceTree = ""; }; + 8349A9001FE6258000E26435 /* afc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = afc.c; sourceTree = ""; }; + 8349A9011FE6258000E26435 /* vxn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vxn.c; sourceTree = ""; }; + 8349A9021FE6258100E26435 /* adx_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adx_keys.h; sourceTree = ""; }; + 8349A9031FE6258100E26435 /* mogg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mogg.c; sourceTree = ""; }; + 8349A9041FE6258100E26435 /* aax_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aax_streamfile.h; sourceTree = ""; }; + 8349A9051FE6258100E26435 /* bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; + 8349A9061FE6258100E26435 /* naac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naac.c; sourceTree = ""; }; 834D3A6D19F47C98001C54F6 /* g1l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g1l.c; sourceTree = ""; }; 8350270C1ED119D200C25929 /* ps3_mta2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_mta2.c; sourceTree = ""; }; 835027121ED119E000C25929 /* mta2_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mta2_decoder.c; sourceTree = ""; }; @@ -586,16 +640,12 @@ 836F6E0318BDC2180095E648 /* bdsp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdsp_blocked.c; sourceTree = ""; }; 836F6E0418BDC2180095E648 /* blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked.c; sourceTree = ""; }; 836F6E0518BDC2180095E648 /* caf_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = caf_blocked.c; sourceTree = ""; }; - 836F6E0618BDC2180095E648 /* de2_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = de2_blocked.c; sourceTree = ""; }; - 836F6E0718BDC2180095E648 /* ea_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_block.c; sourceTree = ""; }; 836F6E0818BDC2180095E648 /* emff_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff_blocked.c; sourceTree = ""; }; 836F6E0918BDC2180095E648 /* filp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filp_blocked.c; sourceTree = ""; }; 836F6E0A18BDC2180095E648 /* gsb_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsb_blocked.c; sourceTree = ""; }; 836F6E0B18BDC2180095E648 /* halpst_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst_blocked.c; sourceTree = ""; }; 836F6E0C18BDC2180095E648 /* ims_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ims_block.c; sourceTree = ""; }; 836F6E0D18BDC2180095E648 /* interleave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interleave.c; sourceTree = ""; }; - 836F6E0E18BDC2180095E648 /* interleave_byte.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interleave_byte.c; sourceTree = ""; }; - 836F6E0F18BDC2180095E648 /* ivaud_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivaud_layout.c; sourceTree = ""; }; 836F6E1018BDC2180095E648 /* layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = layout.h; sourceTree = ""; }; 836F6E1218BDC2180095E648 /* mus_acm_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mus_acm_layout.c; sourceTree = ""; }; 836F6E1318BDC2180095E648 /* mxch_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mxch_blocked.c; sourceTree = ""; }; @@ -617,7 +667,6 @@ 836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = ""; }; 836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = ""; }; 836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = ""; }; - 836F6E2E18BDC2180095E648 /* afc_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = afc_header.c; sourceTree = ""; }; 836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = ""; }; 836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = ""; }; 836F6E3118BDC2180095E648 /* aifc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aifc.c; sourceTree = ""; }; @@ -637,12 +686,10 @@ 836F6E3F18BDC2180095E648 /* dc_idvi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_idvi.c; sourceTree = ""; }; 836F6E4018BDC2180095E648 /* dc_kcey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_kcey.c; sourceTree = ""; }; 836F6E4118BDC2180095E648 /* dc_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_str.c; sourceTree = ""; }; - 836F6E4218BDC2180095E648 /* de2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = de2.c; sourceTree = ""; }; 836F6E4318BDC2180095E648 /* dmsg_segh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dmsg_segh.c; sourceTree = ""; }; 836F6E4418BDC2180095E648 /* dsp_bdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_bdsp.c; sourceTree = ""; }; 836F6E4518BDC2180095E648 /* dsp_sth_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_sth_str.c; sourceTree = ""; }; 836F6E4618BDC2180095E648 /* ea_schl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_schl.c; sourceTree = ""; }; - 836F6E4718BDC2180095E648 /* ea_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_old.c; sourceTree = ""; }; 836F6E4818BDC2180095E648 /* emff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff.c; sourceTree = ""; }; 836F6E4918BDC2180095E648 /* exakt_sc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exakt_sc.c; sourceTree = ""; }; 836F6E4A18BDC2180095E648 /* excitebots.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = excitebots.c; sourceTree = ""; }; @@ -651,7 +698,6 @@ 836F6E4D18BDC2180095E648 /* gca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gca.c; sourceTree = ""; }; 836F6E4E18BDC2180095E648 /* gcsw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gcsw.c; sourceTree = ""; }; 836F6E4F18BDC2180095E648 /* genh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = genh.c; sourceTree = ""; }; - 836F6E5018BDC2180095E648 /* gh3_bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gh3_bar.c; sourceTree = ""; }; 836F6E5118BDC2180095E648 /* gsp_gsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsp_gsb.c; sourceTree = ""; }; 836F6E5218BDC2180095E648 /* halpst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst.c; sourceTree = ""; }; 836F6E5318BDC2180095E648 /* his.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = his.c; sourceTree = ""; }; @@ -705,8 +751,6 @@ 836F6E8618BDC2180095E648 /* pc_mxst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_mxst.c; sourceTree = ""; }; 836F6E8718BDC2180095E648 /* pc_smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_smp.c; sourceTree = ""; }; 836F6E8818BDC2180095E648 /* pc_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_snds.c; sourceTree = ""; }; - 836F6E8918BDC2180095E648 /* pc_sob.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_sob.c; sourceTree = ""; }; - 836F6E8A18BDC2180095E648 /* pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcm.c; sourceTree = ""; }; 836F6E8B18BDC2180095E648 /* pona.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pona.c; sourceTree = ""; }; 836F6E8C18BDC2180095E648 /* pos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pos.c; sourceTree = ""; }; 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_2pfs.c; sourceTree = ""; }; @@ -806,7 +850,6 @@ 836F6EF218BDC2190095E648 /* sli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sli.c; sourceTree = ""; }; 836F6EF318BDC2190095E648 /* spt_spd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spt_spd.c; sourceTree = ""; }; 836F6EF418BDC2190095E648 /* sqex_scd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqex_scd.c; sourceTree = ""; }; - 836F6EF518BDC2190095E648 /* ss_stream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ss_stream.c; sourceTree = ""; }; 836F6EF618BDC2190095E648 /* str_asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_asr.c; sourceTree = ""; }; 836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = ""; }; 836F6EF818BDC2190095E648 /* stx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stx.c; sourceTree = ""; }; @@ -884,7 +927,6 @@ 839E21DF1F2EDAF000EE54D7 /* vorbis_custom_utils_sk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_sk.c; sourceTree = ""; }; 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sk_aud.c; sourceTree = ""; }; 83A3F0711E3AD8B900D6A794 /* formats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = formats.c; sourceTree = ""; }; - 83A3F0721E3AD8B900D6A794 /* formats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = formats.h; sourceTree = ""; }; 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = ""; }; 83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = ""; }; 83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_xa_decoder.c; sourceTree = ""; }; @@ -893,10 +935,8 @@ 83AA5D151F6E2F600020821C /* ea_xas_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_xas_decoder.c; sourceTree = ""; }; 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_vgs.c; sourceTree = ""; }; 83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_awc.c; sourceTree = ""; }; - 83AA5D1C1F6E2F7F0020821C /* ea_sns_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_sns_blocked.c; sourceTree = ""; }; 83AA5D201F6E2F9B0020821C /* awc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awc.c; sourceTree = ""; }; 83AA5D211F6E2F9C0020821C /* hca_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hca_keys.h; sourceTree = ""; }; - 83AA5D221F6E2F9C0020821C /* ea_snu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_snu.c; sourceTree = ""; }; 83AA5D231F6E2F9C0020821C /* stm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stm.c; sourceTree = ""; }; 83AB8C731E8072A100086084 /* nub_vag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_vag.c; sourceTree = ""; }; 83AB8C741E8072A100086084 /* x360_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_ast.c; sourceTree = ""; }; @@ -1038,7 +1078,6 @@ 836F6DFF18BDC2180095E648 /* layout */, 836F6E2718BDC2180095E648 /* meta */, 83A3F0711E3AD8B900D6A794 /* formats.c */, - 83A3F0721E3AD8B900D6A794 /* formats.h */, 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */, 836F6F1718BDC2190095E648 /* streamfile.c */, 836F6F1818BDC2190095E648 /* streamfile.h */, @@ -1054,6 +1093,9 @@ 836F6DDF18BDC2180095E648 /* coding */ = { isa = PBXGroup; children = ( + 8349A8DE1FE6251F00E26435 /* ea_mt_decoder.c */, + 8349A8DD1FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c */, + 8349A8DC1FE6251E00E26435 /* vorbis_custom_utils_vid1.c */, 83345A491F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c */, 8374EE361F787AB500033E90 /* ffmpeg_decoder_utils_ea_xma.c */, 8374EE3D1F787AB600033E90 /* ffmpeg_decoder_utils.c */, @@ -1116,9 +1158,14 @@ 836F6DFF18BDC2180095E648 /* layout */ = { isa = PBXGroup; children = ( + 8349A8E21FE6253800E26435 /* blocked_dec.c */, + 8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */, + 8349A8E41FE6253800E26435 /* blocked_ea_schl.c */, + 8349A8E71FE6253900E26435 /* blocked_ea_sns.c */, + 8349A8E51FE6253800E26435 /* blocked_ivaud.c */, + 8349A8E61FE6253900E26435 /* blocked_vawx.c */, 83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */, 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */, - 83AA5D1C1F6E2F7F0020821C /* ea_sns_blocked.c */, 830165A11F256BF400CA0941 /* hwas_blocked.c */, 831BD1201EEE1D2A00198540 /* rws_blocked.c */, 836F6E0018BDC2180095E648 /* aax_layout.c */, @@ -1127,16 +1174,12 @@ 836F6E0318BDC2180095E648 /* bdsp_blocked.c */, 836F6E0418BDC2180095E648 /* blocked.c */, 836F6E0518BDC2180095E648 /* caf_blocked.c */, - 836F6E0618BDC2180095E648 /* de2_blocked.c */, - 836F6E0718BDC2180095E648 /* ea_block.c */, 836F6E0818BDC2180095E648 /* emff_blocked.c */, 836F6E0918BDC2180095E648 /* filp_blocked.c */, 836F6E0A18BDC2180095E648 /* gsb_blocked.c */, 836F6E0B18BDC2180095E648 /* halpst_blocked.c */, 836F6E0C18BDC2180095E648 /* ims_block.c */, 836F6E0D18BDC2180095E648 /* interleave.c */, - 836F6E0E18BDC2180095E648 /* interleave_byte.c */, - 836F6E0F18BDC2180095E648 /* ivaud_layout.c */, 836F6E1018BDC2180095E648 /* layout.h */, 836F6E1218BDC2180095E648 /* mus_acm_layout.c */, 836F6E1318BDC2180095E648 /* mxch_blocked.c */, @@ -1161,12 +1204,36 @@ 836F6E2718BDC2180095E648 /* meta */ = { isa = PBXGroup; children = ( + 8349A9041FE6258100E26435 /* aax_streamfile.h */, + 8349A9021FE6258100E26435 /* adx_keys.h */, + 8349A9001FE6258000E26435 /* afc.c */, + 8349A8F61FE6257E00E26435 /* aix_streamfile.h */, + 8349A8F81FE6257E00E26435 /* bar_streamfile.h */, + 8349A9051FE6258100E26435 /* bar.c */, + 8349A8EE1FE6257C00E26435 /* dec.c */, + 8349A8FF1FE6258000E26435 /* ea_1snh.c */, + 8349A8F71FE6257E00E26435 /* ea_eaac.c */, + 8349A8EF1FE6257C00E26435 /* ezw.c */, + 8349A8FD1FE6257F00E26435 /* flx.c */, + 8349A9031FE6258100E26435 /* mogg.c */, + 8349A9061FE6258100E26435 /* naac.c */, + 8349A8FA1FE6257E00E26435 /* ngc_vid1.c */, + 8349A8FB1FE6257F00E26435 /* omu.c */, + 8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */, + 8349A8F01FE6257C00E26435 /* pc_ast.c */, + 8349A8F21FE6257D00E26435 /* ps2_pcm.c */, + 8349A8FC1FE6257F00E26435 /* ps2_xa2_rrp.c */, + 8349A8F11FE6257D00E26435 /* sab.c */, + 8349A8F51FE6257D00E26435 /* scd_pcm.c */, + 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */, + 8349A8F41FE6257D00E26435 /* ubi_sb.c */, + 8349A8F91FE6257E00E26435 /* vsf_tta.c */, + 8349A9011FE6258000E26435 /* vxn.c */, 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */, 83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */, 83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */, 83345A4E1F8AEB2800B2EAA4 /* xvag.c */, 83AA5D201F6E2F9B0020821C /* awc.c */, - 83AA5D221F6E2F9C0020821C /* ea_snu.c */, 83AA5D211F6E2F9C0020821C /* hca_keys.h */, 83AA5D231F6E2F9C0020821C /* stm.c */, 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */, @@ -1212,7 +1279,6 @@ 836F6E2A18BDC2180095E648 /* aax.c */, 836F6E2B18BDC2180095E648 /* acm.c */, 836F6E2C18BDC2180095E648 /* ads.c */, - 836F6E2E18BDC2180095E648 /* afc_header.c */, 836F6E2F18BDC2180095E648 /* agsc.c */, 836F6E3018BDC2180095E648 /* ahx.c */, 836F6E3118BDC2180095E648 /* aifc.c */, @@ -1232,12 +1298,10 @@ 836F6E3F18BDC2180095E648 /* dc_idvi.c */, 836F6E4018BDC2180095E648 /* dc_kcey.c */, 836F6E4118BDC2180095E648 /* dc_str.c */, - 836F6E4218BDC2180095E648 /* de2.c */, 836F6E4318BDC2180095E648 /* dmsg_segh.c */, 836F6E4418BDC2180095E648 /* dsp_bdsp.c */, 836F6E4518BDC2180095E648 /* dsp_sth_str.c */, 836F6E4618BDC2180095E648 /* ea_schl.c */, - 836F6E4718BDC2180095E648 /* ea_old.c */, 836F6E4818BDC2180095E648 /* emff.c */, 836F6E4918BDC2180095E648 /* exakt_sc.c */, 836F6E4A18BDC2180095E648 /* excitebots.c */, @@ -1246,7 +1310,6 @@ 836F6E4D18BDC2180095E648 /* gca.c */, 836F6E4E18BDC2180095E648 /* gcsw.c */, 836F6E4F18BDC2180095E648 /* genh.c */, - 836F6E5018BDC2180095E648 /* gh3_bar.c */, 836F6E5118BDC2180095E648 /* gsp_gsb.c */, 836F6E5218BDC2180095E648 /* halpst.c */, 836F6E5318BDC2180095E648 /* his.c */, @@ -1300,8 +1363,6 @@ 836F6E8618BDC2180095E648 /* pc_mxst.c */, 836F6E8718BDC2180095E648 /* pc_smp.c */, 836F6E8818BDC2180095E648 /* pc_snds.c */, - 836F6E8918BDC2180095E648 /* pc_sob.c */, - 836F6E8A18BDC2180095E648 /* pcm.c */, 836F6E8B18BDC2180095E648 /* pona.c */, 836F6E8C18BDC2180095E648 /* pos.c */, 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */, @@ -1401,7 +1462,6 @@ 836F6EF218BDC2190095E648 /* sli.c */, 836F6EF318BDC2190095E648 /* spt_spd.c */, 836F6EF418BDC2190095E648 /* sqex_scd.c */, - 836F6EF518BDC2190095E648 /* ss_stream.c */, 836F6EF618BDC2190095E648 /* str_asr.c */, 836F6EF718BDC2190095E648 /* str_snds.c */, 836F6EF818BDC2190095E648 /* stx.c */, @@ -1475,12 +1535,14 @@ 836F705518BDC2190095E648 /* streamtypes.h in Headers */, 836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */, 836F6F3518BDC2190095E648 /* nwa_decoder.h in Headers */, + 8349A91D1FE6258200E26435 /* aax_streamfile.h in Headers */, + 8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */, + 8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */, 836F6F2718BDC2190095E648 /* g72x_state.h in Headers */, 839E21E01F2EDAF100EE54D7 /* vorbis_custom_data_fsb.h in Headers */, 836F705418BDC2190095E648 /* streamfile.h in Headers */, 8374EE401F787AB600033E90 /* ffmpeg_decoder_utils.h in Headers */, 83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */, - 83A3F0751E3AD8B900D6A794 /* formats.h in Headers */, 8323894B1D22419B00482226 /* clHCA.h in Headers */, 839E21E81F2EDAF100EE54D7 /* mpeg_decoder.h in Headers */, 839E21E51F2EDAF100EE54D7 /* vorbis_custom_decoder.h in Headers */, @@ -1489,6 +1551,8 @@ 48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */, 836F705718BDC2190095E648 /* util.h in Headers */, 836F6F9A18BDC2190095E648 /* meta.h in Headers */, + 8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */, + 8349A91B1FE6258200E26435 /* adx_keys.h in Headers */, 836F6F4D18BDC2190095E648 /* layout.h in Headers */, 83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */, 836F6F2318BDC2190095E648 /* coding.h in Headers */, @@ -1641,6 +1705,7 @@ files = ( 839E21E21F2EDAF100EE54D7 /* vorbis_custom_utils_wwise.c in Sources */, 83E56BA51F2EE3520026BC60 /* vorbis_custom_utils_ogl.c in Sources */, + 8349A9071FE6258200E26435 /* dec.c in Sources */, 839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */, 839E21E41F2EDAF100EE54D7 /* vorbis_custom_utils_fsb.c in Sources */, 839E21E11F2EDAF100EE54D7 /* vorbis_custom_decoder.c in Sources */, @@ -1652,8 +1717,10 @@ 8301659C1F256BD000CA0941 /* nds_strm_ffta2.c in Sources */, 83CAB8E31F0B0755001BC993 /* pc_xa30.c in Sources */, 83CAB8E21F0B0752001BC993 /* wii_04sw.c in Sources */, + 8349A8DF1FE6251F00E26435 /* vorbis_custom_utils_vid1.c in Sources */, 839B54571EEE1DA000048A2D /* rws_blocked.c in Sources */, 839B54521EEE1D9600048A2D /* ngc_ulw.c in Sources */, + 8349A8E01FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c in Sources */, 836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */, 836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */, 836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */, @@ -1664,7 +1731,6 @@ 836F6F7418BDC2190095E648 /* bgw.c in Sources */, 836F6F7218BDC2190095E648 /* baf.c in Sources */, 83F5F8831908D0A400C8E65F /* fsb5.c in Sources */, - 836F6F4B18BDC2190095E648 /* interleave_byte.c in Sources */, 836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */, 836F700C18BDC2190095E648 /* ps2_wb.c in Sources */, 836F6F7D18BDC2190095E648 /* dc_str.c in Sources */, @@ -1678,6 +1744,7 @@ 836F6F9B18BDC2190095E648 /* mn_str.c in Sources */, 836F6F5918BDC2190095E648 /* tra_blocked.c in Sources */, 836F6F9F18BDC2190095E648 /* musc.c in Sources */, + 8349A9121FE6258200E26435 /* vsf_tta.c in Sources */, 836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */, 836F6FA118BDC2190095E648 /* myspd.c in Sources */, 836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */, @@ -1691,6 +1758,7 @@ 83299FD01E7660C7003A3242 /* bik.c in Sources */, 836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */, 836F6FBB18BDC2190095E648 /* ngca.c in Sources */, + 8349A91E1FE6258200E26435 /* bar.c in Sources */, 836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */, 832389521D224C0800482226 /* hca_decoder.c in Sources */, 836F6F9418BDC2190095E648 /* ivb.c in Sources */, @@ -1700,21 +1768,27 @@ 836F6F2218BDC2190095E648 /* at3_decoder.c in Sources */, 83EDE5D91A70951A005F5D84 /* btsnd.c in Sources */, 836F6FFC18BDC2190095E648 /* ps2_ster.c in Sources */, + 8349A9171FE6258200E26435 /* pc_adp_otns.c in Sources */, 836F701E18BDC2190095E648 /* redspark.c in Sources */, 836F6FA018BDC2190095E648 /* musx.c in Sources */, 836F705818BDC2190095E648 /* vgmstream.c in Sources */, + 8349A90A1FE6258200E26435 /* sab.c in Sources */, 836F6F6818BDC2190095E648 /* ads.c in Sources */, 83AB8C761E8072A100086084 /* x360_ast.c in Sources */, 836F6F8B18BDC2190095E648 /* genh.c in Sources */, + 8349A8EA1FE6253900E26435 /* blocked_ea_schl.c in Sources */, 836F705118BDC2190095E648 /* zsd.c in Sources */, + 8349A91F1FE6258200E26435 /* naac.c in Sources */, 836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */, 836F703C18BDC2190095E648 /* wii_bns.c in Sources */, 835027131ED119E000C25929 /* mta2_decoder.c in Sources */, 836F6FA718BDC2190095E648 /* nds_strm.c in Sources */, + 8349A91A1FE6258200E26435 /* vxn.c in Sources */, + 8349A8EB1FE6253900E26435 /* blocked_ivaud.c in Sources */, 83A3F0741E3AD8B900D6A794 /* formats.c in Sources */, 836F6F6E18BDC2190095E648 /* aix.c in Sources */, - 836F703118BDC2190095E648 /* ss_stream.c in Sources */, 836F6F8718BDC2190095E648 /* ffw.c in Sources */, + 8349A9141FE6258200E26435 /* omu.c in Sources */, 836F6FE418BDC2190095E648 /* ps2_leg.c in Sources */, 836F705618BDC2190095E648 /* util.c in Sources */, 836F703618BDC2190095E648 /* thp.c in Sources */, @@ -1745,16 +1819,17 @@ 836F6F6518BDC2190095E648 /* 2dx9.c in Sources */, 836F700818BDC2190095E648 /* ps2_vms.c in Sources */, 836F702418BDC2190095E648 /* rwsd.c in Sources */, - 836F6F7E18BDC2190095E648 /* de2.c in Sources */, 836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */, 836F6F6618BDC2190095E648 /* aax.c in Sources */, - 836F6F4C18BDC2190095E648 /* ivaud_layout.c in Sources */, 836F6FD618BDC2190095E648 /* ps2_exst.c in Sources */, 836F6F6718BDC2190095E648 /* acm.c in Sources */, 836F6F8A18BDC2190095E648 /* gcsw.c in Sources */, 836F6F9C18BDC2190095E648 /* mp4.c in Sources */, + 8349A9101FE6258200E26435 /* ea_eaac.c in Sources */, 836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */, + 8349A8ED1FE6253900E26435 /* blocked_ea_sns.c in Sources */, 836F6F6F18BDC2190095E648 /* akb.c in Sources */, + 8349A9181FE6258200E26435 /* ea_1snh.c in Sources */, 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */, 83709E071ECBC1A4005C03D3 /* mss.c in Sources */, 836F6F8F18BDC2190095E648 /* his.c in Sources */, @@ -1762,7 +1837,6 @@ 836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */, 836F6FCB18BDC2190095E648 /* ps2_ads.c in Sources */, 836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */, - 83AA5D261F6E2F9C0020821C /* ea_snu.c in Sources */, 83AA5D171F6E2F600020821C /* mpeg_custom_utils_ealayer3.c in Sources */, 83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */, 836F704C18BDC2190095E648 /* xbox_xvas.c in Sources */, @@ -1775,16 +1849,15 @@ 836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */, 836F6F7918BDC2190095E648 /* dc_asd.c in Sources */, 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */, - 836F6F8318BDC2190095E648 /* ea_old.c in Sources */, 836F701A18BDC2190095E648 /* psx_fag.c in Sources */, 836F703B18BDC2190095E648 /* vsf.c in Sources */, 836F6F3D18BDC2190095E648 /* aax_layout.c in Sources */, - 83AA5D1F1F6E2F800020821C /* ea_sns_blocked.c in Sources */, 836F6F8218BDC2190095E648 /* ea_schl.c in Sources */, 836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */, 836F6F7318BDC2190095E648 /* bcstm.c in Sources */, 83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */, 836F704018BDC2190095E648 /* wii_sng.c in Sources */, + 8349A9131FE6258200E26435 /* ngc_vid1.c in Sources */, 8350C0551E071881009E0A93 /* xma.c in Sources */, 836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */, 836F704218BDC2190095E648 /* wii_sts.c in Sources */, @@ -1799,7 +1872,6 @@ 836F702B18BDC2190095E648 /* sdt.c in Sources */, 836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */, 836F702C18BDC2190095E648 /* seg.c in Sources */, - 836F6F6A18BDC2190095E648 /* afc_header.c in Sources */, 836F700918BDC2190095E648 /* ps2_voi.c in Sources */, 836F6F3E18BDC2190095E648 /* aix_layout.c in Sources */, 836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */, @@ -1814,6 +1886,7 @@ 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 */, 836F6F9818BDC2190095E648 /* mattel_hyperscan.c in Sources */, @@ -1822,7 +1895,7 @@ 83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */, 836F6F6D18BDC2190095E648 /* aifc.c in Sources */, 836F702218BDC2190095E648 /* rsd.c in Sources */, - 836F6FC618BDC2190095E648 /* pcm.c in Sources */, + 8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */, 83345A501F8AEB2800B2EAA4 /* pc_al2.c in Sources */, 836F702518BDC2190095E648 /* rwx.c in Sources */, 836F6F3A18BDC2190095E648 /* sdx2_decoder.c in Sources */, @@ -1851,6 +1924,7 @@ 836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */, 836F6F5118BDC2190095E648 /* nolayout.c in Sources */, 83AA5D241F6E2F9C0020821C /* awc.c in Sources */, + 8349A8E91FE6253900E26435 /* blocked_ea_1snh.c in Sources */, 836F702918BDC2190095E648 /* sat_sap.c in Sources */, 836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */, 831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */, @@ -1869,11 +1943,13 @@ 83709E061ECBC1A4005C03D3 /* mc3.c in Sources */, 831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */, 836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */, + 8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */, 836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */, 836F6F4A18BDC2190095E648 /* interleave.c in Sources */, 83EDE5D81A70951A005F5D84 /* mca.c in Sources */, 831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */, 838BDB6C1D3AFAB10022CA6F /* ffmpeg_decoder.c in Sources */, + 8349A8E11FE6251F00E26435 /* ea_mt_decoder.c in Sources */, 836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */, 836F702F18BDC2190095E648 /* spt_spd.c in Sources */, 836F704618BDC2190095E648 /* x360_tra.c in Sources */, @@ -1882,7 +1958,9 @@ 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */, 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */, 836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */, + 8349A9091FE6258200E26435 /* pc_ast.c in Sources */, 836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */, + 8349A91C1FE6258200E26435 /* mogg.c in Sources */, 836F703D18BDC2190095E648 /* wii_mus.c in Sources */, 836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */, 831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */, @@ -1901,14 +1979,16 @@ 836F6F7718BDC2190095E648 /* capdsp.c in Sources */, 836F6FB018BDC2190095E648 /* ngc_dsp_ygo.c in Sources */, 836F703318BDC2190095E648 /* str_snds.c in Sources */, + 8349A9191FE6258200E26435 /* afc.c in Sources */, 836F703718BDC2190095E648 /* tun.c in Sources */, 836F700B18BDC2190095E648 /* ps2_wad.c in Sources */, + 8349A9161FE6258200E26435 /* flx.c in Sources */, 831BA61E1EAC61A500CF89B0 /* vawx.c in Sources */, 836F702A18BDC2190095E648 /* sd9.c in Sources */, 836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */, - 836F6F4418BDC2190095E648 /* ea_block.c in Sources */, 836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */, 836F6FF618BDC2190095E648 /* ps2_sfs.c in Sources */, + 8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */, 836F6F9518BDC2190095E648 /* kraw.c in Sources */, 836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */, 83709E051ECBC1A4005C03D3 /* gtd.c in Sources */, @@ -1926,8 +2006,8 @@ 836F700318BDC2190095E648 /* ps2_vag.c in Sources */, 836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */, 831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */, - 836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */, 836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */, + 8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */, 831BA6181EAC61A500CF89B0 /* adx.c in Sources */, 836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */, 836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */, @@ -1937,6 +2017,7 @@ 836F6F4918BDC2190095E648 /* ims_block.c in Sources */, 836F6F7518BDC2190095E648 /* bnsf.c in Sources */, 836F704318BDC2190095E648 /* wpd.c in Sources */, + 8349A9081FE6258200E26435 /* ezw.c in Sources */, 836F6FE118BDC2190095E648 /* ps2_jstm.c in Sources */, 836F6FD918BDC2190095E648 /* ps2_gcm.c in Sources */, 836F6F8E18BDC2190095E648 /* halpst.c in Sources */, @@ -1959,7 +2040,6 @@ 836F700718BDC2190095E648 /* ps2_vgv.c in Sources */, 836F704F18BDC2190095E648 /* xwb.c in Sources */, 8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */, - 836F6FC518BDC2190095E648 /* pc_sob.c in Sources */, 836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */, 836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */, 836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */, @@ -1983,6 +2063,7 @@ 836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */, 836F6F9218BDC2190095E648 /* ish_isd.c in Sources */, 836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */, + 8349A9151FE6258200E26435 /* ps2_xa2_rrp.c in Sources */, 836F703518BDC2190095E648 /* svs.c in Sources */, 836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */, 836F6F9D18BDC2190095E648 /* msvp.c in Sources */, @@ -1990,7 +2071,6 @@ 836F705018BDC2190095E648 /* ydsp.c in Sources */, 836F702718BDC2190095E648 /* sat_baka.c in Sources */, 83345A4A1F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c in Sources */, - 836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */, 836F704B18BDC2190095E648 /* xbox_xmu.c in Sources */, 832389501D2246C300482226 /* hca.c in Sources */, 836F701B18BDC2190095E648 /* psx_gms.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index 1976a5e10..6e36600b9 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -18,11 +18,10 @@ void g72x_init_state(struct g72x_state *state_ptr); void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); -void decode_xbox_ima_int(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); -void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); -void decode_eacs_ima(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); -void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first); +void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); @@ -32,12 +31,14 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); 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 ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset); /* ngc_dsp_decoder */ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); -void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem); +void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave); size_t dsp_bytes_to_samples(size_t bytes, int channels); int32_t dsp_nibbles_to_samples(int32_t nibbles); void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing); @@ -78,7 +79,8 @@ size_t ps_bytes_to_samples(size_t bytes, int channels); /* xa_decoder */ void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); -void init_get_high_nibble(VGMSTREAM * vgmstream); +void xa_init_get_high_nibble(VGMSTREAM * vgmstream); +size_t xa_bytes_to_samples(size_t bytes, int channels, int is_blocked); /* ea_xa_decoder */ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); @@ -133,6 +135,14 @@ void decode_mta2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, /* mc3_decoder */ void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +/* ea_mt_decoder*/ +ea_mt_codec_data *init_ea_mt(int channel_count, int type); +void decode_ea_mt(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +void reset_ea_mt(VGMSTREAM * vgmstream); +void flush_ea_mt(VGMSTREAM *vgmstream); +void seek_ea_mt(VGMSTREAM * vgmstream, int32_t num_sample); +void free_ea_mt(ea_mt_codec_data *data); + /* hca_decoder */ void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); void reset_hca(VGMSTREAM *vgmstream); @@ -167,11 +177,11 @@ void free_mpeg(mpeg_codec_data *data); void flush_mpeg(mpeg_codec_data * data); long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data); -void mpeg_set_error_logging(mpeg_codec_data * data, int enable); #endif #ifdef VGM_USE_G7221 /* g7221_decoder */ +g7221_codec_data *init_g7221(int channel_count, int frame_size); void decode_g7221(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); void reset_g7221(VGMSTREAM *vgmstream); void free_g7221(VGMSTREAM *vgmstream); @@ -179,6 +189,7 @@ void free_g7221(VGMSTREAM *vgmstream); #ifdef VGM_USE_G719 /* g719_decoder */ +g719_codec_data *init_g719(int channel_count, int frame_size); void decode_g719(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); void reset_g719(VGMSTREAM *vgmstream); void free_g719(VGMSTREAM *vgmstream); @@ -265,4 +276,19 @@ void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * cha size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align); size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align); + + +/* An internal struct to pass around and simulate a bitstream. */ +typedef enum { BITSTREAM_MSF, BITSTREAM_VORBIS } vgm_bitstream_t; +typedef struct { + uint8_t * buf; /* buffer to read/write*/ + size_t bufsize; /* max size of the buffer */ + off_t b_off; /* current offset in bits inside the buffer */ + off_t info_offset; /* for logging */ + vgm_bitstream_t mode; /* read/write modes */ +} vgm_bitstream; + +int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value); +int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value); + #endif /*_CODING_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c index a57331469..d0cec7fc7 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c @@ -835,3 +835,149 @@ size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) { * so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */ return (bytes / full_block_align) * 2048; } + + +/* ******************************************** */ +/* BITSTREAM */ +/* ******************************************** */ + + +/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte. + * (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */ +static int r_bits_vorbis(vgm_bitstream * ib, int num_bits, uint32_t * value) { + off_t off, pos; + int i, bit_buf, bit_val; + if (num_bits == 0) return 1; + if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail; + + *value = 0; /* set all bits to 0 */ + off = ib->b_off / 8; /* byte offset */ + pos = ib->b_off % 8; /* bit sub-offset */ + for (i = 0; i < num_bits; i++) { + bit_buf = (1U << pos) & 0xFF; /* bit check for buf */ + bit_val = (1U << i); /* bit to set in value */ + + if (ib->buf[off] & bit_buf) /* is bit in buf set? */ + *value |= bit_val; /* set bit */ + + pos++; /* new byte starts */ + if (pos%8 == 0) { + pos = 0; + off++; + } + } + + ib->b_off += num_bits; + return 1; +fail: + return 0; +} + +/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte. + * (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/ +static int w_bits_vorbis(vgm_bitstream * ob, int num_bits, uint32_t value) { + off_t off, pos; + int i, bit_val, bit_buf; + if (num_bits == 0) return 1; + if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail; + + + off = ob->b_off / 8; /* byte offset */ + pos = ob->b_off % 8; /* bit sub-offset */ + for (i = 0; i < num_bits; i++) { + bit_val = (1U << i); /* bit check for value */ + bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */ + + if (value & bit_val) /* is bit in val set? */ + ob->buf[off] |= bit_buf; /* set bit */ + else + ob->buf[off] &= ~bit_buf; /* unset bit */ + + pos++; /* new byte starts */ + if (pos%8 == 0) { + pos = 0; + off++; + } + } + + ob->b_off += num_bits; + return 1; +fail: + return 0; +} + + +/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */ +static int r_bits_msf(vgm_bitstream * ib, int num_bits, uint32_t * value) { + off_t off, pos; + int i, bit_buf, bit_val; + if (num_bits == 0) return 1; + if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail; + + *value = 0; /* set all bits to 0 */ + off = ib->b_off / 8; /* byte offset */ + pos = ib->b_off % 8; /* bit sub-offset */ + for (i = 0; i < num_bits; i++) { + bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */ + bit_val = (1U << (num_bits-1-i)); /* bit to set in value */ + + if (ib->buf[off] & bit_buf) /* is bit in buf set? */ + *value |= bit_val; /* set bit */ + + pos++; + if (pos%8 == 0) { /* new byte starts */ + pos = 0; + off++; + } + } + + ib->b_off += num_bits; + return 1; +fail: + return 0; +} + +/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */ +static int w_bits_msf(vgm_bitstream * ob, int num_bits, uint32_t value) { + off_t off, pos; + int i, bit_val, bit_buf; + if (num_bits == 0) return 1; + if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail; + + + off = ob->b_off / 8; /* byte offset */ + pos = ob->b_off % 8; /* bit sub-offset */ + for (i = 0; i < num_bits; i++) { + bit_val = (1U << (num_bits-1-i)); /* bit check for value */ + bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */ + + if (value & bit_val) /* is bit in val set? */ + ob->buf[off] |= bit_buf; /* set bit */ + else + ob->buf[off] &= ~bit_buf; /* unset bit */ + + pos++; + if (pos%8 == 0) { /* new byte starts */ + pos = 0; + off++; + } + } + + ob->b_off += num_bits; + return 1; +fail: + return 0; +} + +int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value) { + if (ib->mode == BITSTREAM_VORBIS) + return r_bits_vorbis(ib,num_bits,value); + else + return r_bits_msf(ib,num_bits,value); +} +int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value) { + if (ob->mode == BITSTREAM_VORBIS) + return w_bits_vorbis(ob,num_bits,value); + else + return w_bits_msf(ob,num_bits,value); +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ea_mt_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ea_mt_decoder.c new file mode 100644 index 000000000..fa02d8c5c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ea_mt_decoder.c @@ -0,0 +1,577 @@ +#include "coding.h" + +/* Decodes EA MicroTalk (speech codec) using a copied utkencode lib. + * EA separates MT10:1 and MT5:1 (bigger frames), but apparently are the same + * with different encoding parameters. Later revisions may have PCM blocks (rare). + * + * Decoder by Andrew D'Addesio: https://github.com/daddesio/utkencode + * Info: http://wiki.niotso.org/UTK + * + * The following tries to follow the original code as close as possible, with minimal changes for vgmstream + */ + +/* ************************************************************************************************* */ +#define UTK_BUFFER_SIZE 0x4000 + +//#define UTK_MAKE_U32(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24)) +#define UTK_ROUND(x) ((x) >= 0.0f ? ((x)+0.5f) : ((x)-0.5f)) +#define UTK_MIN(x,y) ((x)<(y)?(x):(y)) +#define UTK_MAX(x,y) ((x)>(y)?(x):(y)) +#define UTK_CLAMP(x,min,max) UTK_MIN(UTK_MAX(x,min),max) + + +/* Note: This struct assumes a member alignment of 4 bytes. +** This matters when pitch_lag > 216 on the first subframe of any given frame. */ +typedef struct UTKContext { + uint8_t buffer[UTK_BUFFER_SIZE]; //vgmstream extra + STREAMFILE * streamfile; //vgmstream extra + off_t offset; //vgmstream extra + int samples_filled; //vgmstream extra + //FILE *fp; //vgmstream extra + const uint8_t *ptr, *end; + int parsed_header; + unsigned int bits_value; + int bits_count; + int reduced_bw; + int multipulse_thresh; + float fixed_gains[64]; + float rc[12]; + float synth_history[12]; + float adapt_cb[324]; + float decompressed_frame[432]; +} UTKContext; + +enum { + MDL_NORMAL = 0, + MDL_LARGEPULSE = 1 +}; + +static const float utk_rc_table[64] = { + 0.0f, + -.99677598476409912109375f, -.99032700061798095703125f, -.983879029750823974609375f, -.977430999279022216796875f, + -.970982015132904052734375f, -.964533984661102294921875f, -.958085000514984130859375f, -.9516370296478271484375f, + -.930754005908966064453125f, -.904959976673126220703125f, -.879167020320892333984375f, -.853372991085052490234375f, + -.827579021453857421875f, -.801786005496978759765625f, -.775991976261138916015625f, -.75019800662994384765625f, + -.724404990673065185546875f, -.6986110210418701171875f, -.6706349849700927734375f, -.61904799938201904296875f, + -.567460000514984130859375f, -.515873014926910400390625f, -.4642859995365142822265625f, -.4126980006694793701171875f, + -.361110985279083251953125f, -.309523999691009521484375f, -.257937014102935791015625f, -.20634900033473968505859375f, + -.1547619998455047607421875f, -.10317499935626983642578125f, -.05158700048923492431640625f, + 0.0f, + +.05158700048923492431640625f, +.10317499935626983642578125f, +.1547619998455047607421875f, +.20634900033473968505859375f, + +.257937014102935791015625f, +.309523999691009521484375f, +.361110985279083251953125f, +.4126980006694793701171875f, + +.4642859995365142822265625f, +.515873014926910400390625f, +.567460000514984130859375f, +.61904799938201904296875f, + +.6706349849700927734375f, +.6986110210418701171875f, +.724404990673065185546875f, +.75019800662994384765625f, + +.775991976261138916015625f, +.801786005496978759765625f, +.827579021453857421875f, +.853372991085052490234375f, + +.879167020320892333984375f, +.904959976673126220703125f, +.930754005908966064453125f, +.9516370296478271484375f, + +.958085000514984130859375f, +.964533984661102294921875f, +.970982015132904052734375f, +.977430999279022216796875f, + +.983879029750823974609375f, +.99032700061798095703125f, +.99677598476409912109375 +}; + +static const uint8_t utk_codebooks[2][256] = { + { /* normal model */ + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 21, + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 25, + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 22, + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 0, + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 21, + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 26, + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 22, + 4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18, + 4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 2 + }, { /* large-pulse model */ + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 27, + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 1, + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 28, + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 3, + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 27, + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 1, + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 28, + 4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24, + 4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 3 + } +}; + +static const struct { + int next_model; + int code_size; + float pulse_value; +} utk_commands[29] = { + {MDL_LARGEPULSE, 8, 0.0f}, + {MDL_LARGEPULSE, 7, 0.0f}, + {MDL_NORMAL, 8, 0.0f}, + {MDL_NORMAL, 7, 0.0f}, + {MDL_NORMAL, 2, 0.0f}, + {MDL_NORMAL, 2, -1.0f}, + {MDL_NORMAL, 2, +1.0f}, + {MDL_NORMAL, 3, -1.0f}, + {MDL_NORMAL, 3, +1.0f}, + {MDL_LARGEPULSE, 4, -2.0f}, + {MDL_LARGEPULSE, 4, +2.0f}, + {MDL_LARGEPULSE, 3, -2.0f}, + {MDL_LARGEPULSE, 3, +2.0f}, + {MDL_LARGEPULSE, 5, -3.0f}, + {MDL_LARGEPULSE, 5, +3.0f}, + {MDL_LARGEPULSE, 4, -3.0f}, + {MDL_LARGEPULSE, 4, +3.0f}, + {MDL_LARGEPULSE, 6, -4.0f}, + {MDL_LARGEPULSE, 6, +4.0f}, + {MDL_LARGEPULSE, 5, -4.0f}, + {MDL_LARGEPULSE, 5, +4.0f}, + {MDL_LARGEPULSE, 7, -5.0f}, + {MDL_LARGEPULSE, 7, +5.0f}, + {MDL_LARGEPULSE, 6, -5.0f}, + {MDL_LARGEPULSE, 6, +5.0f}, + {MDL_LARGEPULSE, 8, -6.0f}, + {MDL_LARGEPULSE, 8, +6.0f}, + {MDL_LARGEPULSE, 7, -6.0f}, + {MDL_LARGEPULSE, 7, +6.0f} +}; + +static int utk_read_byte(UTKContext *ctx) +{ + if (ctx->ptr < ctx->end) + return *ctx->ptr++; + + //vgmstream extra: this reads from FILE if static buffer was exhausted, now from a context buffer and STREAMFILE instead + if (ctx->streamfile) { //if (ctx->fp) { + //static uint8_t buffer[4096]; + //size_t bytes_copied = fread(buffer, 1, sizeof(buffer), ctx->fp); + size_t bytes_copied = read_streamfile(ctx->buffer, ctx->offset, sizeof(ctx->buffer), ctx->streamfile); + + ctx->offset += bytes_copied; + if (bytes_copied > 0 && bytes_copied <= sizeof(ctx->buffer)) { + ctx->ptr = ctx->buffer; + ctx->end = ctx->buffer + bytes_copied; + return *ctx->ptr++; + } + } + + return 0; +} + +static int16_t utk_read_i16(UTKContext *ctx) +{ + int x = utk_read_byte(ctx); + x = (x << 8) | utk_read_byte(ctx); + return x; +} + +static int utk_read_bits(UTKContext *ctx, int count) +{ + int ret = ctx->bits_value & ((1 << count) - 1); + ctx->bits_value >>= count; + ctx->bits_count -= count; + + if (ctx->bits_count < 8) { + /* read another byte */ + ctx->bits_value |= utk_read_byte(ctx) << ctx->bits_count; + ctx->bits_count += 8; + } + + return ret; +} + +static void utk_parse_header(UTKContext *ctx) +{ + int i; + float multiplier; + + ctx->reduced_bw = utk_read_bits(ctx, 1); + ctx->multipulse_thresh = 32 - utk_read_bits(ctx, 4); + ctx->fixed_gains[0] = 8.0f * (1 + utk_read_bits(ctx, 4)); + multiplier = 1.04f + utk_read_bits(ctx, 6)*0.001f; + + for (i = 1; i < 64; i++) + ctx->fixed_gains[i] = ctx->fixed_gains[i-1] * multiplier; +} + +static void utk_decode_excitation(UTKContext *ctx, int use_multipulse, float *out, int stride) +{ + int i; + + if (use_multipulse) { + /* multi-pulse model: n pulses are coded explicitly; the rest are zero */ + int model, cmd; + model = 0; + i = 0; + while (i < 108) { + cmd = utk_codebooks[model][ctx->bits_value & 0xff]; + model = utk_commands[cmd].next_model; + utk_read_bits(ctx, utk_commands[cmd].code_size); + + if (cmd > 3) { + /* insert a pulse with magnitude <= 6.0f */ + out[i] = utk_commands[cmd].pulse_value; + i += stride; + } else if (cmd > 1) { + /* insert between 7 and 70 zeros */ + int count = 7 + utk_read_bits(ctx, 6); + if (i + count * stride > 108) + count = (108 - i)/stride; + + while (count > 0) { + out[i] = 0.0f; + i += stride; + count--; + } + } else { + /* insert a pulse with magnitude >= 7.0f */ + int x = 7; + + while (utk_read_bits(ctx, 1)) + x++; + + if (!utk_read_bits(ctx, 1)) + x *= -1; + + out[i] = (float)x; + i += stride; + } + } + } else { + /* RELP model: entire residual (excitation) signal is coded explicitly */ + i = 0; + while (i < 108) { + if (!utk_read_bits(ctx, 1)) + out[i] = 0.0f; + else if (!utk_read_bits(ctx, 1)) + out[i] = -2.0f; + else + out[i] = 2.0f; + + i += stride; + } + } +} + +static void rc_to_lpc(const float *rc, float *lpc) +{ + int i, j; + float tmp1[12]; + float tmp2[12]; + + for (i = 10; i >= 0; i--) + tmp2[1+i] = rc[i]; + + tmp2[0] = 1.0f; + + for (i = 0; i < 12; i++) { + float x = -tmp2[11] * rc[11]; + + for (j = 10; j >= 0; j--) { + x -= tmp2[j] * rc[j]; + tmp2[j+1] = x * rc[j] + tmp2[j]; + } + + tmp1[i] = tmp2[0] = x; + + for (j = 0; j < i; j++) + x -= tmp1[i-1-j] * lpc[j]; + + lpc[i] = x; + } +} + +static void utk_lp_synthesis_filter(UTKContext *ctx, int offset, int num_blocks) +{ + int i, j, k; + float lpc[12]; + float *ptr = &ctx->decompressed_frame[offset]; + + rc_to_lpc(ctx->rc, lpc); + + for (i = 0; i < num_blocks; i++) { + for (j = 0; j < 12; j++) { + float x = *ptr; + + for (k = 0; k < j; k++) + x += lpc[k] * ctx->synth_history[k-j+12]; + for (; k < 12; k++) + x += lpc[k] * ctx->synth_history[k-j]; + + ctx->synth_history[11-j] = x; + *ptr++ = x; + } + } +} + +/* +** Public functions. +*/ + +static void utk_decode_frame(UTKContext *ctx) +{ + int i, j; + int use_multipulse = 0; + float excitation[5+108+5]; + float rc_delta[12]; + + if (!ctx->bits_count) { + ctx->bits_value = utk_read_byte(ctx); + ctx->bits_count = 8; + } + + if (!ctx->parsed_header) { + utk_parse_header(ctx); + ctx->parsed_header = 1; + } + + memset(&excitation[0], 0, 5*sizeof(float)); + memset(&excitation[5+108], 0, 5*sizeof(float)); + + /* read the reflection coefficients */ + for (i = 0; i < 12; i++) { + int idx; + if (i == 0) { + idx = utk_read_bits(ctx, 6); + if (idx < ctx->multipulse_thresh) + use_multipulse = 1; + } else if (i < 4) { + idx = utk_read_bits(ctx, 6); + } else { + idx = 16 + utk_read_bits(ctx, 5); + } + + rc_delta[i] = (utk_rc_table[idx] - ctx->rc[i])*0.25f; + } + + /* decode four subframes */ + for (i = 0; i < 4; i++) { + int pitch_lag = utk_read_bits(ctx, 8); + float pitch_gain = (float)utk_read_bits(ctx, 4)/15.0f; + float fixed_gain = ctx->fixed_gains[utk_read_bits(ctx, 6)]; + + if (!ctx->reduced_bw) { + utk_decode_excitation(ctx, use_multipulse, &excitation[5], 1); + } else { + /* residual (excitation) signal is encoded at reduced bandwidth */ + int align = utk_read_bits(ctx, 1); + int zero = utk_read_bits(ctx, 1); + + utk_decode_excitation(ctx, use_multipulse, &excitation[5+align], 2); + + if (zero) { + /* fill the remaining samples with zero + ** (spectrum is duplicated into high frequencies) */ + for (j = 0; j < 54; j++) + excitation[5+(1-align)+2*j] = 0.0f; + } else { + /* interpolate the remaining samples + ** (spectrum is low-pass filtered) */ + float *ptr = &excitation[5+(1-align)]; + for (j = 0; j < 108; j += 2) + ptr[j] = ptr[j-5] * 0.01803267933428287506103515625f + - ptr[j-3] * 0.114591561257839202880859375f + + ptr[j-1] * 0.597385942935943603515625f + + ptr[j+1] * 0.597385942935943603515625f + - ptr[j+3] * 0.114591561257839202880859375f + + ptr[j+5] * 0.01803267933428287506103515625f; + + /* scale by 0.5f to give the sinc impulse response unit energy */ + fixed_gain *= 0.5f; + } + } + + for (j = 0; j < 108; j++) + ctx->decompressed_frame[108*i+j] = fixed_gain * excitation[5+j] + + pitch_gain * ctx->adapt_cb[108*i+216-pitch_lag+j]; + } + + for (i = 0; i < 324; i++) + ctx->adapt_cb[i] = ctx->decompressed_frame[108+i]; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 12; j++) + ctx->rc[j] += rc_delta[j]; + + utk_lp_synthesis_filter(ctx, 12*i, i < 3 ? 1 : 33); + } +} + +static void utk_init(UTKContext *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +#if 0 //vgmstream extra: see flush_ea_mt +static void utk_set_fp(UTKContext *ctx, FILE *fp) +{ + ctx->fp = fp; + + /* reset the bit reader */ + ctx->bits_count = 0; +} + +static void utk_set_ptr(UTKContext *ctx, const uint8_t *ptr, const uint8_t *end) +{ + ctx->ptr = ptr; + ctx->end = end; + + /* reset the bit reader */ + ctx->bits_count = 0; +} +#endif + +/* +** MicroTalk Revision 3 decoding function. +*/ + +static void utk_rev3_decode_frame(UTKContext *ctx) +{ + int pcm_data_present = (utk_read_byte(ctx) == 0xee); + int i; + + utk_decode_frame(ctx); + + /* unread the last 8 bits and reset the bit reader */ + ctx->ptr--; + ctx->bits_count = 0; + + if (pcm_data_present) { + /* Overwrite n samples at a given offset in the decoded frame with + ** raw PCM data. */ + int offset = utk_read_i16(ctx); + int count = utk_read_i16(ctx); + + /* sx.exe does not do any bounds checking or clamping of these two + ** fields (see 004274D1 in sx.exe v3.01.01), which means a specially + ** crafted MT5:1 file can crash sx.exe. + ** We will throw an error instead. */ + if (offset < 0 || offset > 432) { + //fprintf(stderr, "error: invalid PCM offset %d\n", offset); + //exit(EXIT_FAILURE); + return; //vgmstream extra + } + if (count < 0 || count > 432 - offset) { + //fprintf(stderr, "error: invalid PCM count %d\n", count); + //exit(EXIT_FAILURE); + return; //vgmstream extra + } + + for (i = 0; i < count; i++) + ctx->decompressed_frame[offset+i] = (float)utk_read_i16(ctx); + } +} + +/* ************************************************************************************************* */ + +ea_mt_codec_data *init_ea_mt(int channel_count, int pcm_blocks) { + ea_mt_codec_data *data = NULL; + int i; + + data = calloc(channel_count, sizeof(ea_mt_codec_data)); + if (!data) goto fail; + + data->pcm_blocks = pcm_blocks; + data->utk_context_size = channel_count; + + data->utk_context = calloc(channel_count, sizeof(UTKContext*)); + if (!data->utk_context) goto fail; + + for (i = 0; i < channel_count; i++) { + data->utk_context[i] = calloc(1, sizeof(UTKContext)); + if (!data->utk_context[i]) goto fail; + utk_init(data->utk_context[i]); + } + + return data; + +fail: + free_ea_mt(data); + return NULL; +} + +void decode_ea_mt(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + ea_mt_codec_data *data = vgmstream->codec_data; + int i, sample_count = 0, frame_samples; + UTKContext* ctx = data->utk_context[channel]; + + /* Use the above decoder, which expects pointers to read data. Since EA-MT frames aren't + * byte-aligned, reading new buffer data is decided by the decoder. When decoding starts + * or a SCHl block changes flush_ea_mt must be called to reset the state. + * A bit hacky but would need some restructuring otherwise. */ + + frame_samples = 432; + first_sample = first_sample % frame_samples; + + /* don't decode again if we didn't consume the current frame. + * UTKContext saves the sample buffer, and can't re-decode a frame */ + if (!ctx->samples_filled) { + if (data->pcm_blocks) + utk_rev3_decode_frame(ctx); + else + utk_decode_frame(ctx); + ctx->samples_filled = 1; + } + + /* copy samples */ + for (i = first_sample; i < first_sample+samples_to_do; i++) { + int x = UTK_ROUND(ctx->decompressed_frame[i]); + outbuf[sample_count] = (int16_t)UTK_CLAMP(x, -32768, 32767); + sample_count += channelspacing; + } + + if (i == frame_samples) + ctx->samples_filled = 0; +} + +static void flush_ea_mt_internal(VGMSTREAM *vgmstream, int is_start) { + ea_mt_codec_data *data = vgmstream->codec_data; + int i; + size_t bytes; + + /* the decoder needs to be notified when offsets change */ + for (i = 0; i < vgmstream->channels; i++) { + UTKContext *ctx = data->utk_context[i]; + + ctx->streamfile = vgmstream->ch[i].streamfile; + ctx->offset = is_start ? vgmstream->ch[i].channel_start_offset : vgmstream->ch[i].offset; + ctx->samples_filled = 0; + + bytes = read_streamfile(ctx->buffer,ctx->offset,sizeof(ctx->buffer),ctx->streamfile); + ctx->offset += sizeof(ctx->buffer); + ctx->ptr = ctx->buffer; + ctx->end = ctx->buffer + bytes; + ctx->bits_count = 0; + } +} + +void flush_ea_mt(VGMSTREAM *vgmstream) { + flush_ea_mt_internal(vgmstream, 0); +} + +void reset_ea_mt(VGMSTREAM *vgmstream) { + flush_ea_mt_internal(vgmstream, 1); +} + +void seek_ea_mt(VGMSTREAM * vgmstream, int32_t num_sample) { + flush_ea_mt_internal(vgmstream, 1); + //todo discard loop (though this should be adecuate as probably only uses full loops, if at all) +} + +void free_ea_mt(ea_mt_codec_data *data) { + int i; + + if (!data) + return; + + for (i = 0; i < data->utk_context_size; i++) { + free(data->utk_context[i]); + } + free(data->utk_context); + free(data); +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c index 0a9e03ba8..f037d1834 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c @@ -29,59 +29,57 @@ static const int EA_XA_TABLE[20] = { 0, -1, -3, -4 }; -/* EA XA v2; like ea_xa_int but with "PCM samples" flag and doesn't add 128 on expand or clamp (pre-adjusted by the encoder?) */ +/* EA XA v2 (always mono); like ea_xa_int but with "PCM samples" flag and doesn't add 128 on expand or clamp (pre-adjusted by the encoder?) */ void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { uint8_t frame_info; - int32_t sample_count; int32_t coef1, coef2; - int i, shift; - off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */ + int i, sample_count, shift; - first_sample = first_sample%28; + int pcm_frame_size = 0x01 + 2*0x02 + 28*0x02; + int xa_frame_size = 0x0f; + int frame_samples = 28; + first_sample = first_sample % frame_samples; /* header */ - frame_info = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile); - channel_offset++; + frame_info = read_8bit(stream->offset,stream->streamfile); if (frame_info == 0xEE) { /* PCM frame (used in later revisions), samples always BE */ - stream->adpcm_history1_32 = read_16bitBE(stream->offset+channel_offset+0x00,stream->streamfile); - stream->adpcm_history2_32 = read_16bitBE(stream->offset+channel_offset+0x02,stream->streamfile); - channel_offset += 4; + stream->adpcm_history1_32 = read_16bitBE(stream->offset + 0x01 + 0x00,stream->streamfile); + stream->adpcm_history2_32 = read_16bitBE(stream->offset + 0x01 + 0x02,stream->streamfile); for (i=first_sample,sample_count=0; ioffset+channel_offset,stream->streamfile); - channel_offset+=2; + outbuf[sample_count] = read_16bitBE(stream->offset + 0x01 + 2*0x02 + i*0x02,stream->streamfile); } - /* Only increment offset on complete frame */ - if (channel_offset-stream->channel_start_offset == (2*28)+5) - stream->channel_start_offset += (2*28)+5; - - } else { /* ADPCM frame */ + /* only increment offset on complete frame */ + if (i == frame_samples) + stream->offset += pcm_frame_size; + } + else { /* ADPCM frame */ coef1 = EA_XA_TABLE[(frame_info >> 4) + 0]; coef2 = EA_XA_TABLE[(frame_info >> 4) + 4]; shift = (frame_info & 0x0F) + 8; for (i=first_sample,sample_count=0; ioffset + channel_offset + i/2); + int32_t new_sample; + off_t byte_offset = (stream->offset + 0x01 + i/2); + int nibble_shift = (!(i&1)) ? 4 : 0; /* high nibble first */ sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile); - sample_nibble = (!(i%2) ? sample_byte >> 4 : sample_byte & 0x0F); /* i=even > high nibble */ - sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ - sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32) >> 8; - sample = clamp16(sample); + sample_nibble = (sample_byte >> nibble_shift) & 0x0F; + new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ + new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32) >> 8; + new_sample = clamp16(new_sample); - outbuf[sample_count] = sample; + outbuf[sample_count] = new_sample; stream->adpcm_history2_32 = stream->adpcm_history1_32; - stream->adpcm_history1_32 = sample; + stream->adpcm_history1_32 = new_sample; } - channel_offset += i/2; - /* Only increment offset on complete frame */ - if (channel_offset - stream->channel_start_offset == 0x0F) - stream->channel_start_offset += 0x0F; + /* only increment offset on complete frame */ + if (i == frame_samples) + stream->offset += xa_frame_size; } } @@ -90,43 +88,42 @@ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing uint8_t frame_info; int32_t coef1, coef2; int i, sample_count, shift; - off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */ int hn = (channel==0); /* high nibble marker for stereo subinterleave, ch0/L=high nibble, ch1/R=low nibble */ - first_sample = first_sample % 28; + int frame_size = 0x1e; + int frame_samples = 28; + first_sample = first_sample % frame_samples; /* header (coefs ch0+ch1 + shift ch0+ch1) */ - frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); - channel_offset++; + frame_info = read_8bit(stream->offset+0x00,stream->streamfile); coef1 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 0]; coef2 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 4]; shift = (frame_info & 0x0F) + 8; - frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); - channel_offset++; + frame_info = read_8bit(stream->offset+0x01,stream->streamfile); shift = (hn ? frame_info >> 4 : frame_info & 0x0F) + 8; /* samples */ for (i=first_sample,sample_count=0; ioffset + channel_offset + i); + int32_t new_sample; + off_t byte_offset = (stream->offset + 0x02 + i); + int nibble_shift = (hn ? 4 : 0); /* high nibble first */ sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile); - sample_nibble = (hn ? sample_byte >> 4 : sample_byte & 0x0F); - sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ - sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8; - sample = clamp16(sample); + sample_nibble = (sample_byte >> nibble_shift) & 0x0F; + new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ + new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8; + new_sample = clamp16(new_sample); - outbuf[sample_count] = sample; + outbuf[sample_count] = new_sample; stream->adpcm_history2_32 = stream->adpcm_history1_32; - stream->adpcm_history1_32 = sample; + stream->adpcm_history1_32 = new_sample; } - channel_offset += i; - /* Only increment offset on complete frame */ - if(channel_offset - stream->channel_start_offset == 0x1E) - stream->channel_start_offset += 0x1E; + /* only increment offset on complete frame */ + if (i == frame_samples) + stream->offset += frame_size; } /* EA-XA v1 mono/interleave */ @@ -134,13 +131,13 @@ void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa uint8_t frame_info; int32_t coef1, coef2; int i, sample_count, shift; - off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */ - first_sample = first_sample % 28; + int frame_size = 0x0f; + int frame_samples = 28; + first_sample = first_sample % frame_samples; /* header (coefs+shift ch0) */ - frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); - channel_offset++; + frame_info = read_8bit(stream->offset,stream->streamfile); coef1 = EA_XA_TABLE[(frame_info >> 4) + 0]; coef2 = EA_XA_TABLE[(frame_info >> 4) + 4]; shift = (frame_info & 0x0F) + 8; @@ -148,39 +145,38 @@ void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa /* samples */ for (i=first_sample,sample_count=0; ioffset + channel_offset + i/2); + int32_t new_sample; + off_t byte_offset = (stream->offset + 0x01 + i/2); + int nibble_shift = (!(i&1)) ? 4 : 0; /* high nibble first */ sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile); - sample_nibble = (!(i%2) ? sample_byte >> 4 : sample_byte & 0x0F); /* i=even > high nibble */ - sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ - sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8; - sample = clamp16(sample); + sample_nibble = (sample_byte >> nibble_shift) & 0x0F; + new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ + new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8; + new_sample = clamp16(new_sample); - outbuf[sample_count] = sample; + outbuf[sample_count] = new_sample; stream->adpcm_history2_32 = stream->adpcm_history1_32; - stream->adpcm_history1_32 = sample; + stream->adpcm_history1_32 = new_sample; } - channel_offset += i/2; - /* Only increment offset on complete frame */ - if(channel_offset - stream->channel_start_offset == 0x0F) - stream->channel_start_offset += 0x0F; + /* only increment offset on complete frame */ + if (i == frame_samples) + stream->offset += frame_size; } -/* Maxis EA-XA v1 (mono+stereo), differing slightly in the header layout in stereo mode */ +/* Maxis EA-XA v1 (mono+stereo) with byte-interleave layout in stereo mode */ void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { uint8_t frame_info; int32_t coef1, coef2; int i, sample_count, shift; - off_t channel_offset = stream->channel_start_offset; - int frame_size = channelspacing * 15; /* mono samples have a frame of 15, stereo files have frames of 30 */ - first_sample = first_sample % 28; + int frame_size = 0x0f * channelspacing; /* varies in mono/stereo */ + int frame_samples = 28; + first_sample = first_sample % frame_samples; /* header (coefs+shift ch0 + coefs+shift ch1) */ - frame_info = read_8bit(channel_offset,stream->streamfile); - channel_offset += channelspacing; + frame_info = read_8bit(stream->offset + channel,stream->streamfile); coef1 = EA_XA_TABLE[(frame_info >> 4) + 0]; coef2 = EA_XA_TABLE[(frame_info >> 4) + 4]; shift = (frame_info & 0x0F) + 8; @@ -188,27 +184,22 @@ void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac /* samples */ for (i=first_sample,sample_count=0; ioffset + channel_offset); + int32_t new_sample; + off_t byte_offset = (stream->offset + 0x01*channelspacing + (channelspacing == 2 ? i/2 + channel + (i/2)*0x01 : i/2)); + int nibble_shift = (!(i&1)) ? 4 : 0; /* high nibble first */ sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile); - sample_nibble = (i&1) ? sample_byte & 0x0F : sample_byte >> 4; - sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ - sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8; - sample = clamp16(sample); + sample_nibble = (sample_byte >> nibble_shift) & 0x0F; + new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ + new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8; + new_sample = clamp16(new_sample); - outbuf[sample_count] = sample; + outbuf[sample_count] = new_sample; stream->adpcm_history2_32 = stream->adpcm_history1_32; - stream->adpcm_history1_32 = sample; - - if(i&1) - stream->offset+=channelspacing; + stream->adpcm_history1_32 = new_sample; } - channel_offset+=i; - /* Only increment offset on complete frame */ - if (channel_offset - stream->channel_start_offset == frame_size) { - stream->channel_start_offset += frame_size; - stream->offset=0; - } + /* only increment offset on complete frame */ + if (i == frame_samples) + stream->offset += frame_size; } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c index fd703699c..ed3c3d7d2 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c @@ -98,6 +98,8 @@ static void convert_audio(sample *outbuf, const uint8_t *inbuf, int sampleCount, * Fortunately seek_frame_generic can use an index to find the correct position. This function reads the * first frame/packet and sets up index to timestamp 0. This ensures faulty demuxers will seek to 0 correctly. * Some formats may not seek to 0 even with this, though. + * + * todo: some formats don't work with the current index values */ static int init_seek(ffmpeg_codec_data * data) { int ret, ts_index, found_first = 0; @@ -220,6 +222,7 @@ static int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size) { switch(data->config.type) { case FFMPEG_EA_XMA: ret = ffmpeg_custom_read_eaxma(data, buf, buf_size); break; case FFMPEG_SWITCH_OPUS: ret = ffmpeg_custom_read_switch_opus(data, buf, buf_size); break; + case FFMPEG_BGW_ATRAC3: ret = ffmpeg_custom_read_bgw_atrac3(data, buf, buf_size); break; //case FFMPEG_EA_SCHL: ret = ffmpeg_custom_read_ea_schl(data, buf, buf_size); break; //case FFMPEG_SFH: ret = ffmpeg_custom_read_sfh(data, buf, buf_size); break; default: ret = ffmpeg_custom_read_standard(data, buf, buf_size); break; @@ -228,6 +231,7 @@ static int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size) { //data->real_offset = ; /* must be updated in function */ //;VGM_LOG("AVIO read done: ret=%x, r_off=%"PRIx64", v_off=%"PRIx64"\n", ret + max_to_copy, data->real_offset, data->virtual_offset);fflush(stdout); + //;VGM_LOGB((buf - max_to_copy),ret + max_to_copy,0); return ret + max_to_copy; } @@ -287,6 +291,7 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) { switch(data->config.type) { case FFMPEG_EA_XMA: offset = ffmpeg_custom_seek_eaxma(data, offset); break; case FFMPEG_SWITCH_OPUS: offset = ffmpeg_custom_seek_switch_opus(data, offset); break; + case FFMPEG_BGW_ATRAC3: offset = ffmpeg_custom_seek_bgw_atrac3(data, offset); break; //case FFMPEG_EA_SCHL: offset = ffmpeg_custom_seek_ea_schl(data, offset); break; //case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break; default: offset = ffmpeg_custom_seek_standard(data, offset); break; @@ -304,6 +309,7 @@ static int64_t ffmpeg_size(ffmpeg_codec_data * data) { switch(data->config.type) { case FFMPEG_EA_XMA: bytes = ffmpeg_custom_size_eaxma(data); break; case FFMPEG_SWITCH_OPUS: bytes = ffmpeg_custom_size_switch_opus(data); break; + case FFMPEG_BGW_ATRAC3: bytes = ffmpeg_custom_size_bgw_atrac3(data); break; //case FFMPEG_EA_SCHL: bytes = ffmpeg_custom_size_ea_schl(data); break; //case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break; default: bytes = ffmpeg_custom_size_standard(data); break; @@ -800,6 +806,9 @@ void free_ffmpeg(ffmpeg_codec_data *data) { close_streamfile(data->streamfile); data->streamfile = NULL; } + if (data->config.key) { + free(data->config.key); + } free(data); } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c index 2d674d87b..2f718ddf9 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c @@ -16,7 +16,9 @@ int ffmpeg_custom_read_standard(ffmpeg_codec_data *data, uint8_t *buf, int buf_s } int64_t ffmpeg_custom_seek_standard(ffmpeg_codec_data *data, int64_t virtual_offset) { - data->real_offset = data->real_start + (virtual_offset - data->header_size); + int64_t seek_virtual_offset = virtual_offset - data->header_size; + + data->real_offset = data->real_start + seek_virtual_offset; return virtual_offset; } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.h b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.h index 64461fe9f..a7e129123 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.h @@ -31,6 +31,10 @@ int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int bu int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset); int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data); +int ffmpeg_custom_read_bgw_atrac3(ffmpeg_codec_data *data, uint8_t *buf, int buf_size); +int64_t ffmpeg_custom_seek_bgw_atrac3(ffmpeg_codec_data *data, int64_t virtual_offset); +int64_t ffmpeg_custom_size_bgw_atrac3(ffmpeg_codec_data *data); + //int ffmpeg_custom_read_ea_schl(ffmpeg_codec_data *data, uint8_t *buf, int buf_size); //int64_t ffmpeg_custom_seek_ea_schl(ffmpeg_codec_data *data, int64_t virtual_offset); //int64_t ffmpeg_custom_size_ea_schl(ffmpeg_codec_data *data); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_bgw_atrac3.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_bgw_atrac3.c new file mode 100644 index 000000000..5b6bd441d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_bgw_atrac3.c @@ -0,0 +1,58 @@ +#if 1 +#include "coding.h" +#include "ffmpeg_decoder_utils.h" + +#ifdef VGM_USE_FFMPEG + +#define BGM_ATRAC3_FRAME_SIZE 0xC0 + +/** + * Encrypted ATRAC3 used in BGW (Final Fantasy XI PC). + * Info from Moogle Toolbox: https://sourceforge.net/projects/mogbox/ + */ + +int ffmpeg_custom_read_bgw_atrac3(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) { + int i, ch; + size_t bytes; + size_t block_align = BGM_ATRAC3_FRAME_SIZE * data->config.channels; + + + /* init key: first frame + modified channel header */ + if (data->config.key == NULL) { + data->config.key = malloc(block_align); + if (!data->config.key) return 0; + + read_streamfile(data->config.key, data->real_start, block_align, data->streamfile); + for (ch = 0; ch < data->config.channels; ch++) { + uint32_t xor = get_32bitBE(data->config.key + ch*BGM_ATRAC3_FRAME_SIZE); + put_32bitBE(data->config.key + ch*BGM_ATRAC3_FRAME_SIZE, xor ^ 0xA0024E9F); + } + } + + + /* read normally and unXOR the data */ + bytes = read_streamfile(buf, data->real_offset, buf_size, data->streamfile); + for (i = 0; i < bytes; i++) { + int key_pos = (data->real_offset - data->real_start + i) % block_align; + buf[i] = buf[i] ^ data->config.key[key_pos]; + } + + + data->real_offset += bytes; + return bytes; +} + +int64_t ffmpeg_custom_seek_bgw_atrac3(ffmpeg_codec_data *data, int64_t virtual_offset) { + int64_t seek_virtual_offset = virtual_offset - data->header_size; + + data->real_offset = data->real_start + seek_virtual_offset; + return virtual_offset; +} + +int64_t ffmpeg_custom_size_bgw_atrac3(ffmpeg_codec_data *data) { + return data->real_size + data->header_size; +} + + +#endif +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c index 6c79a60b4..fd56320ce 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils_ea_xma.c @@ -3,7 +3,7 @@ #ifdef VGM_USE_FFMPEG -#define EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK 3 /* only seen up to 3 (Dante's Inferno) */ +#define EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK 4 /* normally max 3 (Dante's Inferno), ~14 (1 stream) in Burnout Paradise */ #define EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK 4 /* XMA2 max is 8ch = 4 * 2ch */ #define EAXMA_XMA_PACKET_SIZE 0x800 #define EAXMA_XMA_BUFFER_SIZE (EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK * EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK * EAXMA_XMA_PACKET_SIZE) @@ -48,7 +48,8 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size if (max_packets == 0) goto fail; if (max_packets * num_streams * EAXMA_XMA_PACKET_SIZE > EAXMA_XMA_BUFFER_SIZE) { - VGM_LOG("EA XMA: block too big at %lx\n", (off_t)real_offset); + VGM_LOG("EA XMA: block too big (%i * %i * 0x%x = 0x%x vs max 0x%x) at %lx\n", + max_packets,num_streams,EAXMA_XMA_PACKET_SIZE, max_packets*num_streams*EAXMA_XMA_PACKET_SIZE, EAXMA_XMA_BUFFER_SIZE,(off_t)real_offset); goto fail; } @@ -134,12 +135,13 @@ fail: int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset) { int64_t real_offset, virtual_base; - int64_t current_virtual_offset = data->virtual_offset; + int64_t current_virtual_offset = data->virtual_offset - data->header_size; + int64_t seek_virtual_offset = virtual_offset - data->header_size; /* Find SNS block start closest to offset. ie. virtual_offset 0x1A10 could mean SNS blocks * of 0x456+0x820 padded to 0x800+0x1000 (base) + 0x210 (extra for reads), thus real_offset = 0xC76 */ - if (virtual_offset > current_virtual_offset) { /* seek after current: start from current block */ + if (seek_virtual_offset > current_virtual_offset) { /* seek after current: start from current block */ real_offset = data->real_offset; virtual_base = data->virtual_base; } @@ -150,7 +152,7 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset /* find target block */ - while (virtual_base < virtual_offset) { + while (virtual_base < seek_virtual_offset) { size_t data_size, extra_size = 0; size_t block_size = read_32bitBE(real_offset, data->streamfile); @@ -159,7 +161,7 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset extra_size = EAXMA_XMA_PACKET_SIZE - (data_size % EAXMA_XMA_PACKET_SIZE); /* stop if virtual_offset lands inside current block */ - if (data_size + extra_size > virtual_offset) + if (data_size + extra_size > seek_virtual_offset) break; real_offset += (block_size & 0x00FFFFFF); 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 d8ce46db4..5bc1835e1 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 @@ -101,10 +101,11 @@ int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int bu int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset) { int64_t real_offset, virtual_base; int64_t current_virtual_offset = data->virtual_offset; + int64_t seek_virtual_offset = virtual_offset - data->header_size; /* find Wwise block start closest to offset; a 0x1E8 block expands to 0x1D + 0x1E0 (oggs + data) */ - if (virtual_offset > current_virtual_offset) { /* seek after current: start from current block */ + if (seek_virtual_offset > current_virtual_offset) { /* seek after current: start from current block */ real_offset = data->real_offset; virtual_base = data->virtual_base; } @@ -117,14 +118,14 @@ int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_ /* find target block */ - while (virtual_base < virtual_offset) { + while (virtual_base < seek_virtual_offset) { size_t extra_size; size_t data_size = read_32bitBE(real_offset, data->streamfile); extra_size = 0x1b + (int)(data_size / 0xFF + 1); /* OggS page: base size + lacing values */ /* stop if virtual_offset lands inside current block */ - if (data_size + extra_size > virtual_offset) + if (data_size + extra_size > seek_virtual_offset) break; real_offset += 0x04 + 0x04 + data_size; @@ -332,8 +333,8 @@ fail: static size_t make_opus_comment(uint8_t * buf, int buf_size) { size_t comment_size; int vendor_string_length, user_comment_0_length; - char * vendor_string = "vgmstream"; - char * user_comment_0_string = "vgmstream Opus converter"; + const char * vendor_string = "vgmstream"; + const char * user_comment_0_string = "vgmstream Opus converter"; vendor_string_length = strlen(vendor_string); user_comment_0_length = strlen(user_comment_0_string); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c index 012386421..9c01f8e0d 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/g719_decoder.c @@ -4,6 +4,31 @@ #ifdef VGM_USE_G719 #include "../stack_alloc.h" +g719_codec_data *init_g719(int channel_count, int frame_size) { + int i; + g719_codec_data *data = NULL; + + data = calloc(channel_count, sizeof(g719_codec_data)); /* one decoder per channel */ + if (!data) goto fail; + + for (i = 0; i < channel_count; i++) { + data[i].handle = g719_init(frame_size); /* Siren 22 == 22khz bandwidth */ + if (!data[i].handle) goto fail; + } + + return data; + +fail: + if (data) { + for (i = 0; i < channel_count; i++) { + g719_free(data[i].handle); + } + } + free(data); + + return NULL; +} + void decode_g719(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) { VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel]; g719_codec_data *data = vgmstream->codec_data; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g721_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/g721_decoder.c index 41e147ac4..c035a2239 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g721_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/g721_decoder.c @@ -121,7 +121,7 @@ g72x_init_state( * computes the estimated signal from 6-zero predictor. * */ -int +static int predictor_zero( struct g72x_state *state_ptr) { @@ -139,7 +139,7 @@ predictor_zero( * computes the estimated signal from 2-pole predictor. * */ -int +static int predictor_pole( struct g72x_state *state_ptr) { @@ -152,7 +152,7 @@ predictor_pole( * computes the quantization step size of the adaptive quantizer. * */ -int +static int step_size( struct g72x_state *state_ptr) { @@ -181,7 +181,7 @@ step_size( * codeword 'i' and quantization step size scale factor 'y'. * Multiplication is performed in log base 2 domain as addition. */ -int +static int reconstruct( int sign, /* 0 for non-negative value */ int dqln, /* G.72x codeword */ @@ -210,7 +210,7 @@ reconstruct( * * updates the state variables for each output code */ -void +static void update( /*int code_size,*/ /* distinguish 723_40 with others */ int y, /* quantizer step size */ @@ -427,7 +427,7 @@ static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, * returns the resulting linear PCM, A-law or u-law value. * return -1 for unknown out_coding value. */ -int +static int g721_decoder( int i, struct g72x_state *state_ptr) diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c index 32481ea10..5f5aa761e 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c @@ -3,6 +3,32 @@ #ifdef VGM_USE_G7221 +g7221_codec_data * init_g7221(int channel_count, int frame_size) { + int i; + g7221_codec_data *data = NULL; + + data = calloc(channel_count, sizeof(g7221_codec_data)); /* one decoder per channel */ + if (!data) goto fail; + + for (i = 0; i < channel_count; i++) { + data[i].handle = g7221_init(frame_size, 14000); /* Siren 14 == 14khz bandwidth */ + if (!data[i].handle) goto fail; + } + + return data; + +fail: + if (data) { + for (i = 0; i < channel_count; i++) { + g7221_free(data[i].handle); + } + } + free(data); + + return NULL; +} + + void decode_g7221(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) { VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel]; g7221_codec_data *data = vgmstream->codec_data; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c index 8901653b3..c8f56ef1d 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c @@ -7,17 +7,18 @@ * * All IMAs are mostly the same with these variations: * - interleave: blocks and channels are handled externally (layouts) or internally (mixed channels) - * - block header: none (external), normal (4 bytes of history 16b + step 16b) or others; per channel/global + * - block header: none (external), normal (4 bytes of history 16b + step 8b + reserved 8b) or others; per channel/global * - expand type: ms-ima style or others; low or high nibble first * * todo: - * MS IMAs have the last sample of the prev block in the block header. In Microsoft implementation, the header sample + * MS IMAs have the last sample of the prev block in the block header. In Microsoft's implementation, the header sample * is written first and last sample is skipped (since they match). vgmstream ignores the header sample and * writes the last one instead. This means the very first sample in the first header in a stream is incorrectly skipped. + * Header step should be 8 bit. + * Officially defined in "Microsoft Multimedia Standards Update" doc (RIFFNEW.pdf). */ -static const int32_t ADPCMTable[89] = -{ +static const int ADPCMTable[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, @@ -32,48 +33,32 @@ static const int32_t ADPCMTable[89] = 32767 }; -static const int IMA_IndexTable[16] = -{ +static const int IMA_IndexTable[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; -/* Original IMA */ -static void ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { +/* Standard IMA (most common) */ +static void std_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { int sample_nibble, sample_decoded, step, delta; - //"original" ima nibble expansion - sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; - sample_decoded = *hist1 << 3; - step = ADPCMTable[*step_index]; - delta = step * (sample_nibble & 7) * 2 + step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; + /* calculate diff = [signed] (step / 8) + (step / 4) + (step / 2) + (step) [when code = 4+2+1] + * simplified through math, using bitwise ops to avoid rounding: + * diff = (code + 1/2) * (step / 4) + * > diff = (step * nibble / 4) + (step / 8) + * > diff = (((step * nibble) + (step / 2)) / 4) */ - *hist1 = clamp16(sample_decoded >> 3); - *step_index += IMA_IndexTable[sample_nibble]; - if (*step_index < 0) *step_index=0; - if (*step_index > 88) *step_index=88; -} + sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; /* ADPCM code */ + sample_decoded = *hist1; /* predictor value */ + step = ADPCMTable[*step_index]; /* current step */ -/* Microsoft's IMA (most common) */ -static void ms_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { - int sample_nibble, sample_decoded, step, delta; - - sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; - sample_decoded = *hist1; - step = ADPCMTable[*step_index]; delta = step >> 3; if (sample_nibble & 1) delta += step >> 2; if (sample_nibble & 2) delta += step >> 1; if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; + if (sample_nibble & 8) delta = -delta; + sample_decoded += delta; *hist1 = clamp16(sample_decoded); *step_index += IMA_IndexTable[sample_nibble]; @@ -81,21 +66,20 @@ static void ms_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, i if (*step_index > 88) *step_index=88; } -/* Apple's MS IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend) */ -static void ms_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int16_t * hist1, int32_t * step_index) { +/* Apple's IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend?) */ +static void std_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int16_t * hist1, int32_t * step_index) { int sample_nibble, sample_decoded, step, delta; sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; sample_decoded = *hist1; step = ADPCMTable[*step_index]; + delta = step >> 3; if (sample_nibble & 1) delta += step >> 2; if (sample_nibble & 2) delta += step >> 1; if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; + if (sample_nibble & 8) delta = -delta; + sample_decoded += delta; *hist1 = clamp16(sample_decoded); //no need for this actually *step_index += IMA_IndexTable[sample_nibble]; @@ -103,40 +87,61 @@ static void ms_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset if (*step_index > 88) *step_index=88; } -/* update step_index before doing current sample */ +/* 3DS IMA (Mario Golf, Mario Tennis; maybe other Camelot games) */ +static void n3ds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { + int sample_nibble, sample_decoded, step, delta; + + sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; + sample_decoded = *hist1; + step = ADPCMTable[*step_index]; + + sample_decoded = sample_decoded << 3; + delta = step * (sample_nibble & 7) * 2 + step; /* custom */ + if (sample_nibble & 8) delta = -delta; + sample_decoded += delta; + sample_decoded = sample_decoded >> 3; + + *hist1 = clamp16(sample_decoded); + *step_index += IMA_IndexTable[sample_nibble]; + if (*step_index < 0) *step_index=0; + if (*step_index > 88) *step_index=88; +} + +/* The Incredibles PC, updates step_index before doing current sample */ static void snds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { int sample_nibble, sample_decoded, step, delta; sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; + sample_decoded = *hist1; *step_index += IMA_IndexTable[sample_nibble]; if (*step_index < 0) *step_index=0; if (*step_index > 88) *step_index=88; step = ADPCMTable[*step_index]; - delta = (sample_nibble & 7) * step / 4 + step / 8; + + delta = (sample_nibble & 7) * step / 4 + step / 8; /* standard IMA */ if (sample_nibble & 8) delta = -delta; - sample_decoded = *hist1 + delta; + sample_decoded += delta; *hist1 = clamp16(sample_decoded); } -/* algorithm by aluigi, unsure if it's a known IMA variation */ +/* Omikron: The Nomad Soul, algorithm by aluigi */ static void otns_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { int sample_nibble, sample_decoded, step, delta; sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; sample_decoded = *hist1; step = ADPCMTable[*step_index]; + delta = 0; if(sample_nibble & 4) delta = step << 2; if(sample_nibble & 2) delta += step << 1; if(sample_nibble & 1) delta += step; delta >>= 2; - if(sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; + if (sample_nibble & 8) delta = -delta; + sample_decoded += delta; *hist1 = clamp16(sample_decoded); *step_index += IMA_IndexTable[sample_nibble]; @@ -144,283 +149,53 @@ static void otns_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, if (*step_index > 88) *step_index=88; } +/* Ubisoft games, algorithm by Zench (https://bitbucket.org/Zenchreal/decubisnd) */ +static void ubi_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { + int sample_nibble, sample_decoded, step, delta; -void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i, sample_count; + sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; + sample_decoded = *hist1; + step = ADPCMTable[*step_index]; - int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? - int step_index = stream->adpcm_step_index; + delta = (((sample_nibble & 7) * 2 + 1) * step) >> 3; /* custom */ + if (sample_nibble & 8) delta = -delta; + sample_decoded += delta; - //external interleave - - //normal header - if (first_sample == 0) { - off_t header_offset = stream->offset; - - hist1 = read_16bitLE(header_offset,stream->streamfile); - step_index = read_16bitLE(header_offset+2,stream->streamfile); - - //todo clip step_index? - } - - for (i=first_sample,sample_count=0; ioffset + 4 + i/2; - int nibble_shift = (i&1?4:0); //low nibble first - - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); - } - - stream->adpcm_history1_16 = hist1; - stream->adpcm_step_index = step_index; + *hist1 = clamp16(sample_decoded); + *step_index += IMA_IndexTable[sample_nibble]; + if (*step_index < 0) *step_index=0; + if (*step_index > 88) *step_index=88; } -void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i, sample_count; +/* ************************************ */ +/* DVI/IMA */ +/* ************************************ */ - int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? - int step_index = stream->adpcm_step_index; - - //external interleave - - //normal header - if (first_sample == 0) { - off_t header_offset = stream->offset; - - hist1 = read_16bitLE(header_offset,stream->streamfile); - step_index = read_8bit(header_offset+2,stream->streamfile); //todo use 8bit in all MS IMA? - - //todo clip step_index? - } - - for (i=first_sample,sample_count=0; ioffset + 4 + i/2; - int nibble_shift = (i&1?0:4); //high nibble first - - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); - } - - stream->adpcm_history1_16 = hist1; - stream->adpcm_step_index = step_index; -} - -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; - - 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; - 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; - } - - 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 - - ms_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; -} - -void decode_rad_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_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels; - first_sample = first_sample % block_samples; - - //inverted header (per channel) - if (first_sample == 0) { - off_t header_offset = stream->offset + 4*channel; - - step_index = read_16bitLE(header_offset,stream->streamfile); - hist1 = read_16bitLE(header_offset+2,stream->streamfile); - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + channel + i/2*vgmstream->channels; - int nibble_shift = (i&1?4:0); //low nibble first - - ms_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; -} - -void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i, sample_count; - - int32_t hist1 = stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - //semi-external interleave? - int block_samples = 0x14 * 2; - first_sample = first_sample % block_samples; - - //inverted header - if (first_sample == 0) { - off_t header_offset = stream->offset; - - step_index = read_16bitLE(header_offset,stream->streamfile); - hist1 = read_16bitLE(header_offset+2,stream->streamfile); - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ioffset + 4 + i/2; - int nibble_shift = (i&1?4:0); //low nibble first - - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); - } - - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_index; -} - -/* For multichannel the internal 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; - - int32_t hist1 = stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - off_t offset = stream->offset; - - //internal interleave (0x20+4 size), mixed channels (4 byte per ch, mixed stereo) - int block_samples = (vgmstream->channels==1) ? - 32 : - 32*(vgmstream->channels&2);//todo this can be zero in 4/5/8ch = SEGFAULT using % below - first_sample = first_sample % block_samples; - - //normal header (per channel) - if (first_sample == 0) { - off_t header_offset; - header_offset = stream->offset + 4*(channel%2); - - hist1 = read_16bitLE(header_offset,stream->streamfile); - step_index = read_16bitLE(header_offset+2,stream->streamfile); - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ioffset + 4*(channel%2) + 4 + i/8*4 + (i%8)/2 : - stream->offset + 4*(channel%2) + 4*2 + i/8*4*2 + (i%8)/2; - nibble_shift = (i&1?4:0); //low nibble first - - ms_ima_expand_nibble(stream, offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); - } - - //internal interleave: increment offset on complete frame - if (channelspacing==1) { - if(offset-stream->offset==32+3) // ?? - stream->offset+=36; - } else { - if(offset-stream->offset==64+(4*(channel%2))+3) // ?? - stream->offset+=36*channelspacing; - } - - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_index; -} - -/* mono XBOX ADPCM for interleave */ -void decode_xbox_ima_int(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { +/* Standard DVI/IMA ADPCM (as in, ADPCM recommended by the IMA using Intel/DVI's implementation). + * Configurable: stereo or mono/interleave nibbles, and high or low nibble first. + * For vgmstream, low nibble is called "IMA ADPCM" and high nibble is "DVI IMA ADPCM" (same thing though). */ +void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first) { int i, sample_count = 0; int32_t hist1 = stream->adpcm_history1_32; int step_index = stream->adpcm_step_index; - //internal interleave (0x24 size), mono - int block_samples = (0x24 - 0x4) * 2; /* block size - header, 2 samples per byte */ - first_sample = first_sample % block_samples; + /* external interleave */ - //normal header - if (first_sample == 0) { - off_t header_offset = stream->offset; + /* no header (external setup), pre-clamp for wrong values */ + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; - hist1 = read_16bitLE(header_offset,stream->streamfile); - step_index = read_16bitLE(header_offset+2,stream->streamfile); - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; + /* decode nibbles */ + for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) { + off_t byte_offset = is_stereo ? + stream->offset + i : /* stereo: one nibble per channel */ + stream->offset + i/2; /* mono: consecutive nibbles */ + int nibble_shift = is_high_first ? + is_stereo ? (!(channel&1) ? 4:0) : (!(i&1) ? 4:0) : /* even = high, odd = low */ + is_stereo ? (!(channel&1) ? 0:4) : (!(i&1) ? 0:4); /* even = low, odd = high */ - //must write history from header as last nibble/sample in block is almost always 0 / not encoded - outbuf[sample_count] = (short)(hist1); - sample_count += channelspacing; - first_sample += 1; - samples_to_do -= 1; - } - - for (i=first_sample; i < first_sample + samples_to_do; i++) { /* first_sample + samples_to_do should be block_samples at most */ - off_t byte_offset = stream->offset + 4 + (i-1)/2; - int nibble_shift = ((i-1)&1?4:0); //low nibble first - - //last nibble/sample in block is ignored (next header sample contains it) - if (i < block_samples) { - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); - sample_count+=channelspacing; - } - } - - //internal interleave: increment offset on complete frame; layout test so it works in full mono - // (EA SCHl, internally moves offset) or full interleave (XBOX ADS, externally moves offset in layout) - if (i == block_samples && vgmstream->layout_type != layout_interleave) - stream->offset += 0x24; /*full mono */ - - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_index; -} - -void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i, sample_count; - - int32_t hist1 = stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - //external interleave - - //no header - - for (i=first_sample,sample_count=0; ioffset + i/2; - int nibble_shift = (i&1?0:4); //high nibble first (old-style DVI) - - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); outbuf[sample_count] = (short)(hist1); } @@ -428,35 +203,7 @@ void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci stream->adpcm_step_index = step_index; } -/* basically DVI stereo (high=L + low=R nibbles) and DVI mono (high=L, low=L) all-in-one, can be simplified/removed */ -void decode_eacs_ima(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { - VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);//todo pass externally for consistency - int i, sample_count; - - int32_t hist1 = stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - //external interleave - - //no header - - for (i=first_sample,sample_count=0; ioffset + i/2 : /* mono mode */ - stream->offset + i; /* stereo mode */ - int nibble_shift = channelspacing == 1 ? - (!(i%2) ? 4:0) : /* mono mode (high first) */ - (channel==0 ? 4:0); /* stereo mode (high=L,low=R) */ - - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); - outbuf[sample_count] = (short)(hist1); - } - - stream->adpcm_history1_32 = hist1; - stream->adpcm_step_index = step_index; -} - -void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { +void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { int i, sample_count; int32_t hist1 = stream->adpcm_history1_32; @@ -470,7 +217,7 @@ void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, off_t byte_offset = stream->offset + i/2; int nibble_shift = (i&1?4:0); //low nibble order - ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + n3ds_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); outbuf[sample_count] = (short)(hist1); } @@ -478,38 +225,6 @@ void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, stream->adpcm_step_index = step_index; } -void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i, sample_count; - - int16_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? - int step_index = stream->adpcm_step_index; - - off_t packet_offset = stream->offset + first_sample/64*34; - - //semi-internal interleave //todo what - int block_samples = 64; - first_sample = first_sample % block_samples; - - //2-byte header - if (first_sample == 0) { - hist1 = (int16_t)((uint16_t)read_16bitBE(packet_offset,stream->streamfile) & 0xff80); - step_index = read_8bit(packet_offset+1,stream->streamfile) & 0x7f; - - //todo no clamp - } - - for (i=first_sample,sample_count=0; iadpcm_history1_16 = hist1; - stream->adpcm_step_index = step_index; -} - void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { int i, sample_count; @@ -556,6 +271,300 @@ void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * stream->adpcm_step_index = step_index; } +/* ************************************ */ +/* 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; + + 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; + 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; + } + + 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 + + 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; +} + +/* MS IMA with fixed frame size 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; + + int32_t hist1 = stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + off_t offset = stream->offset; + + //internal interleave (0x20+4 size), mixed channels (4 byte per ch, mixed stereo) + int block_samples = (vgmstream->channels==1) ? + 32 : + 32*(vgmstream->channels&2);//todo this can be zero in 4/5/8ch = SEGFAULT using % below + first_sample = first_sample % block_samples; + + //normal header (per channel) + if (first_sample == 0) { + off_t header_offset; + header_offset = stream->offset + 4*(channel%2); + + hist1 = read_16bitLE(header_offset,stream->streamfile); + step_index = read_16bitLE(header_offset+2,stream->streamfile); + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4*(channel%2) + 4 + i/8*4 + (i%8)/2 : + stream->offset + 4*(channel%2) + 4*2 + i/8*4*2 + (i%8)/2; + nibble_shift = (i&1?4:0); //low nibble first + + std_ima_expand_nibble(stream, offset,nibble_shift, &hist1, &step_index); + outbuf[sample_count] = (short)(hist1); + } + + //internal interleave: increment offset on complete frame + if (channelspacing==1) { + if(offset-stream->offset==32+3) // ?? + stream->offset+=36; + } else { + if(offset-stream->offset==64+(4*(channel%2))+3) // ?? + stream->offset+=36*channelspacing; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + +/* mono XBOX 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; + int step_index = stream->adpcm_step_index; + + //external interleave + int block_samples = (0x24 - 0x4) * 2; /* block size - header, 2 samples per byte */ + num_frame = first_sample / block_samples; + first_sample = first_sample % block_samples; + + //normal header + if (first_sample == 0) { + off_t header_offset = stream->offset + 0x24*num_frame; + + 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; + + //must write history from header as last nibble/sample in block is almost always 0 / not encoded + outbuf[sample_count] = (short)(hist1); + sample_count += channelspacing; + first_sample += 1; + samples_to_do -= 1; + } + + for (i=first_sample; i < first_sample + samples_to_do; i++) { /* first_sample + samples_to_do should be block_samples at most */ + off_t byte_offset = (stream->offset + 0x24*num_frame + 0x4) + (i-1)/2; + int nibble_shift = ((i-1)&1?4:0); //low nibble first + + //last nibble/sample in block is ignored (next header sample contains it) + if (i < block_samples) { + std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + outbuf[sample_count] = (short)(hist1); + sample_count += channelspacing; + } + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + +void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_count; + + int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? + int step_index = stream->adpcm_step_index; + + //external interleave + + //normal header + if (first_sample == 0) { + off_t header_offset = stream->offset; + + hist1 = read_16bitLE(header_offset,stream->streamfile); + step_index = read_16bitLE(header_offset+2,stream->streamfile); + + //todo clip step_index? + } + + for (i=first_sample,sample_count=0; ioffset + 4 + 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); + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_index; +} + +void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_count; + + int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? + int step_index = stream->adpcm_step_index; + + //external interleave + + //normal header + if (first_sample == 0) { + off_t header_offset = stream->offset; + + hist1 = read_16bitLE(header_offset,stream->streamfile); + step_index = read_8bit(header_offset+2,stream->streamfile); + + //todo clip step_index? + } + + for (i=first_sample,sample_count=0; ioffset + 4 + i/2; + int nibble_shift = (i&1?0:4); //high nibble first + + std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + outbuf[sample_count] = (short)(hist1); + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_index; +} + +void decode_rad_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_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels; + first_sample = first_sample % block_samples; + + //inverted header (per channel) + if (first_sample == 0) { + off_t header_offset = stream->offset + 4*channel; + + step_index = read_16bitLE(header_offset,stream->streamfile); + hist1 = read_16bitLE(header_offset+2,stream->streamfile); + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + channel + i/2*vgmstream->channels; + 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; +} + +void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_count; + + int32_t hist1 = stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + //semi-external interleave? + int block_samples = 0x14 * 2; + first_sample = first_sample % block_samples; + + //inverted header + if (first_sample == 0) { + off_t header_offset = stream->offset; + + step_index = read_16bitLE(header_offset,stream->streamfile); + hist1 = read_16bitLE(header_offset+2,stream->streamfile); + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4 + 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); + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + +void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i, sample_count, num_frame; + int16_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? + int step_index = stream->adpcm_step_index; + + //external interleave + int block_samples = (0x22 - 0x2) * 2; + num_frame = first_sample / block_samples; + first_sample = first_sample % block_samples; + + //2-byte header + if (first_sample == 0) { + off_t header_offset = stream->offset + 0x22*num_frame; + + hist1 = (int16_t)((uint16_t)read_16bitBE(header_offset,stream->streamfile) & 0xff80); + step_index = read_8bit(header_offset+1,stream->streamfile) & 0x7f; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 0x22*num_frame + 0x2) + i/2; + int nibble_shift = (i&1?4:0); //low nibble first + + std_ima_expand_nibble_16(stream, byte_offset,nibble_shift, &hist1, &step_index); + outbuf[sample_count] = (short)(hist1); + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_index; +} + 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; @@ -581,7 +590,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o off_t byte_offset = stream->offset + 4*vgmstream->channels + 2*channel + i/4*2*vgmstream->channels + (i%4)/2;//2-byte per channel int nibble_shift = (i&1?4:0); //low nibble first - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); outbuf[sample_count] = (short)(hist1); } @@ -626,7 +635,7 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * //last nibble/sample in block is ignored (next header sample contains it) if (i < block_samples) { - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + 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 @@ -667,7 +676,7 @@ void decode_ref_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * ou off_t byte_offset = stream->offset + 4*vgmstream->channels + block_channel_size*channel + i/2; int nibble_shift = (i&1?4:0); //low nibble first - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); outbuf[sample_count] = (short)(hist1); } @@ -702,7 +711,7 @@ void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci off_t byte_offset = stream->offset + 4 + i/2; int nibble_shift = (i&1?4:0); //low nibble first - ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); outbuf[sample_count] = (short)(hist1); } @@ -714,6 +723,67 @@ void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci } +/* DVI stereo/mono with some mini header and sample output */ +void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i, sample_count = 0; + + int32_t hist1 = stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + //internal interleave + + //header in the beginning of the stream + if (stream->channel_start_offset == stream->offset) { + int version, big_endian, header_samples, max_samples_to_do; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + off_t offset = stream->offset; + + /* header fields mostly unknown (vary a lot or look like flags), + * 0x07 0x06 = major/minor tool version?, 0x0c: stereo flag? */ + version = read_8bit(offset + 0x00, stream->streamfile); + big_endian = version < 5; //todo and sb.big_endian? + read_16bit = big_endian ? read_16bitBE : read_16bitLE; + + header_samples = read_16bit(offset + 0x0E, stream->streamfile); /* always 10 (per channel) */ + hist1 = read_16bit(offset + 0x10 + channel*0x04,stream->streamfile); + step_index = read_8bit(offset + 0x12 + channel*0x04,stream->streamfile); + offset += 0x10 + 0x08 + 0x04; //todo v6 has extra 0x08? + + /* write PCM samples, must be written to match header's num_samples (hist mustn't) */ + max_samples_to_do = ((samples_to_do > header_samples) ? header_samples : samples_to_do); + for (i = first_sample; i < max_samples_to_do; i++, sample_count += channelspacing) { + outbuf[sample_count] = read_16bit(offset + channel*sizeof(sample) + i*channelspacing*sizeof(sample),stream->streamfile); + first_sample++; + samples_to_do--; + } + + /* header done */ + if (i == header_samples) { + stream->offset = offset + header_samples*channelspacing*sizeof(sample); + } + } + + + first_sample -= 10; //todo fix hack (needed to adjust nibble offset below) + + for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) { + off_t byte_offset = channelspacing == 1 ? + stream->offset + i/2 : /* mono mode */ + stream->offset + i; /* stereo mode */ + int nibble_shift = channelspacing == 1 ? + (!(i%2) ? 4:0) : /* mono mode (high first) */ + (channel==0 ? 4:0); /* stereo mode (high=L,low=R) */ + + ubi_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); + outbuf[sample_count] = (short)(hist1); /* all samples are written */ + } + + //external interleave + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + 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) */ @@ -724,3 +794,19 @@ size_t ima_bytes_to_samples(size_t bytes, int channels) { /* 2 samples per byte (2 nibbles) in stereo or mono config */ return bytes / channels * 2; } + +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; + size_t header_size = 0; + + version = read_8bit(offset + 0x00, streamFile); + big_endian = version < 5; //todo and sb.big_endian? + read_16bit = big_endian ? read_16bitBE : read_16bitLE; + + header_samples = read_16bit(offset + 0x0E, streamFile); /* always 10 (per channel) */ + header_size += 0x10 + 0x04 * channels + 0x04; //todo v6 has extra 0x08? + header_size += header_samples * channels * sizeof(sample); + + return header_samples + ima_bytes_to_samples(bytes - header_size, channels); +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c index ae1f244c9..dd481741b 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils.c @@ -38,7 +38,8 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m { int current_data_size = info.frame_size; int current_padding = 0; - if (info.layer == 3 && data->config.fsb_padding) { /* FSB padding for Layer III */ + /* FSB padding for Layer III or multichannel Layer II */ + if ((info.layer == 3 && data->config.fsb_padding) || data->config.fsb_padding == 16) { current_padding = (current_data_size % data->config.fsb_padding) ? data->config.fsb_padding - (current_data_size % data->config.fsb_padding) : 0; @@ -59,7 +60,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m case MPEG_STANDARD: case MPEG_AHX: case MPEG_EA: - if (data->channels_per_frame != data->config.channels) + if (info.channels != data->config.channels) goto fail; /* no multichannel expected */ break; @@ -70,6 +71,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m //todo: test more: this improves the output, but seems formats aren't usually prepared // (and/or the num_samples includes all possible samples in file, so by discarding some it'll reach EOF) + // FSBs (with FMOD DLLs) don't seem to need it, even when files contain garbage at the beginning #if 0 /* set encoder delay (samples to skip at the beginning of a stream) if needed, which varies with encoder used */ switch(data->type) { @@ -87,7 +89,8 @@ fail: /* writes data to the buffer and moves offsets */ -int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data) { +int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) { + mpeg_custom_stream *ms = data->streams[num_stream]; mpeg_frame_info info; size_t current_data_size = 0; size_t current_padding = 0; @@ -108,9 +111,9 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d goto fail; current_data_size = info.frame_size; - /* get FSB padding for Layer III (Layer II doesn't use it, and Layer I doesn't seem to be supported) */ - /* Padding sometimes contains garbage like the next frame header so we can't feed it to mpg123 or it gets confused. */ - if (info.layer == 3 && data->config.fsb_padding) { + /* get FSB padding for Layer III or multichannel Layer II (Layer I doesn't seem to be supported) + * Padding sometimes contains garbage like the next frame header so we can't feed it to mpg123 or it gets confused. */ + if ((info.layer == 3 && data->config.fsb_padding) || data->config.fsb_padding == 16) { current_padding = (current_data_size % data->config.fsb_padding) ? data->config.fsb_padding - (current_data_size % data->config.fsb_padding) : 0; @@ -135,14 +138,14 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d current_data_size = info.frame_size; break; } - if (!current_data_size || current_data_size > data->buffer_size) { + if (!current_data_size || current_data_size > ms->buffer_size) { VGM_LOG("MPEG: incorrect data_size 0x%x\n", current_data_size); goto fail; } /* read single frame */ - data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset, current_data_size, stream->streamfile); + ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset, current_data_size, stream->streamfile); /* update offsets */ @@ -233,6 +236,7 @@ int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info * case 384: info->frame_size = (12l * info->bit_rate * 1000l / info->sample_rate + padding) * 4; break; case 576: info->frame_size = (72l * info->bit_rate * 1000l / info->sample_rate + padding); break; case 1152: info->frame_size = (144l * info->bit_rate * 1000l / info->sample_rate + padding); break; + default: goto fail; } return 1; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ahx.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ahx.c index b29979922..f6c3f7167 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ahx.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ahx.c @@ -3,11 +3,12 @@ #ifdef VGM_USE_MPEG #define MPEG_AHX_EXPECTED_FRAME_SIZE 0x414 -static int ahx_decrypt_type08(mpeg_codec_data *data); +static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config); /* writes data to the buffer and moves offsets, transforming AHX frames as needed */ -int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data) { +int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) { /* 0xFFF5E0C0 header: frame size 0x414 (160kbps, 22050Hz) but they actually are much shorter */ + mpeg_custom_stream *ms = data->streams[num_stream]; size_t current_data_size = 0; size_t file_size = get_streamfile_size(stream->streamfile); @@ -33,22 +34,22 @@ int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data) next_offset++; } } - if (!current_data_size || current_data_size > data->buffer_size || current_data_size > MPEG_AHX_EXPECTED_FRAME_SIZE) { + if (!current_data_size || current_data_size > ms->buffer_size || current_data_size > MPEG_AHX_EXPECTED_FRAME_SIZE) { VGM_LOG("MPEG AHX: incorrect data_size 0x%x\n", current_data_size); goto fail; } /* 0-fill up to expected size to keep mpg123 happy */ - data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset,current_data_size,stream->streamfile); - memset(data->buffer + data->bytes_in_buffer,0, MPEG_AHX_EXPECTED_FRAME_SIZE - data->bytes_in_buffer); - data->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE; + ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset,current_data_size,stream->streamfile); + memset(ms->buffer + ms->bytes_in_buffer,0, MPEG_AHX_EXPECTED_FRAME_SIZE - ms->bytes_in_buffer); + ms->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE; /* decrypt if needed */ switch(data->config.encryption) { case 0x00: break; - case 0x08: ahx_decrypt_type08(data); break; + case 0x08: ahx_decrypt_type08(ms->buffer, &data->config); break; default: VGM_LOG("MPEG AHX: unknown encryption 0x%x\n", data->config.encryption); break; /* garbled frame */ @@ -66,7 +67,7 @@ fail: } /* Decrypts an AHX type 0x08 (keystring) encrypted frame. Algorithm by Thealexbarney */ -static int ahx_decrypt_type08(mpeg_codec_data *data) { +static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config) { int i, index, encrypted_bits; uint32_t value; uint16_t current_key; @@ -78,18 +79,18 @@ static int ahx_decrypt_type08(mpeg_codec_data *data) { /* read 2b from a bitstream offset to decrypt, and use it as an index to get the key. * AHX encrypted bitstream starts at 107b (0x0d*8+3), every frame, and seem to always use index 2 */ - value = (uint32_t)get_32bitBE(data->buffer + 0x0d); + value = (uint32_t)get_32bitBE(buffer + 0x0d); index = (value >> (32-3-2)) & 0x03; switch(index) { case 0: current_key = 0; break; - case 1: current_key = data->config.cri_key1; break; - case 2: current_key = data->config.cri_key2; break; - case 3: current_key = data->config.cri_key3; break; + case 1: current_key = config->cri_key1; break; + case 2: current_key = config->cri_key2; break; + case 3: current_key = config->cri_key3; break; default: goto fail; } /* AHX for DC: 16b, normal: 6b (no idea, probably some Layer II field) */ - encrypted_bits = data->config.cri_type == 0x10 ? 16 : 6; + encrypted_bits = config->cri_type == 0x10 ? 16 : 6; /* decrypt next bitstream 2b pairs, up to 16b (max key size): * - read 2b from bitstream (from higher to lower) @@ -101,7 +102,7 @@ static int ahx_decrypt_type08(mpeg_codec_data *data) { } /* write output */ - put_32bitBE(data->buffer + 0x0d, value); + put_32bitBE(buffer + 0x0d, value); return 1; fail: diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c index 9d229dce7..4701975d5 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_awc.c @@ -170,7 +170,7 @@ int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, goto fail; current_data_size = info.frame_size; - data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset, current_data_size, stream->streamfile); + ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset, current_data_size, stream->streamfile); stream->offset += current_data_size; 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 b233b3bfb..84f6cc746 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ealayer3.c @@ -7,11 +7,12 @@ * with regular MPEG data and optional PCM blocks. We transform EA-frames to MPEG-frames on the fly * and manually fill the sample PCM sample buffer. * - * Layer III MPEG1 uses two granules (data chunks) per frame, while MPEG2/2.5 ("LSF mode") only one. EA-frames - * contain one granule, so to reconstruct one MPEG-frame we need two EA-frames (MPEG1) or one (MPEG2). + * Layer III MPEG1 uses two granules (data chunks) per frame, while MPEG2/2.5 ("LSF mode") only one. + * EA-frames contain one granule, so to reconstruct one MPEG-frame we need two EA-frames (MPEG1) or + * one (MPEG2). This is only for our decoder, real EALayer3 would decode EA-frames directly. * EALayer v1 and v2 differ in part of the header, but are mostly the same. * - * Reverse engineering: https://bitbucket.org/Zenchreal/ealayer3 (ealayer3.exe decoder) + * Reverse engineering by Zench: https://bitbucket.org/Zenchreal/ealayer3 (ealayer3.exe decoder) * Reference: https://www.mp3-tech.org/programmer/docs/mp3_theory.pdf * https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/mpegaudiodec_template.c#L1306 */ @@ -24,27 +25,20 @@ #define EALAYER3_MAX_GRANULES 2 #define EALAYER3_MAX_CHANNELS 2 -/* helper to simulate a bitstream */ -typedef struct { - uint8_t * buf; /* buffer to read/write*/ - size_t bufsize; /* max size of the buffer */ - off_t b_off; /* current offset in bits inside the buffer */ - off_t offset; /* info only */ -} ealayer3_bitstream; - /* parsed info from a single EALayer3 frame */ typedef struct { /* EALayer3 v1 header */ uint32_t v1_pcm_flag; uint32_t v1_pcm_decode_discard; uint32_t v1_pcm_number; + uint32_t v1_pcm_unknown; /* EALayer3 v2 header */ uint32_t v2_extended_flag; uint32_t v2_stereo_flag; uint32_t v2_unknown; /* unused? */ uint32_t v2_frame_size; /* full size including headers and pcm block */ - uint32_t v2_mode; /* BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3 */ + uint32_t v2_mode; /* discard mode */ uint32_t v2_mode_value; /* samples to use depending on mode */ uint32_t v2_pcm_number; uint32_t v2_common_size; /* common header+data size; can be zero */ @@ -79,32 +73,26 @@ typedef struct { } ealayer3_frame_info; -static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf); -static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame); -static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf); -static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf); -static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os); +static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf); +static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b); +static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf); +static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf); +static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os); static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf); - -static int r_bits(ealayer3_bitstream * iw, int num_bits, uint32_t * value); -static int w_bits(ealayer3_bitstream * ow, int num_bits, uint32_t value); - +static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start); /* **************************************************************************** */ /* EXTERNAL API */ /* **************************************************************************** */ -/* init codec from a EALayer3 frame */ +/* init codec from an EALayer3 frame */ int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type) { int ok; ealayer3_frame_info eaf; - ealayer3_bitstream is; + vgm_bitstream is = {0}; uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE]; - //;VGM_LOG("EAFRAME: EALayer3 init at %lx\n", start_offset); - - if (data->type == MPEG_EAL32P || data->type == MPEG_EAL32S) - goto fail; /* untested */ + //;VGM_LOG("init at %lx\n", start_offset); /* get first frame for info */ { @@ -115,20 +103,12 @@ int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, ok = ealayer3_parse_frame(data, &is, &eaf); if (!ok) goto fail; } - - ;VGM_ASSERT(!eaf.mpeg1, "MPEG EAL3: mpeg2 found at 0x%lx\n", start_offset); + VGM_ASSERT(!eaf.mpeg1, "MPEG EAL3: mpeg2 found at 0x%lx\n", start_offset); /* untested */ *coding_type = coding_MPEG_ealayer3; data->channels_per_frame = eaf.channels; data->samples_per_frame = eaf.mpeg1 ? 1152 : 576; - /* extra checks */ - if (!data->channels_per_frame || data->config.channels != data->channels_per_frame){ - VGM_LOG("MPEG EAL3: unknown %i multichannel layout\n", data->config.channels); - goto fail; /* unknown layout */ - } - - /* encoder delay: EALayer3 handles this while decoding (skips samples as writes PCM blocks) */ return 1; @@ -138,15 +118,20 @@ fail: /* writes data to the buffer and moves offsets, transforming EALayer3 frames */ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) { - int ok; - off_t current_offset = stream->offset; + mpeg_custom_stream *ms = data->streams[num_stream]; + int ok, granule_found; + off_t info_offset = stream->offset; ealayer3_frame_info eaf_0, eaf_1; - ealayer3_bitstream is_0, is_1, os; + vgm_bitstream is_0 = {0}, is_1 = {0}, os = {0}; uint8_t ibuf_0[EALAYER3_EA_FRAME_BUFFER_SIZE], ibuf_1[EALAYER3_EA_FRAME_BUFFER_SIZE]; - /* read first frame/granule */ - { + /* read first frame/granule, or PCM-only frame (found alone at the end of SCHl streams) */ + { + //;VGM_LOG("s%i: get granule0 at %lx\n", num_stream,stream->offset); + if (!ealayer3_skip_data(stream, data, num_stream, 1)) + goto fail; + is_0.buf = ibuf_0; is_0.bufsize = read_streamfile(ibuf_0,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */ is_0.b_off = 0; @@ -158,51 +143,54 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data * if (!ok) goto fail; stream->offset += eaf_0.eaframe_size; - } + //;VGM_LOG("s%i: get granule0 done at %lx (eaf_size=%x, common_size=%x)\n", num_stream,stream->offset, eaf_0.eaframe_size, eaf_0.common_size); - /* get second frame/granule */ - if (eaf_0.mpeg1) { - int granule1_found; - do { - is_1.buf = ibuf_1; - is_1.bufsize = read_streamfile(ibuf_1,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */ - is_1.b_off = 0; + if (!ealayer3_skip_data(stream, data, num_stream, 0)) + goto fail; - ok = ealayer3_parse_frame(data, &is_1, &eaf_1); - if (!ok) goto fail; + } - ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_1); - if (!ok) goto fail; + /* get second frame/granule (MPEG1 only) if first granule was found */ + granule_found = 0; + while (eaf_0.common_size && eaf_0.mpeg1 && !granule_found) { + //;VGM_LOG("s%i: get granule1 at %lx\n", num_stream,stream->offset); + if (!ealayer3_skip_data(stream, data, num_stream, 1)) + goto fail; - stream->offset += eaf_1.eaframe_size; + is_1.buf = ibuf_1; + is_1.bufsize = read_streamfile(ibuf_1,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */ + is_1.b_off = 0; + ok = ealayer3_parse_frame(data, &is_1, &eaf_1); + if (!ok) goto fail; - /* in V1 sometimes there is a PCM block between two granules, try next */ - if (eaf_1.v1_pcm_flag == 0xEE) - granule1_found = 0; - else - granule1_found = 1; /* assume it does (bad infinite loops) */ - } - while(!granule1_found); - } - else { - memset(&eaf_1, 0, sizeof(ealayer3_frame_info)); + ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_1); + if (!ok) goto fail; + + stream->offset += eaf_1.eaframe_size; + //;VGM_LOG("s%i: get granule0 done at %lx (eaf_size=%x, common_size=%x)\n", num_stream,stream->offset, eaf_0.eaframe_size, eaf_0.common_size); + + if (!ealayer3_skip_data(stream, data, num_stream, 0)) + goto fail; + + /* in V1a there may be PCM-only frames between granules so read until next one (or parse fails) */ + if (eaf_1.common_size > 0) + granule_found = 1; } /* rebuild EALayer frame to MPEG frame */ { - os.buf = data->buffer; - os.bufsize = data->buffer_size; + os.buf = ms->buffer; + os.bufsize = ms->buffer_size; os.b_off = 0; - os.offset = current_offset; + os.info_offset = info_offset; ok = ealayer3_rebuild_mpeg_frame(&is_0, &eaf_0, &is_1, &eaf_1, &os); if (!ok) goto fail; - data->bytes_in_buffer = os.b_off / 8; /* wrote full MPEG frame, hopefully */ + ms->bytes_in_buffer = os.b_off / 8; /* wrote full MPEG frame, hopefully */ } - return 1; fail: return 0; @@ -213,31 +201,29 @@ fail: /* INTERNAL HELPERS */ /* **************************************************************************** */ -static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf) { +static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf) { int ok; + /* make sure as there is re-parsing in loops */ memset(eaf, 0, sizeof(ealayer3_frame_info)); switch(data->type) { - case MPEG_EAL31: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame); break; + case MPEG_EAL31: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame, 0); break; + case MPEG_EAL31b: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame, 1); break; case MPEG_EAL32P: case MPEG_EAL32S: ok = ealayer3_parse_frame_v2(is, eaf); break; default: goto fail; } if (!ok) goto fail; - - //;VGM_LOG("EAFRAME: v=%i, ch=%i, sr=%i, index=%i / pre=%x, common=%x, pcm=%x, eaframe=%x\n", eaf->version, eaf->channels, eaf->sample_rate, eaf->granule_index, eaf->pre_size, eaf->common_size, eaf->pcm_size, eaf->eaframe_size); - //if (data->type==MPEG_EAL31) VGM_LOG("EAFRAME v1: pcm=%x, unk=%x, number=%x\n", eaf->v1_pcm_flag, eaf->v1_pcm_unknown, eaf->v1_pcm_number); - //else VGM_LOG("EAFRAME v2: stereo=%x, unk=%x, fs=%x, mode=%x, val=%x, number=%x, size=%x\n", eaf->v2_stereo_flag, eaf->v2_unknown, eaf->v2_frame_size, eaf->v2_mode, eaf->v2_mode_value, eaf->v2_pcm_number, eaf->v2_common_size); - return 1; fail: return 0; } -static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame) { +/* read V1"a" (in SCHl) and V1"b" (in SNS) EALayer3 frame */ +static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b) { int ok; /* read EA-frame V1 header */ @@ -249,25 +235,30 @@ static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * VGM_LOG("MPEG EAL3 v1: header not 0x00 or 0xEE\n"); goto fail; /* wrong offset? */ } + if (eaf->v1_pcm_flag == 0xEE && !channels_per_frame) { + VGM_LOG("MPEG EAL3 v1: PCM block in first frame\n"); + goto fail; /* must know from a prev frame */ + } + /* read EA-frame common header (v1a PCM blocks don't have EA-frames, while v1b do) */ + if (is_v1b || eaf->v1_pcm_flag == 0x00) { + ok = ealayer3_parse_frame_common(is, eaf); + if (!ok) goto fail; + } /* check PCM block */ if (eaf->v1_pcm_flag == 0xEE) { r_bits(is, 16,&eaf->v1_pcm_decode_discard); /* samples to discard of the next decoded (not PCM block) samples */ r_bits(is, 16,&eaf->v1_pcm_number); /* number of PCM samples, can be 0 */ - if (!channels_per_frame) { - VGM_LOG("MPEG EAL3 v1: PCM block as first frame\n"); - goto fail; /* must know from a prev frame */ - } - eaf->pre_size += 2+2; /* 16b+16b */ eaf->pcm_size = (2*eaf->v1_pcm_number * channels_per_frame); - } - else { - /* read EA-frame common header */ - ok = ealayer3_parse_frame_common(is, eaf); - if (!ok) goto fail; + + if (is_v1b) { /* extra 32b in v1b */ + r_bits(is, 32,&eaf->v1_pcm_unknown); + eaf->pre_size += 4; /* 32b */ + VGM_ASSERT(eaf->v1_pcm_unknown != 0, "EA EAL3 v1: v1_pcm_unknown not 0\n"); + } } eaf->eaframe_size = eaf->pre_size + eaf->common_size + eaf->pcm_size; @@ -277,8 +268,9 @@ fail: return 0; } - -static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf) { +/* read V2"PCM" and V2"Spike" EALayer3 frame (exactly the same but V2P seems to have bigger + * PCM blocks and maybe smaller frames) */ +static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf) { int ok; /* read EA-frame V2 header */ @@ -286,7 +278,7 @@ static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * r_bits(is, 1,&eaf->v2_stereo_flag); r_bits(is, 2,&eaf->v2_unknown); r_bits(is, 12,&eaf->v2_frame_size); - + eaf->pre_size = 2; /* 16b */ if (eaf->v2_extended_flag) { @@ -294,25 +286,24 @@ static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * r_bits(is, 10,&eaf->v2_mode_value); r_bits(is, 10,&eaf->v2_pcm_number); r_bits(is, 10,&eaf->v2_common_size); - + eaf->pre_size += 4; /* 32b */ } /* read EA-frame common header */ - ok = ealayer3_parse_frame_common(is, eaf); - if (!ok) goto fail; - - //todo maybe v2 frames can be PCM-only like v1 - if (!eaf->channels) { - VGM_LOG("MPEG EAL3: v2 frame with no channel number"); - goto fail; + if (!eaf->v2_extended_flag || (eaf->v2_extended_flag && eaf->v2_common_size)) { + ok = ealayer3_parse_frame_common(is, eaf); + if (!ok) goto fail; } + VGM_ASSERT(eaf->v2_extended_flag && eaf->v2_common_size == 0, "EA EAL3: v2 empty frame\n"); /* seen in V2S */ + VGM_ASSERT(eaf->v2_extended_flag && eaf->v2_mode_value > 0, "EA EAL3: v2_mode=%x with 0x%x\n", eaf->v2_mode, eaf->v2_mode_value); + //VGM_ASSERT(eaf->v2_pcm_number > 0, "EA EAL3: v2_pcm_number 0x%x\n", eaf->v2_pcm_number); eaf->pcm_size = (2*eaf->v2_pcm_number * eaf->channels); eaf->eaframe_size = eaf->pre_size + eaf->common_size + eaf->pcm_size; - if(eaf->v2_frame_size != eaf->eaframe_size) { + if (eaf->v2_frame_size != eaf->eaframe_size) { VGM_LOG("MPEG EAL3: different v2 frame size vs calculated (0x%x vs 0x%x)\n", eaf->v2_frame_size, eaf->eaframe_size); goto fail; } @@ -324,8 +315,8 @@ fail: } -/* Parses a EALayer3 frame (common part) */ -static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf) { +/* parses an EALayer3 frame (common part) */ +static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf) { /* index tables */ static const int versions[4] = { /* MPEG 2.5 */ 3, /* reserved */ -1, /* MPEG 2 */ 2, /* MPEG 1 */ 1 }; static const int sample_rates[4][4] = { /* [version_index][sample rate index] */ @@ -393,9 +384,11 @@ static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_in for (i = 0; i < eaf->channels; i++) { /* data size (can be 0, meaning a micro EA-frame) */ eaf->data_size_b += eaf->main_data_size[i]; } + is->b_off += eaf->data_size_b; if ((eaf->base_size_b+eaf->data_size_b) % 8) /* aligned to closest 8b */ eaf->padding_size_b = 8 - ((eaf->base_size_b+eaf->data_size_b) % 8); + is->b_off += eaf->padding_size_b; eaf->common_size = (eaf->base_size_b + eaf->data_size_b + eaf->padding_size_b)/8; @@ -406,36 +399,46 @@ fail: } -/* Converts a EALAYER3 frame to a standard MPEG frame from pre-parsed info */ -static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os) { +/* converts an EALAYER3 frame to a standard MPEG frame from pre-parsed info */ +static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os) { uint32_t c = 0; int i,j; int expected_bitrate_index, expected_frame_size; - if (!eaf_0->common_size && !eaf_1->common_size) - return 1; /* empty frames, PCM block only */ - - /* get bitrate: use max bitrate (320/160) to simplify calcs for now (but some EA-frames use bit reservoir) */ - expected_bitrate_index = 0x0E; - if (eaf_0->mpeg1) { /* 44100=0x414, 48000=0x3C0, 32000=0x5A0 */ - expected_frame_size = 144l * 320 * 1000l / eaf_0->sample_rate; - } else { /* 22050=0x20A, 24000=0x1E0, 16000=0x2D0, 11025=0x414, 12000=0x3C0, 8000=0x5A0 */ - expected_frame_size = 72l * 160 * 1000l / eaf_0->sample_rate; - } + /* ignore PCM-only frames */ + if (!eaf_0->common_size) + return 1; /* extra checks */ - if (eaf_0->mpeg1) { - if (!eaf_1 - || eaf_0->mpeg1 != eaf_1->mpeg1 - || eaf_0->version != eaf_1->version - || eaf_0->granule_index == eaf_1->granule_index - || !eaf_0->common_size || !eaf_1->common_size) { - VGM_LOG("MPEG EAL3: EA-frames for MPEG1 don't match at 0x%lx\n", os->offset); - goto fail; - } + if (eaf_0->mpeg1 && (!eaf_1 + || eaf_0->mpeg1 != eaf_1->mpeg1 + || eaf_0->version != eaf_1->version + || eaf_0->granule_index == eaf_1->granule_index + || !eaf_0->common_size || !eaf_1->common_size)) { + VGM_LOG("MPEG EAL3: EA-frames for MPEG1 don't match at 0x%lx\n", os->info_offset); + goto fail; } + /* get bitrate: use "free format" (bigger bitrate) to avoid the need of bit reservoir + * this feature is in the spec but some decoders may not support it + * (free format detection is broken in some MP3 in mpg123 < 1.25.8 but works ok) */ + expected_bitrate_index = 0x00; + if (eaf_0->mpeg1) { + expected_frame_size = 144l * (320*2) * 1000l / eaf_0->sample_rate; + } else { + expected_frame_size = 72l * (160*2) * 1000l / eaf_0->sample_rate; + } +#if 0 + /* this uses max official bitrate (320/160) but some frames need more = complex bit reservoir */ + expected_bitrate_index = 0x0E; + if (eaf_0->mpeg1) { /* 320: 44100=0x414, 48000=0x3C0, 32000=0x5A0 */ + expected_frame_size = 144l * 320 * 1000l / eaf_0->sample_rate; + } else { /* 160: 22050=0x20A, 24000=0x1E0, 16000=0x2D0, 11025=0x414, 12000=0x3C0, 8000=0x5A0 */ + expected_frame_size = 72l * 160 * 1000l / eaf_0->sample_rate; + } +#endif + /* write MPEG1/2 frame header */ w_bits(os, 11, 0x7FF); /* sync */ w_bits(os, 2, eaf_0->version_index); @@ -521,12 +524,8 @@ static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_ if (os->b_off/8 > expected_frame_size) { - 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->offset); - //todo bit reservoir! (doesn't seem to affect the output too much) - - //;VGM_LOG("EAFRAME: F0 v=%i, ch=%i, sr=%i, index=%i / pre=%x, common=%x, pcm=%x, eaframe=%x\n", eaf_0->version, eaf_0->channels, eaf_0->sample_rate, eaf_0->granule_index, eaf_0->pre_size, eaf_0->common_size, eaf_0->pcm_size, eaf_0->eaframe_size); - //;VGM_LOG("EAFRAME: F1 v=%i, ch=%i, sr=%i, index=%i / pre=%x, common=%x, pcm=%x, eaframe=%x\n", eaf_1->version, eaf_1->channels, eaf_1->sample_rate, eaf_1->granule_index, eaf_1->pre_size, eaf_1->common_size, eaf_1->pcm_size, eaf_1->eaframe_size); - //;VGM_LOGB(os->buf, os->b_off/8, 0); + /* bit reservoir! shouldn't happen with free bitrate, otherwise it's hard to fix as needs complex buffering/calcs */ + 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) */ @@ -541,7 +540,9 @@ fail: return 0; } -/* write PCM block directly to sample buffer (EALayer3 seems to use this as a prefectch of sorts) */ +/* write PCM block directly to sample buffer and setup decode discard (EALayer3 seems to use this as a prefetch of sorts). + * Meant to be written inmediatedly, as those PCM are parts that can be found after 1 decoded frame. + * (ex. EA-frame_gr0, PCM-frame_0, EA-frame_gr1, PCM-frame_1 actually writes PCM-frame_0+1, decode of EA-frame_gr0+1 + discard part */ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf) { mpeg_custom_stream *ms = data->streams[num_stream]; size_t bytes_filled; @@ -552,13 +553,12 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d bytes_filled = sizeof(sample)*ms->samples_filled*data->channels_per_frame; if (bytes_filled + eaf->pcm_size > ms->output_buffer_size) { - VGM_LOG("MPEG EAL3: can't fill the sample buffer with 0x%x\n", eaf->pcm_size); - goto fail; + VGM_LOG("MPEG EAL3: can't fill the sample buffer with 0x%x\n", eaf->pcm_size); + goto fail; } if (eaf->v1_pcm_number) { - //;VGM_LOG("pcm discard = %i, number = %i at 0x%lx\n", eaf->v1_pcm_decode_discard, eaf->v1_pcm_number, stream->offset); VGM_ASSERT(eaf->v1_pcm_decode_discard > 576, "MPEG EAL3: big discard %i at 0x%lx\n", eaf->v1_pcm_decode_discard, stream->offset); VGM_ASSERT(eaf->v1_pcm_number > 0x100, "MPEG EAL3: big samples %i at 0x%lx\n", eaf->v1_pcm_number, stream->offset); @@ -576,95 +576,98 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d //todo should also discard v1_pcm_number, but block layout samples may be exhausted and won't move (maybe new block if offset = new offset detected) /* special meanings */ - if (decode_to_discard == 576) - decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number; - + if (data->type == MPEG_EAL31) { + if (decode_to_discard == 576) + decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number; + } + else { + if (decode_to_discard == 0) /* seems ok? */ + decode_to_discard += data->samples_per_frame;//+ eaf->v1_pcm_number; + else if (decode_to_discard == 576) /* untested */ + decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number; + } ms->decode_to_discard += decode_to_discard; } } + if (eaf->v2_extended_flag) { + if (eaf->v2_pcm_number) { + /* read + write PCM block samples (always BE) */ + for (i = 0; i < eaf->v2_pcm_number * data->channels_per_frame; i++) { + off_t pcm_offset = stream->offset + eaf->pre_size + eaf->common_size + sizeof(sample)*i; + int16_t pcm_sample = read_16bitBE(pcm_offset,stream->streamfile); + put_16bitLE(ms->output_buffer + bytes_filled + sizeof(sample)*i, pcm_sample); + } + ms->samples_filled += eaf->v2_pcm_number; + } - /* todo V2 (id7 only?) supposed skip modes: - * BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3 - * - * AB00CCCC CCCCCCCC if A is set: DDEEEEEE EEEEFFFF FFFFFFGG GGGGGGGG - * D = mode: - * E = bytes to discard (mode == 0) or skip (mode == 1 or 2) before outputting the uncompressed samples - * (when mode == 3 this is ignored) - * F = number of uncompressed sample frames - * G = MPEG granule size (can be zero) - * - * if 0: 576 - E if G == 0 then F - * if 1: 576 if G == 0 then F - * if 2: 576 if G == 0 then F * 2 - * if 3: 576 - */ +#if 0 + /* todo supposed skip modes (only seen 0x00): + * + * AB00CCCC CCCCCCCC if A is set: DDEEEEEE EEEEFFFF FFFFFFGG GGGGGGGG + * D = BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3 + * E = samples to discard (mode == 0) or skip (mode == 1 or 2) before outputting the uncompressed samples + * (when mode == 3 this is ignored) + * F = number of uncompressed sample frames (pcm block) + * G = MPEG granule size (can be zero) + * + * if 0: 576 - E if G == 0 then F + * if 1: 576 if G == 0 then F + * if 2: 576 if G == 0 then F * 2 + * if 3: 576 + */ + + /* modify decoded samples depending on flag */ + if (eaf->v2_mode == 0x00) { + size_t decode_to_discard = eaf->v2_mode_value; + + if (decode_to_discard == 576) + decode_to_discard = data->samples_per_frame;//+ eaf->v2_pcm_number; + + ms->decode_to_discard += decode_to_discard; + } +#endif + } return 1; fail: return 0; } -/* ********************************************* */ -/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */ -static int r_bits(ealayer3_bitstream * is, int num_bits, uint32_t * value) { - off_t off, pos; - int i, bit_buf, bit_val; - if (num_bits == 0) return 1; - if (num_bits > 32 || num_bits < 0 || is->b_off + num_bits > is->bufsize*8) goto fail; +/* Skip EA-frames from other streams for multichannel (interleaved 1 EA-frame per stream). + * Due to EALayer3 being in blocks and other complexities (we can't go past a block) all + * streams's offsets should start in the first stream's EA-frame. + * + * So to properly read one MPEG-frame from a stream we need to: + * - skip one EA-frame per previous streams until offset is in current stream's EA-frame + * (ie. 1st stream skips 0, 2nd stream skips 1, 3rd stream skips 2) + * - read EA-frame (granule0) + * - skip one EA-frame per following streams until offset is in first stream's EA-frame + * (ie. 1st stream skips 2, 2nd stream skips 1, 3rd stream skips 0) + * - repeat again for granule1 + */ +static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start) { + int ok, i; + ealayer3_frame_info eaf; + vgm_bitstream is = {0}; + uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE]; + int skips = at_start ? num_stream : data->streams_size - 1 - num_stream; - *value = 0; /* set all bits to 0 */ - off = is->b_off / 8; /* byte offset */ - pos = is->b_off % 8; /* bit sub-offset */ - for (i = 0; i < num_bits; i++) { - bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */ - bit_val = (1U << (num_bits-1-i)); /* bit to set in value */ - if (is->buf[off] & bit_buf) /* is bit in buf set? */ - *value |= bit_val; /* set bit */ + for (i = 0; i < skips; i++) { + is.buf = ibuf; + is.bufsize = read_streamfile(ibuf,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */ + is.b_off = 0; - pos++; - if (pos%8 == 0) { /* new byte starts */ - pos = 0; - off++; - } + ok = ealayer3_parse_frame(data, &is, &eaf); + if (!ok) goto fail; + + stream->offset += eaf.eaframe_size; } + //;VGM_LOG("s%i: skipped %i frames, now at %lx\n", num_stream,skips,stream->offset); - is->b_off += num_bits; - return 1; -fail: - return 0; -} - -/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */ -static int w_bits(ealayer3_bitstream * os, int num_bits, uint32_t value) { - off_t off, pos; - int i, bit_val, bit_buf; - if (num_bits == 0) return 1; - if (num_bits > 32 || num_bits < 0 || os->b_off + num_bits > os->bufsize*8) goto fail; - - - off = os->b_off / 8; /* byte offset */ - pos = os->b_off % 8; /* bit sub-offset */ - for (i = 0; i < num_bits; i++) { - bit_val = (1U << (num_bits-1-i)); /* bit check for value */ - bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */ - - if (value & bit_val) /* is bit in val set? */ - os->buf[off] |= bit_buf; /* set bit */ - else - os->buf[off] &= ~bit_buf; /* unset bit */ - - pos++; - if (pos%8 == 0) { /* new byte starts */ - pos = 0; - off++; - } - } - - os->b_off += num_bits; return 1; fail: return 0; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c index 8a0cab0b7..3000bf3d1 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c @@ -10,10 +10,9 @@ * - don't force channel param and get them from frame headers for some types (for MPEG_STANDARD) * - in case of streams like 2ch+1ch+1ch+2ch (not seen) use one stream per channel and advance streams as channels are done * - validate of channels between streams - * - fsb garbage in the first frames */ -#define MPEG_DATA_BUFFER_SIZE 0x1000 /* at least one MPEG frame (max ~0x5A1) */ +#define MPEG_DATA_BUFFER_SIZE 0x1000 /* at least one MPEG frame (max ~0x5A1 plus some more in case of free bitrate) */ static mpg123_handle * init_mpg123_handle(); static void decode_mpeg_standard(VGMSTREAMCHANNEL *stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); @@ -101,6 +100,8 @@ mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset if (channels_per_frame != channels) goto fail; + /* copy current as open_feed may invalidate until data is fed */ + memcpy(&data->mi, &mi, sizeof(struct mpg123_frameinfo)); /* reinit, to ignore the reading done */ mpg123_open_feed(main_m); @@ -123,11 +124,6 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start data = calloc(1,sizeof(mpeg_codec_data)); if (!data) goto fail; - data->buffer_size = MPEG_DATA_BUFFER_SIZE; - data->buffer = calloc(sizeof(uint8_t), data->buffer_size); - if (!data->buffer) goto fail; - - /* keep around to decode */ data->custom = 1; data->type = type; @@ -137,6 +133,7 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start /* init per subtype */ switch(data->type) { case MPEG_EAL31: + case MPEG_EAL31b: case MPEG_EAL32P: case MPEG_EAL32S: ok = mpeg_custom_setup_init_ealayer3(streamFile, start_offset, data, coding_type); break; case MPEG_AWC: ok = mpeg_custom_setup_init_awc(streamFile, start_offset, data, coding_type); break; @@ -161,6 +158,11 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start data->streams[i]->output_buffer_size = sizeof(sample) * data->channels_per_frame * data->samples_per_frame; data->streams[i]->output_buffer = calloc(data->streams[i]->output_buffer_size, sizeof(uint8_t)); if (!data->streams[i]->output_buffer) goto fail; + + /* one per stream as sometimes mpg123 can't read the whole buffer in one pass */ + data->streams[i]->buffer_size = MPEG_DATA_BUFFER_SIZE; + data->streams[i]->buffer = calloc(sizeof(uint8_t), data->streams[i]->buffer_size); + if (!data->streams[i]->buffer) goto fail; } @@ -238,7 +240,7 @@ static void decode_mpeg_standard(VGMSTREAMCHANNEL *stream, mpeg_codec_data * dat /* end of stream, fill rest with 0s */ if (!data->bytes_in_buffer) { - memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample)); + memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * channels * sizeof(sample)); break; } @@ -367,7 +369,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data int rc, ok; mpeg_custom_stream *ms = data->streams[num_stream]; - //;VGM_LOG("MPEG: decode stream%i @ 0x%08lx (filled=%i, used=%i)\n", num_stream, stream->offset, ms->samples_filled, ms->samples_used); + //;VGM_LOG("MPEG: decode stream%i @ 0x%08lx (filled=%i, used=%i, buffer_full=%i)\n", num_stream, stream->offset, ms->samples_filled, ms->samples_used, ms->buffer_full); /* wait until samples are depleted, so buffers don't grow too big */ if (ms->samples_filled - ms->samples_used > 0) { @@ -379,58 +381,47 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data ms->samples_used = 0; /* extra EOF check for edge cases when the caller tries to read more samples than possible */ - if (!data->buffer_full && stream->offset >= stream_size) { + if (!ms->buffer_full && stream->offset >= stream_size) { VGM_LOG("MPEG: EOF found but more data is requested\n"); goto decode_fail; } /* read more raw data (could fill the sample buffer too in some cases, namely EALayer3) */ - if (!data->buffer_full) { + if (!ms->buffer_full) { //;VGM_LOG("MPEG: reading more raw data\n"); switch(data->type) { case MPEG_EAL31: + case MPEG_EAL31b: case MPEG_EAL32P: case MPEG_EAL32S: ok = mpeg_custom_parse_frame_ealayer3(stream, data, num_stream); break; - case MPEG_AHX: ok = mpeg_custom_parse_frame_ahx(stream, data); break; + case MPEG_AHX: ok = mpeg_custom_parse_frame_ahx(stream, data, num_stream); break; case MPEG_AWC: ok = mpeg_custom_parse_frame_awc(stream, data, num_stream); break; - default: ok = mpeg_custom_parse_frame_default(stream, data); break; + default: ok = mpeg_custom_parse_frame_default(stream, data, num_stream); break; } if (!ok) { VGM_LOG("MPEG: cannot parse frame @ around %lx\n",stream->offset); goto decode_fail; /* mpg123 could resync but custom MPEGs wouldn't need that */ } - //;VGM_LOG("MPEG: read results: bytes_in_buffer=0x%x, new offset=%lx\n", data->bytes_in_buffer, stream->offset); + //;VGM_LOG("MPEG: read results: bytes_in_buffer=0x%x, new offset=%lx\n", ms->bytes_in_buffer, stream->offset); /* parse frame may not touch the buffer (only move offset, or fill the sample buffer) */ - if (data->bytes_in_buffer) { - data->buffer_full = 1; - data->buffer_used = 0; + if (ms->bytes_in_buffer) { + ms->buffer_full = 1; + ms->buffer_used = 0; } } -#if 0 - //FSB sometimes has garbage in the first frames, not sure why/when, no apparent patern - if (data->custom_type == MPEG_FSB && stream->offset == stream->channel_start_offset) { /* first frame */ - VGM_LOG("MPEG: skip first frame @ %x - %x\n", stream->offset, stream->channel_start_offset); - - data->buffer_full = 0; - memset(data->stream_buffer, 0, data->stream_buffer_size); - bytes_done = data->stream_buffer_size; - break; - } -#endif - bytes_filled = sizeof(sample)*ms->samples_filled*data->channels_per_frame; /* feed new raw data to the decoder if needed, copy decoded results to frame buffer output */ - if (!data->buffer_used) { - //;VGM_LOG("MPEG: feed new data and get samples \n"); + if (!ms->buffer_used) { + //;VGM_LOG("MPEG: feed new data and get samples\n"); rc = mpg123_decode(ms->m, - data->buffer, data->bytes_in_buffer, + ms->buffer, ms->bytes_in_buffer, (unsigned char*)ms->output_buffer + bytes_filled, ms->output_buffer_size - bytes_filled, &bytes_done); - data->buffer_used = 1; + ms->buffer_used = 1; } else { //;VGM_LOG("MPEG: get samples from old data\n"); @@ -460,11 +451,12 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data /* not enough raw data, set flag to request more next time * (but only with empty mpg123 buffer, EA blocks wait for all samples decoded before advancing blocks) */ if (!bytes_done && rc == MPG123_NEED_MORE) { - //;VGM_LOG("MPEG: need more raw data to get samples (bytest_done=%x)\n", bytes_done); - data->buffer_full = 0; + //;VGM_LOG("MPEG: need more raw data to get samples (bytes_done=%x)\n", bytes_done); + ms->buffer_full = 0; } + //;VGM_LOG("MPEG: stream samples now=%i, filled=%i)\n\n", ms->samples_filled, samples_filled); return; decode_fail: @@ -490,6 +482,7 @@ void free_mpeg(mpeg_codec_data *data) { int i; for (i=0; i < data->streams_size; i++) { mpg123_delete(data->streams[i]->m); + free(data->streams[i]->buffer); free(data->streams[i]->output_buffer); free(data->streams[i]); } @@ -537,6 +530,8 @@ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) { /* seek multistream */ if (!data->custom) { mpg123_feedseek(data->m, num_sample,SEEK_SET,&input_offset); + + /* force first offset as discard-looping needs to start from the beginning */ if (vgmstream->loop_ch) vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset + input_offset; } @@ -548,7 +543,10 @@ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) { data->streams[i]->samples_filled = 0; data->streams[i]->samples_used = 0; data->streams[i]->decode_to_discard = 0; + data->streams[i]->buffer_full = 0; + data->streams[i]->buffer_used = 0; + /* force first offset as discard-looping needs to start from the beginning */ if (vgmstream->loop_ch) vgmstream->loop_ch[i].offset = vgmstream->loop_ch[i].channel_start_offset; } @@ -579,6 +577,9 @@ void flush_mpeg(mpeg_codec_data * data) { data->streams[i]->samples_filled = 0; data->streams[i]->samples_used = 0; data->streams[i]->decode_to_discard = 0; + data->streams[i]->bytes_in_buffer = 0; + data->streams[i]->buffer_full = 0; + data->streams[i]->buffer_used = 0; } data->samples_to_discard = data->skip_samples; /* initial delay */ @@ -592,23 +593,20 @@ void flush_mpeg(mpeg_codec_data * data) { long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data) { /* if not found just return 0 and expect to fail (if used for num_samples) */ if (!data->custom) { - struct mpg123_frameinfo mi; - mpg123_handle *m = data->m; - - if (m == NULL || MPG123_OK != mpg123_info(m, &mi)) - return 0; - /* We would need to read all VBR frames headers to count samples */ - if (mi.vbr != MPG123_CBR) //maybe abr_rate could be used to get an approx + if (data->mi.vbr != MPG123_CBR) { //maybe abr_rate could be used to get an approx + VGM_LOG("MPEG: vbr mp3 can't do bytes_to_samples\n"); return 0; + } - return (int64_t)bytes * mi.rate * 8 / (mi.bitrate * 1000); + return (int64_t)bytes * data->mi.rate * 8 / (data->mi.bitrate * 1000); } else { return 0; /* a bit too complex for what is worth */ } } +#if 0 /* disables/enables stderr output, for MPEG known to contain recoverable errors */ void mpeg_set_error_logging(mpeg_codec_data * data, int enable) { if (!data->custom) { @@ -621,5 +619,5 @@ void mpeg_set_error_logging(mpeg_codec_data * data, int enable) { } } } - +#endif #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h index d6a0a6787..94e31b13c 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h @@ -2,6 +2,7 @@ #define _MPEG_DECODER_H_ #include "../vgmstream.h" +#include "../coding/coding.h" /* used by mpeg_decoder.c, but scattered in other .c files */ #ifdef VGM_USE_MPEG @@ -21,8 +22,8 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); int mpeg_custom_setup_init_awc(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); -int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data); -int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data); +int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); +int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c index 8e84d57e9..6b6c96ec9 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c @@ -37,13 +37,11 @@ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci } /* read from memory rather than a file */ -void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) { +static void decode_ngc_dsp_subint_internal(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) { int i=first_sample; int32_t sample_count; - int framesin = first_sample/14; - - int8_t header = mem[framesin*8]; + int8_t header = mem[0]; int32_t scale = 1 << (header & 0xf); int coef_index = (header >> 4) & 0xf; int32_t hist1 = stream->adpcm_history1_16; @@ -54,7 +52,7 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels first_sample = first_sample%14; for (i=first_sample,sample_count=0; iadpcm_history2_16 = hist2; } +/* decode DSP with byte-interleaved frames (ex. 0x08: 1122112211221122) */ +void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave) { + uint8_t sample_data[0x08]; + int i; + + int framesin = first_sample/14; + + for (i=0; i < 0x08; i++) { + /* base + current frame + subint section + subint byte + channel adjust */ + sample_data[i] = read_8bit( + stream->offset + + framesin*(0x08*channelspacing) + + i/interleave * interleave * channelspacing + + i%interleave + + interleave * channel, stream->streamfile); + } + + decode_ngc_dsp_subint_internal(stream, outbuf, channelspacing, first_sample, samples_to_do, sample_data); +} + + /* * The original DSP spec uses nibble counts for loop points, and some * variants don't have a proper sample count, so we (who are interested diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c index 1fd256f2e..7c6cdf282 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c @@ -50,6 +50,7 @@ vorbis_custom_codec_data * init_vorbis_custom_codec_data(STREAMFILE *streamFile, case VORBIS_WWISE: ok = vorbis_custom_setup_init_wwise(streamFile, start_offset, data); break; case VORBIS_OGL: ok = vorbis_custom_setup_init_ogl(streamFile, start_offset, data); break; case VORBIS_SK: ok = vorbis_custom_setup_init_sk(streamFile, start_offset, data); break; + case VORBIS_VID1: ok = vorbis_custom_setup_init_vid1(streamFile, start_offset, data); break; default: goto fail; } if(!ok) goto fail; @@ -131,6 +132,7 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample case VORBIS_WWISE: ok = vorbis_custom_parse_packet_wwise(stream, data); break; case VORBIS_OGL: ok = vorbis_custom_parse_packet_ogl(stream, data); break; case VORBIS_SK: ok = vorbis_custom_parse_packet_sk(stream, data); break; + case VORBIS_VID1: ok = vorbis_custom_parse_packet_vid1(stream, data); break; default: goto decode_fail; } if(!ok) { @@ -142,8 +144,9 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample /* parse the fake ogg packet into a logical vorbis block */ rc = vorbis_synthesis(&data->vb,&data->op); if (rc == OV_ENOTAUDIO) { - VGM_LOG("Vorbis: not an audio packet @ %lx\n",stream->offset); - continue; /* not tested */ + VGM_LOG("Vorbis: not an audio packet (size=0x%x) @ %lx\n",(size_t)data->op.bytes,stream->offset); + //VGM_LOGB(data->op.packet, (size_t)data->op.bytes,0); + continue; /* seems ok? */ } else if (rc != 0) { VGM_LOG("Vorbis: cannot parse Vorbis block @ %lx\n",stream->offset); goto decode_fail; @@ -164,7 +167,7 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample decode_fail: /* on error just put some 0 samples */ - memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample)); + memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * channels * sizeof(sample)); } /* converts from internal Vorbis format to standard PCM (mostly from Xiph's decoder_example.c) */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h index e3957b283..0801d91c1 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h @@ -2,6 +2,7 @@ #define _VORBIS_CUSTOM_DECODER_H_ #include "../vgmstream.h" +#include "../coding/coding.h" /* used by vorbis_custom_decoder.c, but scattered in other .c files */ #ifdef VGM_USE_VORBIS @@ -9,11 +10,13 @@ int vorbis_custom_setup_init_fsb(STREAMFILE *streamFile, off_t start_offset, vor int vorbis_custom_setup_init_wwise(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data); int vorbis_custom_setup_init_ogl(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data); int vorbis_custom_setup_init_sk(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data); +int vorbis_custom_setup_init_vid1(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data); int vorbis_custom_parse_packet_fsb(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data); int vorbis_custom_parse_packet_wwise(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data); int vorbis_custom_parse_packet_ogl(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data); int vorbis_custom_parse_packet_sk(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data); +int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data); #endif/* VGM_USE_VORBIS */ #endif/*_VORBIS_CUSTOM_DECODER_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c new file mode 100644 index 000000000..1f5adad10 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c @@ -0,0 +1,152 @@ +#include "vorbis_custom_decoder.h" + +#ifdef VGM_USE_VORBIS +#include + + +/* **************************************************************************** */ +/* DEFS */ +/* **************************************************************************** */ + +static int get_packet_header(STREAMFILE *streamFile, off_t *offset, size_t *size); +static int build_header_comment(uint8_t * buf, size_t bufsize); + + +/* **************************************************************************** */ +/* EXTERNAL API */ +/* **************************************************************************** */ + +/** + * VID1 removes the Ogg layer and uses a block layout with custom packet headers. + * + * Info from hcs's vid1_2ogg: https://github.com/hcs64/vgm_ripping/tree/master/demux/vid1_2ogg + */ +int vorbis_custom_setup_init_vid1(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data) { + off_t offset = start_offset; + size_t packet_size = 0; + + /* read header packets (id/setup), each with an VID1 header */ + + /* normal identificacion packet */ + get_packet_header(streamFile, &offset, &packet_size); + if (packet_size > data->buffer_size) goto fail; + data->op.bytes = read_streamfile(data->buffer,offset,packet_size, streamFile); + if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */ + offset += packet_size; + + /* generate comment packet */ + data->op.bytes = build_header_comment(data->buffer, data->buffer_size); + if (!data->op.bytes) goto fail; + if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */ + + /* normal setup packet */ + get_packet_header(streamFile, &offset, &packet_size); + if (packet_size > data->buffer_size) goto fail; + data->op.bytes = read_streamfile(data->buffer,offset,packet_size, streamFile); + if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */ + offset += packet_size; + + return 1; + +fail: + return 0; +} + + +int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data) { + size_t bytes; + + + /* test block start */ + if (read_32bitBE(stream->offset + 0x00,stream->streamfile) == 0x4652414D && /* "FRAM" */ + read_32bitBE(stream->offset + 0x20,stream->streamfile) == 0x41554444) { /* "AUDD" */ + data->block_offset = stream->offset; + data->block_size = read_32bitBE(stream->offset + 0x2c,stream->streamfile); + stream->offset += 0x34; /* actual start, rest is chunk sizes and maybe granule info */ + } + + + /* get packet info the VID1 header */ + get_packet_header(stream->streamfile, &stream->offset, (uint32_t*)&data->op.bytes); + if (data->op.bytes == 0) { + VGM_LOG("VID1 Vorbis: wrong packet (0x%lx) @ %lx\n", data->op.bytes, stream->offset); + goto fail; /* EOF or end padding */ + } + + /* read raw block */ + bytes = read_streamfile(data->buffer,stream->offset, data->op.bytes,stream->streamfile); + stream->offset += data->op.bytes; + if (bytes != data->op.bytes) { + VGM_LOG("VID1 Vorbis: wrong bytes (0x%lx) @ %lx\n", data->op.bytes, stream->offset-bytes); + goto fail; /* wrong packet? */ + } + //todo: sometimes there are short packets like 01be590000 and Vorbis complains and skips, no idea + + + /* test block end (weird size calc but seems ok) */ + if ((stream->offset - (data->block_offset + 0x34)) >= (data->block_size - 0x06)) { + stream->offset = data->block_offset + read_32bitBE(data->block_offset + 0x04,stream->streamfile); + } + + + return 1; + +fail: + return 0; +} + + +/* **************************************************************************** */ +/* INTERNAL HELPERS */ +/* **************************************************************************** */ + +static int build_header_comment(uint8_t * buf, size_t bufsize) { + int bytes = 0x19; + + if (bytes > bufsize) return 0; + + put_8bit (buf+0x00, 0x03); /* packet_type (comments) */ + memcpy (buf+0x01, "vorbis", 6); /* id */ + put_32bitLE(buf+0x07, 0x09); /* vendor_length */ + memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */ + put_32bitLE(buf+0x14, 0x00); /* user_comment_list_length */ + put_8bit (buf+0x18, 0x01); /* framing_flag (fixed) */ + + return bytes; +} + +/* read header in Vorbis bitpacking format */ +static int get_packet_header(STREAMFILE *streamFile, off_t *offset, size_t *size) { + uint8_t ibuf[0x04]; /* header buffer */ + size_t ibufsize = 0x04; /* header ~max */ + vgm_bitstream ib = {0}; + uint32_t size_bits; + + + if (read_streamfile(ibuf,(*offset),ibufsize, streamFile) != ibufsize) + goto fail; + ib.buf = ibuf; + ib.bufsize = ibufsize; + ib.b_off = 0; + ib.mode = BITSTREAM_VORBIS; + + /* read using Vorbis weird LSF */ + r_bits(&ib, 4,&size_bits); + r_bits(&ib, (size_bits+1),(uint32_t*)size); + + /* special meaning, seen in silent frames */ + if (size_bits == 0 && *size == 0 && (uint8_t)read_8bit(*offset, streamFile)==0x80) { + *size = 0x01; + } + + /* pad and convert to byte offset */ + if (ib.b_off % 8) + ib.b_off += 8 - (ib.b_off % 8); + *offset += (ib.b_off/8); + + return 1; +fail: + return 0; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c index 8155ab560..7fba94174 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c @@ -13,25 +13,17 @@ /* DEFS */ /* **************************************************************************** */ -/* An internal struct to pass around and simulate a bitstream. - * Mainly to keep code cleaner and somewhat closer to ww2ogg */ -typedef struct { - uint8_t * buf; /* buffer to read/write*/ - size_t bufsize; /* max size of the buffer */ - off_t b_off; /* current offset in bits inside the buffer */ -} ww_bitstream; - static int build_header_identification(uint8_t * buf, size_t bufsize, int channels, int sample_rate, int blocksize_short, int blocksize_long); static int build_header_comment(uint8_t * buf, size_t bufsize); static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_t header_type, int * granulepos, size_t * packet_size, int big_endian); static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian); static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels); -static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian); -static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile); -static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw); -static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile); -static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile); +static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian); +static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile); +static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw); +static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile); +static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile); static int ww2ogg_tremor_ilog(unsigned int v); static unsigned int ww2ogg_tremor_book_maptype1_quantvals(unsigned int entries, unsigned int dimensions); @@ -39,9 +31,6 @@ static int load_wvc(uint8_t * ibuf, size_t ibufsize, uint32_t codebook_id, wwise static int load_wvc_file(uint8_t * buf, size_t bufsize, uint32_t codebook_id, STREAMFILE *streamFile); static int load_wvc_array(uint8_t * buf, size_t bufsize, uint32_t codebook_id, wwise_setup_t setup_type); -static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value); -static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value); - /* **************************************************************************** */ /* EXTERNAL API */ @@ -165,7 +154,7 @@ static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_ /* Transforms a Wwise data packet into a real Vorbis one (depending on config) */ static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) { - ww_bitstream ow, iw; + vgm_bitstream ow, iw; int rc, granulepos; size_t header_size, packet_size; @@ -183,11 +172,13 @@ static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFil /* prepare helper structs */ ow.buf = obuf; ow.bufsize = obufsize; - ow.b_off = 0 ; + ow.b_off = 0; + ow.mode = BITSTREAM_VORBIS; iw.buf = ibuf; iw.bufsize = ibufsize; iw.b_off = 0; + iw.mode = BITSTREAM_VORBIS; rc = ww2ogg_generate_vorbis_packet(&ow,&iw, streamFile,offset, data, big_endian); if (!rc) goto fail; @@ -206,7 +197,7 @@ fail: /* Transforms a Wwise setup packet into a real Vorbis one (depending on config). */ static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels) { - ww_bitstream ow, iw; + vgm_bitstream ow, iw; int rc, granulepos; size_t header_size, packet_size; @@ -226,10 +217,12 @@ static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile ow.buf = obuf; ow.bufsize = obufsize; ow.b_off = 0; + ow.mode = BITSTREAM_VORBIS; iw.buf = ibuf; iw.bufsize = ibufsize; iw.b_off = 0; + iw.mode = BITSTREAM_VORBIS; rc = ww2ogg_generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile); if (!rc) goto fail; @@ -295,7 +288,7 @@ static int build_header_comment(uint8_t * buf, size_t bufsize) { /* Copy packet as-is or rebuild first byte if mod_packets is used. * (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-720004.3) */ -static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) { +static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) { int i,granule; size_t header_size, packet_size, data_size; @@ -350,10 +343,13 @@ static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, S /* get next first byte to read next_mode_number */ uint32_t next_mode_number; uint8_t nbuf[1]; - ww_bitstream nw; + vgm_bitstream nw; + nw.buf = nbuf; nw.bufsize = 1; nw.b_off = 0; + nw.mode = BITSTREAM_VORBIS; + if (read_streamfile(nw.buf, next_offset + next_header_size, nw.bufsize, streamFile) != nw.bufsize) goto fail; @@ -409,7 +405,7 @@ fail: /* Rebuild a Wwise setup (simplified with removed stuff), recreating all six setup parts. * (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4) */ -static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) { +static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) { int i,j,k; uint32_t codebook_count = 0, floor_count = 0, residue_count = 0; uint32_t codebook_count_less1 = 0; @@ -798,7 +794,7 @@ fail: /* copies Vorbis codebooks (untouched, but size uncertain) */ -static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw) { +static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw) { int i; uint32_t id = 0, dimensions = 0, entries = 0; uint32_t ordered = 0, lookup_type = 0; @@ -914,7 +910,7 @@ fail: /* rebuilds a Wwise codebook into a Vorbis codebook */ -static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) { +static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) { int i; uint32_t id = 0, dimensions = 0, entries = 0; uint32_t ordered = 0, lookup_type = 0; @@ -1038,11 +1034,11 @@ fail: } /* rebuilds an external Wwise codebook referenced by id to a Vorbis codebook */ -static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) { +static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) { size_t ibufsize = 0x8000; /* arbitrary max size of a codebook */ uint8_t ibuf[0x8000]; /* Wwise codebook buffer */ size_t cb_size; - ww_bitstream iw; + vgm_bitstream iw; cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, streamFile); if (cb_size == 0) goto fail; @@ -1050,6 +1046,7 @@ static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t cod iw.buf = ibuf; iw.bufsize = ibufsize; iw.b_off = 0; + iw.mode = BITSTREAM_VORBIS; return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, streamFile); fail: @@ -1228,70 +1225,4 @@ fail: return 0; } -/* ********************************************* */ - -/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte. - * (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */ -static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value) { - off_t off, pos; - int i, bit_buf, bit_val; - if (num_bits == 0) return 1; - if (num_bits > 32 || num_bits < 0 || iw->b_off + num_bits > iw->bufsize*8) goto fail; - - *value = 0; /* set all bits to 0 */ - off = iw->b_off / 8; /* byte offset */ - pos = iw->b_off % 8; /* bit sub-offset */ - for (i = 0; i < num_bits; i++) { - bit_buf = (1U << pos) & 0xFF; /* bit check for buf */ - bit_val = (1U << i); /* bit to set in value */ - - if (iw->buf[off] & bit_buf) /* is bit in buf set? */ - *value |= bit_val; /* set bit */ - - pos++; /* new byte starts */ - if (pos%8 == 0) { - pos = 0; - off++; - } - } - - iw->b_off += num_bits; - return 1; -fail: - return 0; -} - -/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte. - * (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/ -static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value) { - off_t off, pos; - int i, bit_val, bit_buf; - if (num_bits == 0) return 1; - if (num_bits > 32 || num_bits < 0 || ow->b_off + num_bits > ow->bufsize*8) goto fail; - - - off = ow->b_off / 8; /* byte offset */ - pos = ow->b_off % 8; /* bit sub-offset */ - for (i = 0; i < num_bits; i++) { - bit_val = (1U << i); /* bit check for value */ - bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */ - - if (value & bit_val) /* is bit in val set? */ - ow->buf[off] |= bit_buf; /* set bit */ - else - ow->buf[off] &= ~bit_buf; /* unset bit */ - - pos++; /* new byte starts */ - if (pos%8 == 0) { - pos = 0; - off++; - } - } - - ow->b_off += num_bits; - return 1; -fail: - return 0; -} - #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c index 083ce1037..deeada360 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c @@ -7,21 +7,21 @@ const int SHC = 10; double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125}; double K1[4] = { 0.0, 0.0, -0.8125,-0.859375}; -int IK0(int fid) +static int IK0(int fid) { return ((int)((-K0[fid]) * (1 << SHC))); } -int IK1(int fid) +static int IK1(int fid) { return ((int)((-K1[fid]) * (1 << SHC))); } -int CLAMP(int value, int Minim, int Maxim) +static int CLAMP(int value, int Minim, int Maxim) { if (value < Minim) value = Minim; if (value > Maxim) value = Maxim; return value; } -void init_get_high_nibble(VGMSTREAM *vgmstream) { - vgmstream->get_high_nibble=1; +void xa_init_get_high_nibble(VGMSTREAM *vgmstream) { + vgmstream->xa_get_high_nibble=1; } void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { @@ -41,18 +41,18 @@ void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32 first_sample = first_sample % 28; - vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + vgmstream->xa_get_high_nibble=!vgmstream->xa_get_high_nibble; if((first_sample) && (channelspacing==1)) - vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + vgmstream->xa_get_high_nibble=!vgmstream->xa_get_high_nibble; - predict_nr = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) >> 4; - shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) & 0xf; + predict_nr = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->xa_get_high_nibble,stream->streamfile) >> 4; + shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->xa_get_high_nibble,stream->streamfile) & 0xf; for (i=first_sample,sample_count=0; ioffset+16+framesin+(i*4),stream->streamfile); - scale = ((vgmstream->get_high_nibble ? + scale = ((vgmstream->xa_get_high_nibble ? sample_byte >> 4 : sample_byte & 0x0f)<<12); @@ -70,3 +70,13 @@ void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32 stream->adpcm_history1_32=hist1; stream->adpcm_history2_32=hist2; } + +size_t xa_bytes_to_samples(size_t bytes, int channels, int is_blocked) { + if (is_blocked) { + //todo with -0x10 misses the last sector, not sure if bug or feature + return ((bytes - 0x10) / 0x930) * (0x900 - 18*0x10) * 2 / channels; + } + else { + return ((bytes / 0x80)*0xE0) / 2; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 259869641..37e5e0bfd 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -1,4 +1,4 @@ -#include "formats.h" +#include "vgmstream.h" //#define VGM_REGISTER_TYPE(extension) ... //#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */ @@ -52,6 +52,7 @@ static const char* extension_list[] = { "bar", "bcstm", "bcwav", + "bd3", //txth/reserved [Elevator Action Deluxe (PS3)] "bdsp", "bfstm", "bfwav", @@ -81,6 +82,7 @@ static const char* extension_list[] = { "capdsp", "cbd2", "ccc", + "cd", "cfn", "ckd", "cnk", @@ -92,6 +94,7 @@ static const char* extension_list[] = { "dcs", "ddsp", "de2", + "dec", "dmsg", "dsp", "dspw", @@ -103,10 +106,12 @@ static const char* extension_list[] = { "emff", "enth", "exa", + "ezw", "fag", "ffw", "filp", + "flx", "fsb", "fwav", @@ -132,7 +137,7 @@ static const char* extension_list[] = { "iab", "iadp", "idsp", - "idvi", + "idvi", //fake extension (to be removed) "ikm", "ild", "int", @@ -147,12 +152,13 @@ static const char* extension_list[] = { "jstm", "kces", - "kcey", + "kcey", //fake extension (to be removed) "khv", "kovs", "kraw", "laac", //fake extension, for AAC (tri-Ace/FFmpeg) + "lac3", //fake extension, for AC3 "leg", "lmp4", //fake extension, for MP4s "logg", //fake extension, for OGGs @@ -174,7 +180,9 @@ static const char* extension_list[] = { "mic", "mihb", "mnstr", + "mogg", //"mp4", //common + //"mpc", //FFmpeg, not parsed (musepack) //common "mpdsp", "mpds", "msa", @@ -190,6 +198,7 @@ static const char* extension_list[] = { "mxst", "myspd", + "naac", "ndp", "ngca", "nps", @@ -201,7 +210,7 @@ static const char* extension_list[] = { "ogl", "oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "omu", - "opus", + //"opus", //common "otm", "p1d", //txth/reserved [Farming Simulator 18 (3DS)] @@ -226,7 +235,8 @@ static const char* extension_list[] = { "rrds", "rsd", "rsf", - "rstm", + "rsm", + "rstm", //rsm header id "rvws", "rwar", "rwav", @@ -239,10 +249,19 @@ static const char* extension_list[] = { "sab", "sad", "sap", + "sb0", + "sb1", + "sb2", + "sb3", + "sb4", + "sb5", + "sb6", + "sb7", "sc", "scd", "sck", "sd9", + "sdf", "sdt", "seg", "sf0", @@ -255,10 +274,11 @@ static const char* extension_list[] = { "sl3", "sli", "smp", - "smpl", + "smpl", //fake extension (to be removed) "snd", "snds", "sng", + "snr", "sns", "snu", "spd", @@ -267,8 +287,6 @@ static const char* extension_list[] = { "spsd", "spw", "ss2", - "ss3", - "ss7", "ssm", "sss", "ster", @@ -299,21 +317,24 @@ static const char* extension_list[] = { "ulw", "um3", + "v0", + //"v1", //dual channel with v0 "vag", "vas", "vawx", "vb", "vbk", + "vds", + "vdm", "vgs", "vgv", "vig", - "vds", - "vdm", "vms", "voi", "vpk", "vs", "vsf", + "vxn", "waa", "wac", @@ -365,22 +386,12 @@ static const char* extension_list[] = { //, NULL //end mark }; -/** - * List of supported formats. - * - * For plugins that need to know (test.exe doesn't use it) - */ -const char ** vgmstream_get_formats() { +/* List supported formats and return elements in the list, for plugins that need to know. */ +const char ** vgmstream_get_formats(size_t * size) { + *size = sizeof(extension_list) / sizeof(char*); return extension_list; } -/** - * Number of elements in the list. - */ -int vgmstream_get_formats_length() { - return sizeof(extension_list) / sizeof(char*); -} - /* internal description info */ @@ -404,51 +415,54 @@ static const coding_info coding_info_list[] = { {coding_PCM16LE, "Little Endian 16-bit PCM"}, {coding_PCM16LE_XOR_int, "Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"}, {coding_PCM16BE, "Big Endian 16-bit PCM"}, - {coding_PCM16_int, "16-bit PCM with 2 byte interleave"}, + {coding_PCM16_int, "16-bit PCM with 2 byte interleave (block)"}, {coding_PCM8, "8-bit PCM"}, + {coding_PCM8_int, "8-bit PCM with 1 byte interleave (block)"}, {coding_PCM8_U, "8-bit unsigned PCM"}, - {coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave"}, - {coding_PCM8_int, "8-bit PCM with 1 byte interleave"}, - {coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"}, + {coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave (block)"}, + {coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave (block)"}, {coding_ULAW, "8-bit u-Law"}, {coding_ALAW, "8-bit a-Law"}, {coding_PCMFLOAT, "32-bit float PCM"}, + {coding_CRI_ADX, "CRI ADX 4-bit ADPCM"}, - {coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM with exponential scale"}, - {coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM with fixed coefficients"}, + {coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM (fixed coefficients)"}, + {coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM (exponential scale)"}, {coding_CRI_ADX_enc_8, "CRI ADX 4-bit ADPCM (type 8 encryption)"}, {coding_CRI_ADX_enc_9, "CRI ADX 4-bit ADPCM (type 9 encryption)"}, + {coding_NGC_DSP, "Nintendo DSP 4-bit ADPCM"}, + {coding_NGC_DSP_subint, "Nintendo DSP 4-bit ADPCM (subinterleave)"}, {coding_NGC_DTK, "Nintendo DTK 4-bit ADPCM"}, {coding_NGC_AFC, "Nintendo AFC 4-bit ADPCM"}, - {coding_CRI_HCA, "CRI HCA"}, - {coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"}, - {coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"}, + {coding_G721, "CCITT G.721 4-bit ADPCM"}, + + {coding_XA, "CD-ROM XA 4-bit ADPCM"}, {coding_PSX, "Playstation 4-bit ADPCM"}, {coding_PSX_badflags, "Playstation 4-bit ADPCM (bad flags)"}, {coding_PSX_bmdx, "Playstation 4-bit ADPCM (BMDX encryption)"}, {coding_PSX_cfg, "Playstation 4-bit ADPCM (configurable)"}, {coding_HEVAG, "Playstation Vita HEVAG 4-bit ADPCM"}, - {coding_XA, "CD-ROM XA 4-bit ADPCM"}, - {coding_XBOX, "XBOX 4-bit IMA ADPCM"}, - {coding_XBOX_int, "XBOX 4-bit IMA ADPCM (interleaved)"}, - {coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM (v1)"}, - {coding_EA_XA_int, "Electronic Arts EA-XA 4-bit ADPCM (v1) (interleaved)"}, - {coding_EA_XA_V2, "Electronic Arts EA-XA 4-bit ADPCM (v2)"}, + + {coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM v1"}, + {coding_EA_XA_int, "Electronic Arts EA-XA 4-bit ADPCM v1 (mono/interleave)"}, + {coding_EA_XA_V2, "Electronic Arts EA-XA 4-bit ADPCM v2"}, {coding_MAXIS_XA, "Maxis EA-XA 4-bit ADPCM"}, - {coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, - {coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"}, - {coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"}, - {coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"}, - {coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"}, - {coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (interleaved)"}, - {coding_EACS_IMA, "EACS 4-bit IMA ADPCM"}, - {coding_IMA_int, "IMA 4-bit ADPCM (interleaved)"}, + {coding_EA_XAS, "Electronic Arts EA-XAS 4-bit ADPCM"}, + {coding_IMA, "IMA 4-bit ADPCM"}, + {coding_IMA_int, "IMA 4-bit ADPCM (mono/interleave)"}, + {coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"}, + {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_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"}, - {coding_RAD_IMA_mono, "Radical 4-bit IMA ADPCM (mono)"}, + {coding_RAD_IMA_mono, "Radical 4-bit IMA ADPCM (mono/interleave)"}, {coding_APPLE_IMA4, "Apple Quicktime 4-bit IMA ADPCM"}, {coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"}, {coding_OTNS_IMA, "Omikron: The Nomad Soul 4-bit IMA ADPCM"}, @@ -456,15 +470,10 @@ static const coding_info coding_info_list[] = { {coding_WWISE_IMA, "Audiokinetic Wwise 4-bit IMA ADPCM"}, {coding_REF_IMA, "Reflections 4-bit IMA ADPCM"}, {coding_AWC_IMA, "Rockstar AWC 4-bit IMA ADPCM"}, - {coding_WS, "Westwood Studios VBR ADPCM"}, - {coding_ACM, "InterPlay ACM"}, - {coding_NWA0, "NWA DPCM Level 0"}, - {coding_NWA1, "NWA DPCM Level 1"}, - {coding_NWA2, "NWA DPCM Level 2"}, - {coding_NWA3, "NWA DPCM Level 3"}, - {coding_NWA4, "NWA DPCM Level 4"}, - {coding_NWA5, "NWA DPCM Level 5"}, + {coding_UBI_IMA, "Ubisoft 4-bit IMA ADPCM"}, + {coding_MSADPCM, "Microsoft 4-bit ADPCM"}, + {coding_WS, "Westwood Studios VBR ADPCM"}, {coding_AICA, "Yamaha AICA 4-bit ADPCM"}, {coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"}, {coding_L5_555, "Level-5 0x555 4-bit ADPCM"}, @@ -473,7 +482,22 @@ static const coding_info coding_info_list[] = { {coding_MTAF, "Konami MTAF 4-bit ADPCM"}, {coding_MTA2, "Konami MTA2 4-bit ADPCM"}, {coding_MC3, "Paradigm MC3 3-bit ADPCM"}, - {coding_EA_XAS, "Electronic Arts EA-XAS 4-bit ADPCM"}, + + {coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, + {coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"}, + {coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"}, + {coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"}, + {coding_ACM, "InterPlay ACM"}, + {coding_NWA0, "NWA DPCM Level 0"}, + {coding_NWA1, "NWA DPCM Level 1"}, + {coding_NWA2, "NWA DPCM Level 2"}, + {coding_NWA3, "NWA DPCM Level 3"}, + {coding_NWA4, "NWA DPCM Level 4"}, + {coding_NWA5, "NWA DPCM Level 5"}, + + {coding_EA_MT, "Electronic Arts MicroTalk"}, + + {coding_CRI_HCA, "CRI HCA"}, #ifdef VGM_USE_VORBIS {coding_ogg_vorbis, "Ogg Vorbis"}, @@ -505,20 +529,19 @@ static const layout_info layout_info_list[] = { {layout_none, "flat (no layout)"}, {layout_interleave, "interleave"}, {layout_interleave_shortblock, "interleave with short last block"}, - {layout_interleave_byte, "sub-frame interleave"}, {layout_mxch_blocked, "MxCh blocked"}, {layout_ast_blocked, "AST blocked"}, {layout_halpst_blocked, "HALPST blocked"}, {layout_xa_blocked, "CD-ROM XA"}, - {layout_ea_blocked, "Electronic Arts SCxx blocked"}, - {layout_eacs_blocked, "Electronic Arts EACS blocked"}, + {layout_blocked_ea_schl, "blocked (EA SCHl)"}, + {layout_blocked_ea_1snh, "blocked (EA 1SNh)"}, {layout_caf_blocked, "CAF blocked"}, {layout_wsi_blocked, ".wsi blocked"}, {layout_xvas_blocked, ".xvas blocked"}, {layout_str_snds_blocked, ".str SNDS blocked"}, {layout_ws_aud_blocked, "Westwood Studios .aud blocked"}, {layout_matx_blocked, "Matrix .matx blocked"}, - {layout_de2_blocked, "de2 blocked"}, + {layout_blocked_dec, "blocked (DEC)"}, {layout_vs_blocked, "vs blocked"}, {layout_emff_ps2_blocked, "EMFF (PS2) blocked"}, {layout_emff_ngc_blocked, "EMFF (NGC/WII) blocked"}, @@ -528,7 +551,7 @@ static const layout_info layout_info_list[] = { {layout_psx_mgav_blocked, "MGAV blocked"}, {layout_ps2_adm_blocked, "ADM blocked"}, {layout_dsp_bdsp_blocked, "DSP blocked"}, - {layout_ivaud_blocked, "GTA IV blocked"}, + {layout_blocked_ivaud, "blocked (IVAUD)"}, {layout_ps2_iab_blocked, "IAB blocked"}, {layout_ps2_strlr_blocked, "The Bouncer STR blocked"}, {layout_rws_blocked, "RWS blocked"}, @@ -539,9 +562,10 @@ static const layout_info layout_info_list[] = { {layout_aix, "AIX interleave, internally 18-byte interleaved"}, {layout_aax, "AAX blocked, 18-byte interleaved"}, {layout_scd_int, "SCD multistream interleave"}, - {layout_ea_sns_blocked, "Electronic Arts SNS blocked"}, + {layout_blocked_ea_sns, "blocked (EA SNS)"}, {layout_blocked_awc, "blocked (AWC)"}, {layout_blocked_vgs, "blocked (VGS)"}, + {layout_blocked_vawx, "blocked (VAWX)"}, #ifdef VGM_USE_VORBIS {layout_ogg_vorbis, "Ogg"}, #endif @@ -561,8 +585,8 @@ static const meta_info meta_info_list[] = { {meta_UTF_DSP, "CRI ADPCM_WII header"}, {meta_DSP_AGSC, "Retro Studios AGSC header"}, {meta_DSP_CSMP, "Retro Studios CSMP header"}, - {meta_NGC_ADPDTK, "assumed Nintendo ADP by .adp extension and valid first frame"}, - {meta_RSF, "assumed Retro Studios RSF by .rsf extension and valid first bytes"}, + {meta_NGC_ADPDTK, "Nintendo ADP raw header"}, + {meta_RSF, "Retro Studios RSF raw header"}, {meta_AFC, "Nintendo AFC header"}, {meta_AST, "Nintendo AST header"}, {meta_HALPST, "HAL Laboratory HALPST header"}, @@ -631,9 +655,7 @@ static const meta_info meta_info_list[] = { {meta_HGC1, "Knights of the Temple 2 hgC1 Header"}, {meta_AUS, "Capcom AUS Header"}, {meta_RWS, "RenderWare RWS header"}, - {meta_EACS_PC, "Electronic Arts EACS header (PC)"}, - {meta_EACS_PSX, "Electronic Arts EACS header (PSX)"}, - {meta_EACS_SAT, "Electronic Arts EACS header (SATURN)"}, + {meta_EA_1SNH, "Electronic Arts 1SNh/EACS header"}, {meta_SL3, "SL3 Header"}, {meta_FSB1, "FMOD Sample Bank (FSB1) Header"}, {meta_FSB2, "FMOD Sample Bank (FSB2) Header"}, @@ -653,8 +675,8 @@ static const meta_info meta_info_list[] = { {meta_FILP, "Bio Hazard - Gun Survivor FILp Header"}, {meta_IKM, "Zwei!! IKM Header"}, {meta_SFS, "Baroque SFS Header"}, - {meta_DVI, "DVI Header"}, - {meta_KCEY, "KCEYCOMP Header"}, + {meta_SAT_DVI, "Konami KCEN DVI. header"}, + {meta_DC_KCEY, "Konami KCEY KCEYCOMP header"}, {meta_BG00, "Falcom BG00 Header"}, {meta_PS2_RSTM, "Rockstar Games RSTM Header"}, {meta_ACM, "InterPlay ACM Header"}, @@ -667,8 +689,8 @@ static const meta_info meta_info_list[] = { {meta_RIFX_WAVE, "RIFX WAVE header"}, {meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"}, {meta_XNB, "Microsoft XNA Game Studio 4.0 header"}, - {meta_PCM_SCD, "PCM file with custom header (SCD)"}, - {meta_PCM_PS2, "PCM file with custom header (PS2)"}, + {meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"}, + {meta_PS2_PCM, "Konami KCEJ East .PCM header"}, {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"}, {meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"}, {meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"}, @@ -676,14 +698,15 @@ static const meta_info meta_info_list[] = { {meta_XBOX_WVS, "Metal Arms WVS Header (XBOX)"}, {meta_NGC_WVS, "Metal Arms WVS Header (GameCube)"}, {meta_XBOX_MATX, "assumed Matrix file by .matx extension"}, - {meta_DE2, "gurumin .de2 with embedded funky RIFF"}, + {meta_DEC, "Falcom DEC RIFF header"}, {meta_VS, "Men in Black VS Header"}, {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_PS2_XA2, "Acclaim XA2 Header"}, - {meta_DC_IDVI, "IDVI Header"}, + {meta_DC_IDVI, "Capcom IDVI header"}, + {meta_KRAW, "Geometry Wars: Galaxies KRAW header"}, {meta_NGC_YMF, "YMF DSP Header"}, {meta_PS2_CCC, "CCC Header"}, {meta_PSX_FAG, "FAG Header"}, @@ -769,14 +792,14 @@ static const meta_info meta_info_list[] = { {meta_NGC_SWD, "PSF + Standard DSP Headers"}, {meta_CAFF, "Apple Core Audio Format Header"}, {meta_PC_MXST, "Lego Island MxSt Header"}, - {meta_PC_SOB_SAB, "Worms 4: Mayhem SOB/SAB Header"}, + {meta_SAB, "Team17 SAB header"}, {meta_MAXIS_XA, "Maxis XAI/XAJ Header"}, {meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"}, {meta_WII_BNS, "Nintendo BNS header"}, {meta_WII_WAS, "WAS (iSWS) DSP header"}, {meta_XBOX_HLWAV, "Half Life 2 bgm header"}, {meta_STX, "Nintendo .stx header"}, - {meta_MYSPD, "U-Sing .myspd header"}, + {meta_MYSPD, "U-Sing .MYSPD header"}, {meta_HIS, "Her Interactive Sound header"}, {meta_PS2_AST, "KOEI AST header"}, {meta_CAPDSP, "Capcom DSP header"}, @@ -788,15 +811,15 @@ static const meta_info meta_info_list[] = { {meta_PS2_STER, "STER Header"}, {meta_BNSF, "Namco Bandai BNSF header"}, {meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"}, - {meta_S14, "assumed Polycom Siren 14 by .s14 extension"}, - {meta_SSS, "assumed Polycom Siren 14 by .sss extension"}, + {meta_S14, "Namco .S14 raw header"}, + {meta_SSS, "Namco .SSS raw header"}, {meta_PS2_GCM, "GCM 'MCG' Header"}, - {meta_PS2_SMPL, "Homura 'SMPL' Header"}, + {meta_PS2_SMPL, "Homura SMPL header"}, {meta_PS2_MSA, "Psyvariar -Complete Edition- MSA header"}, {meta_PC_SMP, "Ghostbusters .smp Header"}, {meta_NGC_PDT, "PDT DSP header"}, {meta_NGC_BO2, "Blood Omen 2 DSP header"}, - {meta_P3D, "Radical P3D Header"}, + {meta_P3D, "Radical P3D header"}, {meta_PS2_TK1, "Tekken TK5STRM1 Header"}, {meta_PS2_ADSC, "ADSC Header"}, {meta_NGC_DSP_MPDS, "MPDS DSP header"}, @@ -826,7 +849,7 @@ static const meta_info meta_info_list[] = { {meta_NGCA, "NGCA header"}, {meta_WII_RAS, "RAS header"}, {meta_PS2_SPM, "SPM header"}, - {meta_X360_TRA, "assumed DefJam Rapstar Audio File by .tra extension"}, + {meta_X360_TRA, "Terminal Reality .TRA raw header"}, {meta_PS2_VGS, "Princess Soft VGS header"}, {meta_PS2_IAB, "IAB header"}, {meta_PS2_STRLR, "STR L/R header"}, @@ -844,7 +867,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_MTAF, "Konami MTAF header"}, {meta_PS2_VAG1, "Konami VAG Mono header (VAG1)"}, {meta_PS2_VAG2, "Konami VAG Stereo header (VAG2)"}, - {meta_TUN, "TUN 'ALP' header"}, + {meta_TUN, "Lego Racers ALP header"}, {meta_WPD, "WPD 'DPW' header"}, {meta_MN_STR, "Mini Ninjas 'STR' header"}, {meta_MSS, "Guerilla MCSS header"}, @@ -870,7 +893,7 @@ static const meta_info meta_info_list[] = { {meta_NUB_XMA, "Namco NUB XMA header"}, {meta_X360_PASX, "Namco PASX header"}, {meta_XMA_RIFF, "Microsoft XMA RIFF header"}, - {meta_X360_AST, "Capcom AST header"}, + {meta_X360_AST, "Capcom AST (X360) header"}, {meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"}, {meta_UBI_RAKI, "Ubisoft RAKI header"}, {meta_SXD, "Sony SXD header"}, @@ -891,8 +914,19 @@ static const meta_info meta_info_list[] = { {meta_BINK, "RAD Game Tools Bink header"}, {meta_EA_SNU, "Electronic Arts SNU header"}, {meta_AWC, "Rockstar AWC header"}, - {meta_NSW_OPUS, ".OPUS header"}, + {meta_NSW_OPUS, "Nintendo Switch OPUS header"}, {meta_PC_AL2, "Illwinter Game Design AL2 raw header"}, + {meta_PC_AST, "Capcom AST (PC) header"}, + {meta_UBI_SB, "Ubisoft SBx header"}, + {meta_NAAC, "Namco NAAC header"}, + {meta_EZW, "EZ2DJ EZWAVE header"}, + {meta_VXN, "Gameloft VXN header"}, + {meta_EA_SNR_SNS, "Electronic Arts SNR+SNS header"}, + {meta_EA_SPS, "Electronic Arts SPS header"}, + {meta_NGC_VID1, "Neversoft VID1 header"}, + {meta_PC_FLX, "Ultima IX .FLX header"}, + {meta_MOGG, "Harmonix Music Systems MOGG Vorbis "}, + #ifdef VGM_USE_VORBIS {meta_OGG_VORBIS, "Ogg Vorbis"}, diff --git a/Frameworks/vgmstream/vgmstream/src/formats.h b/Frameworks/vgmstream/vgmstream/src/formats.h deleted file mode 100644 index 2fe6d910e..000000000 --- a/Frameworks/vgmstream/vgmstream/src/formats.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * formats.h - utils to parse supported formats - */ -#ifndef _FORMATS_H_ -#define _FORMATS_H_ - -#include "vgmstream.h" - -/* rough number of chars counting all extensions (actually <1500 and extra space) */ -#define VGM_EXTENSION_LIST_CHAR_SIZE 2000 - -const char ** vgmstream_get_formats(); -int vgmstream_get_formats_length(); - -const char * get_vgmstream_coding_description(coding_t coding_type); -const char * get_vgmstream_layout_description(layout_t layout_type); -const char * get_vgmstream_meta_description(meta_t meta_type); - -#endif /* _FORMATS_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c index c9d372e74..645ec6946 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c @@ -8,23 +8,24 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); int samples_this_block; + /* get samples in the current block */ if (vgmstream->current_block_samples) { samples_this_block = vgmstream->current_block_samples; - } else if (frame_size == 0) { - /* assume 4 bit */ - /* TODO: get_vgmstream_frame_size() really should return bits... */ + } else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */ samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; } else { samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; } - while (samples_writtenloop_flag && vgmstream_do_loop(vgmstream)) { + /* on loop those values are changed */ if (vgmstream->current_block_samples) { samples_this_block = vgmstream->current_block_samples; - } else if (frame_size == 0) { + } else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */ samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; } else { samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; @@ -32,52 +33,62 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * continue; } + /* probably block bug or EOF, next calcs would give wrong values and buffer segfaults */ + if (samples_this_block <= 0) { + VGM_LOG("layout_blocked: empty/wrong block\n"); + memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample)); + break; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + if (samples_written + samples_to_do > sample_count) + samples_to_do = sample_count - samples_written; - if (samples_written+samples_to_do > sample_count) - samples_to_do=sample_count-samples_written; - - if (vgmstream->current_block_offset>=0) + if (vgmstream->current_block_offset >= 0) { decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer); + } else { + /* block end signal (used below): partially 0-set buffer */ int i; - /* we've run off the end! */ - for (i=samples_written*vgmstream->channels; - i<(samples_written+samples_to_do)*vgmstream->channels;i++) - buffer[i]=0; + for (i = samples_written*vgmstream->channels; i < (samples_written+samples_to_do)*vgmstream->channels; i++) { + buffer[i]=0; + } } samples_written += samples_to_do; vgmstream->current_sample += samples_to_do; - vgmstream->samples_into_block+=samples_to_do; + vgmstream->samples_into_block += samples_to_do; + + /* move to next block when all samples are consumed */ if (vgmstream->samples_into_block==samples_this_block /*&& vgmstream->current_sample < vgmstream->num_samples*/) { /* don't go past last block */ switch (vgmstream->layout_type) { case layout_ast_blocked: ast_block_update(vgmstream->next_block_offset,vgmstream); break; - case layout_mxch_blocked: + case layout_mxch_blocked: mxch_block_update(vgmstream->next_block_offset,vgmstream); break; case layout_halpst_blocked: if (vgmstream->next_block_offset>=0) halpst_block_update(vgmstream->next_block_offset,vgmstream); else - vgmstream->current_block_offset=-1; + vgmstream->current_block_offset = -1; + break; + case layout_xa_blocked: + xa_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_blocked_ea_schl: + block_update_ea_schl(vgmstream->next_block_offset,vgmstream); + break; + case layout_blocked_ea_1snh: + block_update_ea_1snh(vgmstream->next_block_offset,vgmstream); + break; + case layout_caf_blocked: + caf_block_update(vgmstream->next_block_offset,vgmstream); break; - case layout_xa_blocked: - xa_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_ea_blocked: - ea_schl_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_eacs_blocked: - eacs_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_caf_blocked: - caf_block_update(vgmstream->next_block_offset,vgmstream); - break; case layout_wsi_blocked: wsi_block_update(vgmstream->next_block_offset,vgmstream); break; @@ -90,8 +101,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * case layout_matx_blocked: matx_block_update(vgmstream->next_block_offset,vgmstream); break; - case layout_de2_blocked: - de2_block_update(vgmstream->next_block_offset,vgmstream); + case layout_blocked_dec: + block_update_dec(vgmstream->next_block_offset,vgmstream); break; case layout_emff_ps2_blocked: emff_ps2_block_update(vgmstream->next_block_offset,vgmstream); @@ -105,33 +116,33 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * case layout_vs_blocked: vs_block_update(vgmstream->next_block_offset,vgmstream); break; - case layout_xvas_blocked: - xvas_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_thp_blocked: - thp_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_filp_blocked: - filp_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_ivaud_blocked: - ivaud_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_psx_mgav_blocked: - psx_mgav_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_ps2_adm_blocked: - ps2_adm_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_dsp_bdsp_blocked: - dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_tra_blocked: - tra_block_update(vgmstream->next_block_offset,vgmstream); - break; - case layout_ps2_iab_blocked: - ps2_iab_block_update(vgmstream->next_block_offset,vgmstream); - break; + case layout_xvas_blocked: + xvas_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_thp_blocked: + thp_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_filp_blocked: + filp_block_update(vgmstream->next_block_offset,vgmstream); + break; + 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); + break; + case layout_ps2_adm_blocked: + ps2_adm_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_dsp_bdsp_blocked: + dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_tra_blocked: + tra_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_ps2_iab_blocked: + ps2_iab_block_update(vgmstream->next_block_offset,vgmstream); + break; case layout_ps2_strlr_blocked: ps2_strlr_block_update(vgmstream->next_block_offset,vgmstream); break; @@ -141,8 +152,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * case layout_hwas_blocked: hwas_block_update(vgmstream->next_block_offset,vgmstream); break; - case layout_ea_sns_blocked: - ea_sns_block_update(vgmstream->next_block_offset,vgmstream); + case layout_blocked_ea_sns: + block_update_ea_sns(vgmstream->next_block_offset,vgmstream); break; case layout_blocked_awc: block_update_awc(vgmstream->next_block_offset,vgmstream); @@ -150,22 +161,27 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * case layout_blocked_vgs: block_update_vgs(vgmstream->next_block_offset,vgmstream); break; - default: + case layout_blocked_vawx: + block_update_vawx(vgmstream->next_block_offset,vgmstream); + break; + default: break; } /* for VBR these may change */ - frame_size = get_vgmstream_frame_size(vgmstream); + frame_size = get_vgmstream_frame_size(vgmstream); /* for VBR these may change */ samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + /* get samples in the current block */ if (vgmstream->current_block_samples) { samples_this_block = vgmstream->current_block_samples; - } else if (frame_size == 0) { + } else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */ samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; } else { samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; } - vgmstream->samples_into_block=0; + + vgmstream->samples_into_block = 0; } } diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_dec.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_dec.c new file mode 100644 index 000000000..3a7809dce --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_dec.c @@ -0,0 +1,21 @@ +#include "layout.h" + +/* Falcom RIFF blocks (.DEC/DE2) */ +void block_update_dec(off_t block_offset, VGMSTREAM * vgmstream) { + STREAMFILE* streamFile = vgmstream->ch[0].streamfile; + size_t block_size, header_size; + int i; + + header_size = 0x08; + block_size = read_32bitLE(block_offset,streamFile); + /* 0x04: PCM size? */ + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = block_size; + vgmstream->next_block_offset = block_offset + block_size + header_size; + + /* MSADPCM = same offset per channel */ + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + header_size; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c new file mode 100644 index 000000000..bcb8e673e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_1snh.c @@ -0,0 +1,83 @@ +#include "layout.h" +#include "../coding/coding.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + STREAMFILE* streamFile = vgmstream->ch[0].streamfile; + uint32_t id; + size_t file_size, block_size = 0, block_header = 0; + int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; + + + /* find target block ID and skip the rest */ + file_size = get_streamfile_size(streamFile); + while (block_offset < file_size) { + id = read_32bitBE(block_offset+0x00,streamFile); + block_size = read_32bit(block_offset+0x04,streamFile); /* includes id/size */ + block_header = 0x0; + + if (id == 0x31534E68) { /* "1SNh" header block found */ + block_header = read_32bitBE(block_offset+0x08, streamFile) == 0x45414353 ? 0x28 : 0x2c; /* "EACS" */ + if (block_header < block_size) /* sometimes has data */ + break; + } + + if (id == 0x31534E64) { /* "1SNd" data block found */ + block_header = 0x08; + break; + } + + if (id == 0x00000000 || id == 0xFFFFFFFF) { /* EOF: possible? */ + break; + } + + /* any other blocks "1SNl" "1SNe" etc */ //todo parse movie blocks + block_offset += block_size; + } + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + vgmstream->current_block_size = block_size - block_header; + + + /* set new channel offsets and block sizes */ + switch(vgmstream->coding_type) { + case coding_PCM8_int: + vgmstream->current_block_size /= vgmstream->channels; + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = block_offset + block_header + i; + } + break; + + case coding_PCM16_int: + vgmstream->current_block_size /= vgmstream->channels; + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = block_offset + block_header + (i*2); + } + break; + + case coding_PSX: + vgmstream->current_block_size /= vgmstream->channels; + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = block_offset + block_header + i*vgmstream->current_block_size; + } + break; + + case coding_DVI_IMA: + vgmstream->current_block_size -= 0x14; + for(i = 0; i < vgmstream->channels; i++) { + off_t adpcm_offset = block_offset + block_header + 0x04; + vgmstream->ch[i].adpcm_step_index = read_32bit(adpcm_offset + i*0x04, streamFile); + vgmstream->ch[i].adpcm_history1_32 = read_32bit(adpcm_offset + 0x04*vgmstream->channels + i*0x04, streamFile); + // todo some demuxed vids don't have ADPCM hist? not sure how to correctly detect + vgmstream->ch[i].offset = block_offset + block_header + 0x14; + } + break; + + default: + break; + } + +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ea_block.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c similarity index 73% rename from Frameworks/vgmstream/vgmstream/src/layout/ea_block.c rename to Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c index 244aad6dc..39c8f2648 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/ea_block.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_schl.c @@ -3,7 +3,7 @@ #include "../vgmstream.h" /* set up for the block at the given offset */ -void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) { +void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) { int i; int new_schl = 0; STREAMFILE* streamFile = vgmstream->ch[0].streamfile; @@ -91,7 +91,7 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) { break; /* id, size, IMA hist, stereo/mono data */ - case coding_EACS_IMA: + case coding_DVI_IMA: for(i = 0; i < vgmstream->channels; i++) { off_t header_offset = block_offset + 0xc + i*4; vgmstream->ch[i].adpcm_history1_32 = read_16bitLE(header_offset+0x00, vgmstream->ch[i].streamfile); @@ -119,6 +119,17 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) { break; + /* id, size, samples, offsets-per-channel, flag (0x01 = data start), data */ + case coding_EA_MT: + 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 + 0x01; + } + + /* flush decoder in every block change */ + flush_ea_mt(vgmstream); + break; + #ifdef VGM_USE_MPEG /* id, size, samples, offset?, unknown (null for MP2, some constant for all blocks for EALayer3) */ case coding_MPEG_custom: @@ -161,64 +172,4 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) { vgmstream->next_block_offset = block_offset + block_size; vgmstream->current_block_samples = block_samples; vgmstream->current_block_size = 0; /* uses current_block_samples instead */ - - - /* reset channel sub offset for codecs using it */ - if (vgmstream->coding_type == coding_EA_XA - || vgmstream->coding_type == coding_EA_XA_int - || vgmstream->coding_type == coding_EA_XA_V2) { - for(i=0;ichannels;i++) { - vgmstream->ch[i].channel_start_offset=0; - } - } -} - -void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - off_t block_size=vgmstream->current_block_size; - - if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) { - block_offset+=0x0C; - } - - vgmstream->current_block_offset = block_offset; - - if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E64) { /* 1Snd */ - block_offset+=4; - if(vgmstream->ea_platform==0) - block_size=read_32bitLE(vgmstream->current_block_offset+0x04, - vgmstream->ch[0].streamfile); - else - block_size=read_32bitBE(vgmstream->current_block_offset+0x04, - vgmstream->ch[0].streamfile); - block_offset+=4; - } - - vgmstream->current_block_size=block_size-8; - - if(vgmstream->coding_type==coding_EACS_IMA) { - vgmstream->current_block_size=read_32bitLE(block_offset,vgmstream->ch[0].streamfile); - - for(i=0;ichannels;i++) { - vgmstream->ch[i].adpcm_step_index = read_32bitLE(block_offset+0x04+i*4,vgmstream->ch[0].streamfile); - vgmstream->ch[i].adpcm_history1_32 = read_32bitLE(block_offset+0x04+i*4+(4*vgmstream->channels),vgmstream->ch[0].streamfile); - vgmstream->ch[i].offset = block_offset+0x14; - } - } else { - if(vgmstream->coding_type==coding_PSX) { - for (i=0;ichannels;i++) - vgmstream->ch[i].offset = vgmstream->current_block_offset+8+(i*(vgmstream->current_block_size/2)); - } else { - - for (i=0;ichannels;i++) { - if(vgmstream->coding_type==coding_PCM16_int) - vgmstream->ch[i].offset = block_offset+(i*2); - else - vgmstream->ch[i].offset = block_offset+i; - } - } - vgmstream->current_block_size/=vgmstream->channels; - } - vgmstream->next_block_offset = vgmstream->current_block_offset + - (off_t)block_size; } diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ea_sns_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c similarity index 65% rename from Frameworks/vgmstream/vgmstream/src/layout/ea_sns_blocked.c rename to Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c index 6e8c41e29..827ecc938 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/ea_sns_blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ea_sns.c @@ -3,7 +3,7 @@ #include "../vgmstream.h" /* EA "SNS "blocks (most common in .SNS) */ -void ea_sns_block_update(off_t block_offset, VGMSTREAM * vgmstream) { +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); @@ -21,15 +21,25 @@ void ea_sns_block_update(off_t block_offset, VGMSTREAM * vgmstream) { return; } - /* known: 0x80 = last block, 0x40, 0x08, 0x04, 0x01 */ + /* 0x80: last block + * 0x40: new block for some codecs? + * 0x08: ? + * 0x04: new block for some codecs? + * 0x01: last block for some codecs? + * 0x00: none? */ if (block_size & 0xFF000000) { - VGM_ASSERT(!(block_size & 0x80000000), "EA SNS: unknown flag found at %lx\n", block_offset); + //VGM_ASSERT(!(block_size & 0x80000000), "EA SNS: unknown flag found at %lx\n", block_offset); block_size &= 0x00FFFFFF; } for (i = 0; i < vgmstream->channels; i++) { off_t channel_start = 0x00; vgmstream->ch[i].offset = block_offset + 0x08 + channel_start; + + /* also fix first offset (for EALayer3) */ + if (block_offset == vgmstream->ch[i].channel_start_offset) { + vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset; + } } vgmstream->current_block_offset = block_offset; diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ivaud_layout.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ivaud.c similarity index 92% rename from Frameworks/vgmstream/vgmstream/src/layout/ivaud_layout.c rename to Frameworks/vgmstream/vgmstream/src/layout/blocked_ivaud.c index f5df3c7bf..3a950e31a 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/ivaud_layout.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_ivaud.c @@ -2,7 +2,7 @@ #include "../vgmstream.h" /* set up for the block at the given offset */ -void ivaud_block_update(off_t block_offset, VGMSTREAM * vgmstream) { +void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream) { int i; off_t start_offset; off_t interleave_size; diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_vawx.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vawx.c new file mode 100644 index 000000000..dd28dc7ef --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_vawx.c @@ -0,0 +1,25 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* pseudo-blocks that must skip last 0x20 every 0x8000 */ +void block_update_vawx(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + size_t block_size; + + /* no header */ + block_size = vgmstream->channels * 0x10; + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + vgmstream->current_block_size = block_size / vgmstream->channels; + + if ((vgmstream->next_block_offset - 0x800) > 0 + && ((vgmstream->next_block_offset - 0x800 + 0x20) % 0x8000) == 0) { + vgmstream->next_block_offset += 0x20; + } + + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = block_offset + 0x10*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/de2_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/de2_blocked.c deleted file mode 100644 index a89ddbafa..000000000 --- a/Frameworks/vgmstream/vgmstream/src/layout/de2_blocked.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* set up for the block at the given offset */ -void de2_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, - vgmstream->ch[0].streamfile); - vgmstream->next_block_offset = block_offset+8+read_32bitLE( - vgmstream->current_block_offset, - vgmstream->ch[0].streamfile); - - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset + 8; - } -} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/interleave_byte.c b/Frameworks/vgmstream/vgmstream/src/layout/interleave_byte.c deleted file mode 100644 index c9f8eb088..000000000 --- a/Frameworks/vgmstream/vgmstream/src/layout/interleave_byte.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* for formats where the interleave is smaller than a frame, so we need to - * deinterleave in memory before passing it along to a specialized decoder which - * reads from memory - */ - -/* just do one frame at a time */ - -void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { - /* frame sizes are much smaller than this */ - uint8_t sample_data[0x400]; - int samples_written=0; - - int frame_size = get_vgmstream_frame_size(vgmstream); - int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); - int samples_this_block; - - samples_this_block = samples_per_frame; - - while (samples_writtenloop_flag && vgmstream_do_loop(vgmstream)) { - continue; - } - - samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); - - if (samples_written+samples_to_do > sample_count) - samples_to_do=sample_count-samples_written; - - { - int i,j; - for (j=0;jchannels;j++) { - for (i=0;ich[j].offset+ - i/vgmstream->interleave_block_size* - vgmstream->interleave_block_size* - vgmstream->channels+ - i%vgmstream->interleave_block_size, - vgmstream->ch[j].streamfile); - } - decode_vgmstream_mem(vgmstream, samples_written, - samples_to_do, buffer, sample_data, j); - } - } - - samples_written += samples_to_do; - vgmstream->current_sample += samples_to_do; - vgmstream->samples_into_block+=samples_to_do; - - if (vgmstream->samples_into_block==samples_this_block) { - int chan; - for (chan=0;chanchannels;chan++) - vgmstream->ch[chan].offset+=frame_size*vgmstream->channels; - vgmstream->samples_into_block=0; - } - - } -} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/layout.h b/Frameworks/vgmstream/vgmstream/src/layout/layout.h index b3af1efc0..9e946ed2c 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/layout.h +++ b/Frameworks/vgmstream/vgmstream/src/layout/layout.h @@ -5,19 +5,18 @@ #include "../vgmstream.h" /* blocked layouts */ +void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + void ast_block_update(off_t block_ofset, VGMSTREAM * vgmstream); void mxch_block_update(off_t block_ofset, VGMSTREAM * vgmstream); -void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); - void halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream); void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream); -void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream); void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream); @@ -29,7 +28,7 @@ void ws_aud_block_update(off_t block_offset, VGMSTREAM * vgmstream); void matx_block_update(off_t block_offset, VGMSTREAM * vgmstream); -void de2_block_update(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_dec(off_t block_offset, VGMSTREAM * vgmstream); void vs_block_update(off_t block_offset, VGMSTREAM * vgmstream); @@ -45,7 +44,7 @@ void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream); void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream); -void ivaud_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); @@ -63,18 +62,16 @@ void rws_block_update(off_t block_offset, VGMSTREAM * vgmstream); void hwas_block_update(off_t block_offset, VGMSTREAM * vgmstream); -void ea_sns_block_update(off_t block_offset, VGMSTREAM * vgmstream); - +void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream); void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream); void block_update_vgs(off_t block_offset, VGMSTREAM * vgmstream); +void block_update_vawx(off_t block_offset, VGMSTREAM * vgmstream); /* other layouts */ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); -void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); - void render_vgmstream_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); diff --git a/Frameworks/vgmstream/vgmstream/src/layout/str_snds_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/str_snds_blocked.c index e18f1510e..91b64d60e 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/str_snds_blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/str_snds_blocked.c @@ -48,7 +48,7 @@ void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream) { read_32bitBE(vgmstream->current_block_offset+4, vgmstream->ch[0].streamfile); - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18; + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18 + i * vgmstream->interleave_block_size; } } diff --git a/Frameworks/vgmstream/vgmstream/src/layout/thp_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/thp_blocked.c index f4ed39e87..828d6c8de 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/thp_blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/thp_blocked.c @@ -12,8 +12,8 @@ void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream) { nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile); vgmstream->next_block_offset = vgmstream->current_block_offset - + vgmstream->thpNextFrameSize; - vgmstream->thpNextFrameSize=nextFrameSize; + + vgmstream->full_block_size; + vgmstream->full_block_size = nextFrameSize; start_offset=vgmstream->current_block_offset + read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10; diff --git a/Frameworks/vgmstream/vgmstream/src/layout/xa_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/xa_blocked.c index e84cb15b4..b8bdd4f1c 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/xa_blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/xa_blocked.c @@ -4,48 +4,69 @@ /* set up for the block at the given offset */ void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + int8_t currentChannel=0; + int8_t subAudio=0; - int i; - int8_t currentChannel=0; - int8_t subAudio=0; - - init_get_high_nibble(vgmstream); + xa_init_get_high_nibble(vgmstream); - if(vgmstream->samples_into_block!=0) - // don't change this variable in the init process - vgmstream->xa_sector_length+=128; + /* don't change this variable in the init process */ + if (vgmstream->samples_into_block != 0) + vgmstream->xa_sector_length += 0x80; - // We get to the end of a sector ? - if(vgmstream->xa_sector_length==(18*128)) { - vgmstream->xa_sector_length=0; + /* XA mode2/form2 sector + * 0x00: sync word + * 0x0c: header = minute, second, sector, mode (always 0x02) + * 0x10: subheader = file, channel (marker), submode flags, xa header + * 0x14: subheader again + * 0x18: data + * 0x918: unused + * 0x92c: EDC/checksum or null + * 0x930: end + */ - // 0x30 of unused bytes/sector :( - if (!vgmstream->xa_headerless) { - block_offset+=0x30; + /* submode flags (typical audio value = 0x64) + * - 7: end of file + * - 6: real time mode + * - 5: sector form (0=form1, 1=form2) + * - 4: trigger (for application) + * - 3: data sector + * - 2: audio sector + * - 1: video sector + * - 0: end of audio + */ + + // We get to the end of a sector ? + if (vgmstream->xa_sector_length == (18*0x80)) { + vgmstream->xa_sector_length = 0; + + // 0x30 of unused bytes/sector :( + if (!vgmstream->xa_headerless) { + block_offset += 0x30; begin: - // Search for selected channel & valid audio - currentChannel=read_8bit(block_offset-7,vgmstream->ch[0].streamfile); - subAudio=read_8bit(block_offset-6,vgmstream->ch[0].streamfile); + // Search for selected channel & valid audio + currentChannel = read_8bit(block_offset-0x07,vgmstream->ch[0].streamfile); + subAudio = read_8bit(block_offset-0x06,vgmstream->ch[0].streamfile); - // audio is coded as 0x64 - if(!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) { - // go to next sector - block_offset+=2352; - if(currentChannel!=-1) goto begin; - } - } - } + // audio is coded as 0x64 + if (!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) { + // go to next sector + block_offset += 0x930; + if (currentChannel!=-1) goto begin; + } + } + } - vgmstream->current_block_offset = block_offset; + vgmstream->current_block_offset = block_offset; - // Quid : how to stop the current channel ??? - // i set up 0 to current_block_size to make vgmstream not playing bad samples - // another way to do it ??? - // (as the number of samples can be false in cd-xa due to multi-channels) - vgmstream->current_block_size = (currentChannel==-1?0:112); - - vgmstream->next_block_offset = vgmstream->current_block_offset+128; - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset; - } + // Quid : how to stop the current channel ??? + // i set up 0 to current_block_size to make vgmstream not playing bad samples + // another way to do it ??? + // (as the number of samples can be false in cd-xa due to multi-channels) + vgmstream->current_block_size = (currentChannel==-1 ? 0 : 0x70); + + vgmstream->next_block_offset = vgmstream->current_block_offset + 0x80; + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset; + } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c index 39d5d5e06..54218e20b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c @@ -3,8 +3,7 @@ #include "../util.h" /* .dsp w/ Cstr header, seen in Star Fox Assault and Donkey Konga */ - -VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aax.c b/Frameworks/vgmstream/vgmstream/src/meta/aax.c index 47b02f290..b37c70f84 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aax.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aax.c @@ -1,16 +1,5 @@ -#include "../vgmstream.h" #include "meta.h" -#include "../util.h" - -typedef struct _AAXSTREAMFILE -{ - STREAMFILE sf; - STREAMFILE *real_file; - off_t start_physical_offset; - size_t file_size; -} AAXSTREAMFILE; - -static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size); +#include "aax_streamfile.h" struct utf_query { @@ -107,10 +96,9 @@ struct utf_table_info }; -/* Actual AAX init fcn */ +/* AAX - segmented ADX [Padora's Tower (Wii)] */ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { - - VGMSTREAM * vgmstream = NULL; + VGMSTREAM * vgmstream = NULL; STREAMFILE * streamFileAAX = NULL; STREAMFILE * streamFileADX = NULL; char filename[PATH_LIMIT]; @@ -131,7 +119,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { int channel_count = 0, segment_count; int sample_rate = 0; - int i; + int i; long aax_data_offset; @@ -297,91 +285,6 @@ fail: return NULL; } -/* virtual file, a piece of the overall file */ - -static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) -{ - /* truncate at end of logical file */ - if (offset+length > streamfile->file_size) - { - long signed_length = length; - signed_length = streamfile->file_size - offset; - if (signed_length < 0) signed_length = 0; - length = signed_length; - } - return read_streamfile(dest, - streamfile->start_physical_offset+offset, - length,streamfile->real_file); -} - -static void close_aax(AAXSTREAMFILE *streamfile) -{ - free(streamfile); - return; -} - -static size_t get_size_aax(AAXSTREAMFILE *streamfile) -{ - return 0; -} - -static size_t get_offset_aax(AAXSTREAMFILE *streamfile) -{ - long offset = streamfile->real_file->get_offset(streamfile->real_file); - offset -= streamfile->start_physical_offset; - if (offset < 0) offset = 0; - if (offset > streamfile->file_size) offset = streamfile->file_size; - - return offset; -} - -static void get_name_aax(AAXSTREAMFILE *streamfile,char *buffer,size_t length) -{ - strncpy(buffer,"ARBITRARY.ADX",length); - buffer[length-1]='\0'; -} - -static STREAMFILE *open_aax_impl(AAXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) -{ - AAXSTREAMFILE *newfile; - if (strcmp(filename,"ARBITRARY.ADX")) - return NULL; - - newfile = malloc(sizeof(AAXSTREAMFILE)); - if (!newfile) - return NULL; - memcpy(newfile,streamfile,sizeof(AAXSTREAMFILE)); - return &newfile->sf; -} - -static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size) -{ - AAXSTREAMFILE *streamfile = malloc(sizeof(AAXSTREAMFILE)); - - if (!streamfile) - return NULL; - - /* success, set our pointers */ - - streamfile->sf.read = (void*)read_aax; - streamfile->sf.get_size = (void*)get_size_aax; - streamfile->sf.get_offset = (void*)get_offset_aax; - streamfile->sf.get_name = (void*)get_name_aax; - streamfile->sf.get_realname = (void*)get_name_aax; - streamfile->sf.open = (void*)open_aax_impl; - streamfile->sf.close = (void*)close_aax; -#ifdef PROFILE_STREAMFILE - streamfile->sf.get_bytes_read = NULL; - streamfile->sf.get_error_count = NULL; -#endif - - streamfile->real_file = file; - streamfile->start_physical_offset = start_offset; - streamfile->file_size = file_size; - - return &streamfile->sf; -} - /* @UTF table reading, abridged */ static struct utf_query_result analyze_utf(STREAMFILE *infile, const long offset, const struct utf_query *query) { @@ -744,8 +647,7 @@ static struct offset_size_pair query_utf_data(STREAMFILE *infile, const long off /* CRI's UTF wrapper around DSP */ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { - - VGMSTREAM * vgmstream = NULL; + VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; int table_error = 0; @@ -843,4 +745,3 @@ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; } - diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aax_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/aax_streamfile.h new file mode 100644 index 000000000..9caacab6e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/aax_streamfile.h @@ -0,0 +1,87 @@ +#ifndef _AAX_STREAMFILE_H_ +#define _AAX_STREAMFILE_H_ +#include "../streamfile.h" + +/* a streamfile representing a subfile inside another */ + +typedef struct _AAXSTREAMFILE { + STREAMFILE sf; + STREAMFILE *real_file; + off_t start_physical_offset; + size_t file_size; +} AAXSTREAMFILE; + +static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) { + /* truncate at end of logical file */ + if (offset+length > streamfile->file_size) { + long signed_length = length; + signed_length = streamfile->file_size - offset; + if (signed_length < 0) signed_length = 0; + length = signed_length; + } + return read_streamfile(dest, streamfile->start_physical_offset+offset, length,streamfile->real_file); +} + +static void close_aax(AAXSTREAMFILE *streamfile) { + free(streamfile); + return; +} + +static size_t get_size_aax(AAXSTREAMFILE *streamfile) { + return 0; +} + +static size_t get_offset_aax(AAXSTREAMFILE *streamfile) { + long offset = streamfile->real_file->get_offset(streamfile->real_file); + offset -= streamfile->start_physical_offset; + if (offset < 0) offset = 0; + if (offset > streamfile->file_size) offset = streamfile->file_size; + + return offset; +} + +static void get_name_aax(AAXSTREAMFILE *streamfile,char *buffer,size_t length) { + strncpy(buffer,"ARBITRARY.ADX",length); + buffer[length-1]='\0'; +} + +static STREAMFILE *open_aax_impl(AAXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) { + AAXSTREAMFILE *newfile; + if (strcmp(filename,"ARBITRARY.ADX")) + return NULL; + + newfile = malloc(sizeof(AAXSTREAMFILE)); + if (!newfile) + return NULL; + memcpy(newfile,streamfile,sizeof(AAXSTREAMFILE)); + return &newfile->sf; +} + +static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size) { + AAXSTREAMFILE *streamfile = malloc(sizeof(AAXSTREAMFILE)); + + if (!streamfile) + return NULL; + + /* success, set our pointers */ + + streamfile->sf.read = (void*)read_aax; + streamfile->sf.get_size = (void*)get_size_aax; + streamfile->sf.get_offset = (void*)get_offset_aax; + streamfile->sf.get_name = (void*)get_name_aax; + streamfile->sf.get_realname = (void*)get_name_aax; + streamfile->sf.open = (void*)open_aax_impl; + streamfile->sf.close = (void*)close_aax; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = NULL; + streamfile->sf.get_error_count = NULL; +#endif + + streamfile->real_file = file; + streamfile->start_physical_offset = start_offset; + streamfile->file_size = file_size; + + return &streamfile->sf; +} + +#endif /* _AAX_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/adx.c b/Frameworks/vgmstream/vgmstream/src/meta/adx.c index ed6700808..683e5cc0b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/adx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/adx.c @@ -2,12 +2,13 @@ #define _USE_MATH_DEFINES #endif #include -#include #include -#include "meta.h" +#include "meta.h" +#include "adx_keys.h" #include "../coding/coding.h" -#include "../util.h" + +#define MAX_TEST_FRAMES (INT_MAX/0x8000) static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add); @@ -233,270 +234,6 @@ fail: return NULL; } -/* guessadx stuff */ - -/* type 8 keys */ -static struct { - uint16_t start,mult,add; -} keys_8[] = { - /* Clover Studio (GOD HAND, Okami) */ - /* Verified by VGAudio and the game's executable */ - /* Key string: karaage */ - {0x49e1,0x4a57,0x553d}, - - /* Grasshopper Manufacture 0 (Blood+) */ - /* this is estimated */ - {0x5f5d,0x58bd,0x55ed}, - - /* Grasshopper Manufacture 1 (Killer7) */ - /* this is estimated */ - {0x50fb,0x5803,0x5701}, - - /* Grasshopper Manufacture 2 (Samurai Champloo) */ - /* confirmed unique with guessadx */ - {0x4f3f,0x472f,0x562f}, - - /* Moss Ltd (Raiden III) */ - /* this is estimated */ - {0x66f5,0x58bd,0x4459}, - - /* Sonic Team 0 (Phantasy Star Universe) */ - /* Verified by VGAudio and the game's executable */ - /* Key string: 3x5k62bg9ptbwy */ - {0x5deb,0x5f27,0x673f}, - - /* G.rev 0 (Senko no Ronde) */ - /* this is estimated */ - {0x46d3,0x5ced,0x474d}, - - /* Sonic Team 1 (NiGHTS: Journey of Dreams) */ - /* this seems to be dead on, but still estimated */ - {0x440b,0x6539,0x5723}, - - /* from guessadx (unique?), unknown source */ - {0x586d,0x5d65,0x63eb}, - - /* Navel (Shuffle! On the Stage) */ - /* 2nd key from guessadx */ - {0x4969,0x5deb,0x467f}, - - /* Success (Aoishiro) */ - /* 1st key from guessadx */ - {0x4d65,0x5eb7,0x5dfd}, - - /* Sonic Team 2 (Sonic and the Black Knight) */ - /* Verified by VGAudio and the game's executable */ - /* Key string: morio */ - {0x55b7,0x6191,0x5a77}, - - /* Enterbrain (Amagami) */ - /* Verified by VGAudio and the game's executable */ - /* Key string: mituba */ - {0x5a17,0x509f,0x5bfd}, - - /* Yamasa (Yamasa Digi Portable: Matsuri no Tatsujin) */ - /* confirmed unique with guessadx */ - {0x4c01,0x549d,0x676f}, - - /* Kadokawa Shoten (Fragments Blue) */ - /* confirmed unique with guessadx */ - {0x5803,0x4555,0x47bf}, - - /* Namco (Soulcalibur IV) */ - /* confirmed unique with guessadx */ - {0x59ed,0x4679,0x46c9}, - - /* G.rev 1 (Senko no Ronde DUO) */ - /* from guessadx */ - {0x6157,0x6809,0x4045}, - - /* ASCII Media Works 0 (Nogizaka Haruka no Himitsu: Cosplay Hajimemashita) */ - /* 2nd from guessadx, other was {0x45ad,0x5f27,0x10fd} */ - {0x45af,0x5f27,0x52b1}, - - /* D3 Publisher 0 (Little Anchor) */ - /* confirmed unique with guessadx */ - {0x5f65,0x5b3d,0x5f65}, - - /* Marvelous 0 (Hanayoi Romanesque: Ai to Kanashimi) */ - /* 2nd from guessadx, other was {0x5562,0x5047,0x1433} */ - {0x5563,0x5047,0x43ed}, - - /* Capcom (Mobile Suit Gundam: Gundam vs. Gundam NEXT PLUS) */ - /* confirmed unique with guessadx */ - {0x4f7b,0x4fdb,0x5cbf}, - - /* Developer: Bridge NetShop - * Publisher: Kadokawa Shoten (Shoukan Shoujo: Elemental Girl Calling) */ - /* confirmed unique with guessadx */ - {0x4f7b,0x5071,0x4c61}, - - /* Developer: Net Corporation - * Publisher: Tecmo (Rakushou! Pachi-Slot Sengen 6: Rio 2 Cruising Vanadis) */ - /* confirmed unique with guessadx */ - {0x53e9,0x586d,0x4eaf}, - - /* Developer: Aquaplus - * Tears to Tiara Gaiden Avalon no Kagi (PS3) */ - /* confirmed unique with guessadx */ - {0x47e1,0x60e9,0x51c1}, - - /* Developer: Broccoli - * Neon Genesis Evangelion: Koutetsu no Girlfriend 2nd (PS2) */ - /* confirmed unique with guessadx */ - {0x481d,0x4f25,0x5243}, - - /* Developer: Marvelous - * Futakoi Alternative (PS2) */ - /* confirmed unique with guessadx */ - {0x413b,0x543b,0x57d1}, - - /* Developer: Marvelous - * Gakuen Utopia - Manabi Straight! KiraKira Happy Festa! (PS2) - * Second guess from guessadx, other was - * {0x440b,0x4327,0x564b} - **/ - {0x440d,0x4327,0x4fff}, - - /* Developer: Datam Polystar - * Soshite Kono Uchuu ni Kirameku Kimi no Shi XXX (PS2) */ - /* confirmed unique with guessadx */ - {0x5f5d,0x552b,0x5507}, - - /* Developer: Sega - * Sakura Taisen: Atsuki Chishio Ni (PS2) */ - /* confirmed unique with guessadx */ - {0x645d,0x6011,0x5c29}, - - /* Developer: Sega - * Sakura Taisen 3 ~Paris wa Moeteiru ka~ (PS2) */ - /* confirmed unique with guessadx */ - {0x62ad,0x4b13,0x5957}, - - /* Developer: Jinx - * Sotsugyou 2nd Generation (PS2) - * First guess from guessadx, other was - * {0x6307,0x509f,0x2ac5} - */ - {0x6305,0x509f,0x4c01}, - - /* - * La Corda d'Oro (2005)(-)(Koei)[PSP] - * confirmed unique with guessadx */ - {0x55b7,0x67e5,0x5387}, - - /* - * Nanatsuiro * Drops Pure!! (2007)(Media Works)[PS2] - * confirmed unique with guessadx */ - {0x6731,0x645d,0x566b}, - - /* - * Shakugan no Shana (2006)(Vridge)(Media Works)[PS2] - * confirmed unique with guessadx */ - {0x5fc5,0x63d9,0x599f}, - - /* - * Uragiri wa Boku no Namae o Shitteiru (2010)(Kadokawa Shoten)[PS2] - * confirmed unique with guessadx */ - {0x4c73,0x4d8d,0x5827}, - - /* - * StormLover Kai!! (2012)(D3 Publisher)[PSP] - * confirmed unique with guessadx */ - {0x5a11,0x67e5,0x6751}, - - /* - * Sora no Otoshimono - DokiDoki Summer Vacation (2010)(Kadokawa Shoten)[PSP] - * confirmed unique with guessadx */ - {0x5e75,0x4a89,0x4c61}, - - /* - * Boku wa Koukuu Kanseikan - Airport Hero Naha (2006)(Sonic Powered)(Electronic Arts)[PSP] - * confirmed unique with guessadx */ - {0x64ab,0x5297,0x632f}, - - /* - * Lucky Star - Net Idol Meister (2009)(Kadokawa Shoten)[PSP] - * confirmed unique with guessadx */ - {0x4d82,0x5243,0x685}, - - /* - * Ishin Renka: Ryouma Gaiden (2010-11-25)(-)(D3 Publisher)[PSP] - */ - {0x54d1,0x526d,0x5e8b}, - - /* - * Lucky Star - Ryouou Gakuen Outousai Portable (2010-12-22)(-)(Kadokawa Shoten)[PSP] - */ - {0x4d06,0x663b,0x7d09}, - - /* - * Marriage Royale - Prism Story (2010-04-28)(-)(ASCII Media Works)[PSP] - */ - {0x40a9,0x46b1,0x62ad}, - - /* - * Nogizaka Haruka no Himitsu - Doujinshi Hajime Mashita (2010-10-28)(-)(ASCII Media Works)[PSP] - */ - {0x4601,0x671f,0x0455}, - - /* - * Slotter Mania P - Mach Go Go Go III (2011-01-06)(-)(Dorart)[PSP] - */ - {0x41ef,0x463d,0x5507}, - - /* - * Nichijou - Uchuujin (2011-07-28)(-)(Kadokawa Shoten)[PSP] - */ - {0x4369,0x486d,0x5461}, - - /* - * R-15 Portable (2011-10-27)(-)(Kadokawa Shoten)[PSP] - */ - {0x6809,0x5fd5,0x5bb1}, - - /* - * Suzumiya Haruhi-chan no Mahjong (2011-07-07)(-)(Kadokawa Shoten)[PSP] - */ - {0x5c33,0x4133,0x4ce7}, - - // Storm Lover Natsu Koi!! (2011-08-04)(Vridge)(D3 Publisher) - {0x4133,0x5a01,0x5723}, - -}; - -/* type 9 keys (may not be autodetected correctly) */ -static struct { - uint16_t start,mult,add; -} keys_9[] = { - /* Phantasy Star Online 2 - * guessed with degod */ - {0x07d2,0x1ec5,0x0c7f}, - - /* Dragon Ball Z: Dokkan Battle - * Verified by VGAudio - * Key code: 416383518 */ - {0x0003,0x0d19,0x043b}, - - /* Kisou Ryouhei Gunhound EX (2013-01-31)(Dracue)[PSP] - * Verified by VGAudio - * Key code: 683461999 */ - {0x0005,0x0bcd,0x1add}, - - /* Raramagi [Android] - * Verified by VGAudio - * Key code: 12160794 */ - {0x0000,0x0b99,0x1e33}, - - /* Sonic runners [Android] - * Verified by VGAudio - * Key code: 19910623 */ - {0x0000,0x12fd,0x1fbd}, - -}; - -static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]); -static const int keys_9_count = sizeof(keys_9)/sizeof(keys_9[0]); /* return 0 if not found, 1 if found and set parameters */ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add) @@ -521,7 +258,7 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_ } - /* guess key from the tables above */ + /* guess key from the tables */ startoff=read_16bitBE(2, file)+4; endoff=(read_32bitBE(12, file)+31)/32*18*read_8bit(7, file)+startoff; @@ -558,14 +295,13 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_ { /* try to guess key */ -#define MAX_FRAMES (INT_MAX/0x8000) - struct { uint16_t start, mult, add; } *keys = NULL; + const adxkey_info * keys = NULL; int keycount = 0, keymask = 0; int scales_to_do; int key_id; /* allocate storage for scales */ - scales_to_do = (bruteframecount > MAX_FRAMES ? MAX_FRAMES : bruteframecount); + scales_to_do = (bruteframecount > MAX_TEST_FRAMES ? MAX_TEST_FRAMES : bruteframecount); scales = malloc(scales_to_do*sizeof(uint16_t)); if (!scales) { goto find_key_cleanup; @@ -595,8 +331,8 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_ if (type == 8) { - keys = &keys_8; - keycount = keys_8_count; + keys = adxkey8_list; + keycount = adxkey8_list_count; keymask = 0x6000; } else if (type == 9) @@ -605,8 +341,8 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_ * but the maximum value assigned by the encoder is 0x1000. * This is written to the ADX file as 0xFFF, leaving the high bit * empty, which is used to validate a key */ - keys = &keys_9; - keycount = keys_9_count; + keys = adxkey9_list; + keycount = adxkey9_list_count; keymask = 0x1000; } @@ -618,6 +354,23 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_ uint16_t add = keys[key_id].add; int i; +#ifdef ADX_VERIFY_DERIVED_KEYS + { + uint16_t test_start, test_mult, test_add; + if (type == 8 && keys[key_id].key8) { + process_cri_key8(keys[key_id].key8, &test_start, &test_mult, &test_add); + VGM_LOG("key8: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (\"%s\")\n", + xor,mult,add, test_start,test_mult,test_add, xor==test_start && mult==test_mult && add==test_add ? "ok" : "ko", keys[key_id].key8); + } + else if (type == 9 && keys[key_id].key9) { + process_cri_key9(keys[key_id].key9, &test_start, &test_mult, &test_add); + VGM_LOG("key9: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (%"PRIu64")\n", + xor,mult,add, test_start,test_mult,test_add, xor==test_start && mult==test_mult && add==test_add ? "ok" : "ko", keys[key_id].key9); + } + continue; + } +#endif + for (i=0;i> 27) & 0x7fff)); + mult = (int)(((key9 >> 12) & 0x7ffc) | 1); + add = (int)(((key9 << 1 ) & 0x7fff) | 1); + + /* alt from ADX_Decoder, probably the same */ + //start = ((key9 >> 27) & 0x7FFF); + //mult = ((key9 >> 12) & 0x7FFC) | 1; + //add = ((key9 << 1 ) & 0x7FFE) | 1; + //mult |= add << 16; + +end: + *out_start = start; + *out_mult = mult; + *out_add = add; +} + +#endif + +#endif/*_ADX_KEYS_H_*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/afc_header.c b/Frameworks/vgmstream/vgmstream/src/meta/afc.c similarity index 100% rename from Frameworks/vgmstream/vgmstream/src/meta/afc_header.c rename to Frameworks/vgmstream/vgmstream/src/meta/afc.c diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aifc.c b/Frameworks/vgmstream/vgmstream/src/meta/aifc.c index d46617e1c..772dd1813 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aifc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aifc.c @@ -8,7 +8,7 @@ /* Included primarily for 3DO */ /* for reading integers inexplicably packed into 80 bit floats */ -uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) { +static uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) { uint8_t buf[10]; int32_t exponent; int32_t mantissa; @@ -31,7 +31,7 @@ uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) { return mantissa*((buf[0]&0x80)?-1:1); } -uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset, +static uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset, int marker_id) { uint16_t marker_count; int i; @@ -173,7 +173,7 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) { interleave = 1; break; case 0x41445034: /* ADP4 */ - coding_type = coding_DVI_IMA; + coding_type = coding_DVI_IMA_int; /* don't know how stereo DVI is laid out */ if (channel_count != 1) break; break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aix.c b/Frameworks/vgmstream/vgmstream/src/meta/aix.c index 840af854a..682dced53 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aix.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aix.c @@ -1,20 +1,7 @@ -#include "../vgmstream.h" #include "meta.h" -#include "../util.h" - -typedef struct _AIXSTREAMFILE -{ - STREAMFILE sf; - STREAMFILE *real_file; - off_t start_physical_offset; - off_t current_physical_offset; - off_t current_logical_offset; - off_t current_block_size; - int stream_id; -} AIXSTREAMFILE; - -static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id); +#include "aix_streamfile.h" +/* AIX - interleaved AAX, N segments per channels [SoulCalibur IV (PS3)] */ VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; @@ -61,7 +48,7 @@ VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) { goto fail; sample_rate = read_32bitBE(stream_list_offset+8,streamFile); - if (!check_sample_rate(sample_rate)) + if (sample_rate < 300 || sample_rate > 96000) goto fail; samples_in_segment = calloc(segment_count,sizeof(int32_t)); @@ -228,190 +215,3 @@ fail: } return NULL; } -static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) -{ - size_t sz = 0; - - /*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/ - while (length > 0) - { - int read_something = 0; - - /* read the beginning of the requested block, if we can */ - if (offset >= streamfile->current_logical_offset) - { - off_t to_read; - off_t length_available; - - length_available = - (streamfile->current_logical_offset+ - streamfile->current_block_size) - - offset; - - if (length < length_available) - { - to_read = length; - } - else - { - to_read = length_available; - } - - if (to_read > 0) - { - size_t bytes_read; - - bytes_read = read_streamfile(dest, - streamfile->current_physical_offset+0x10+ - (offset-streamfile->current_logical_offset), - to_read,streamfile->real_file); - - sz += bytes_read; - if (bytes_read != to_read) - { - /* an error which we will not attempt to handle here */ - return sz; - } - - read_something = 1; - - dest += bytes_read; - offset += bytes_read; - length -= bytes_read; - } - } - - if (!read_something) - { - /* couldn't read anything, must seek */ - int found_block = 0; - - /* as we have no memory we must start seeking from the beginning */ - if (offset < streamfile->current_logical_offset) - { - streamfile->current_logical_offset = 0; - streamfile->current_block_size = 0; - streamfile->current_physical_offset = - streamfile->start_physical_offset; - } - - /* seek ye forwards */ - while (!found_block) { - /*printf("seek looks at %x\n",streamfile->current_physical_offset);*/ - switch (read_32bitBE(streamfile->current_physical_offset, - streamfile->real_file)) - { - case 0x41495850: /* AIXP */ - if (read_8bit( - streamfile->current_physical_offset+8, - streamfile->real_file) == - streamfile->stream_id) - { - streamfile->current_block_size = - (uint16_t)read_16bitBE( - streamfile->current_physical_offset+0x0a, - streamfile->real_file); - - if (offset >= streamfile->current_logical_offset+ - streamfile->current_block_size) - { - streamfile->current_logical_offset += - streamfile->current_block_size; - } - else - { - found_block = 1; - } - } - - if (!found_block) - { - streamfile->current_physical_offset += - read_32bitBE( - streamfile->current_physical_offset+0x04, - streamfile->real_file - ) + 8; - } - - break; - case 0x41495846: /* AIXF */ - /* shouldn't ever see this */ - case 0x41495845: /* AIXE */ - /* shouldn't have reached the end o' the line... */ - default: - return sz; - break; - } /* end block/chunk type select */ - } /* end while !found_block */ - } /* end if !read_something */ - } /* end while length > 0 */ - - return sz; -} - -static void close_aix(AIXSTREAMFILE *streamfile) -{ - free(streamfile); - return; -} - -static size_t get_size_aix(AIXSTREAMFILE *streamfile) -{ - return 0; -} - -static size_t get_offset_aix(AIXSTREAMFILE *streamfile) -{ - return streamfile->current_logical_offset; -} - -static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length) -{ - strncpy(buffer,"ARBITRARY.ADX",length); - buffer[length-1]='\0'; -} - -static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) -{ - AIXSTREAMFILE *newfile; - if (strcmp(filename,"ARBITRARY.ADX")) - return NULL; - - newfile = malloc(sizeof(AIXSTREAMFILE)); - if (!newfile) - return NULL; - memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE)); - return &newfile->sf; -} - -static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id) -{ - AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE)); - - if (!streamfile) - return NULL; - - /* success, set our pointers */ - - streamfile->sf.read = (void*)read_aix; - streamfile->sf.get_size = (void*)get_size_aix; - streamfile->sf.get_offset = (void*)get_offset_aix; - streamfile->sf.get_name = (void*)get_name_aix; - streamfile->sf.get_realname = (void*)get_name_aix; - streamfile->sf.open = (void*)open_aix_impl; - streamfile->sf.close = (void*)close_aix; -#ifdef PROFILE_STREAMFILE - streamfile->sf.get_bytes_read = NULL; - streamfile->sf.get_error_count = NULL; -#endif - - streamfile->real_file = file; - streamfile->current_physical_offset = - streamfile->start_physical_offset = start_offset; - streamfile->current_logical_offset = 0; - streamfile->current_block_size = 0; - streamfile->stream_id = stream_id; - - return &streamfile->sf; -} - diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h new file mode 100644 index 000000000..785ba8b9f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/aix_streamfile.h @@ -0,0 +1,169 @@ +#ifndef _AIX_STREAMFILE_H_ +#define _AIX_STREAMFILE_H_ +#include "../streamfile.h" + +/* a streamfile representing a subfile inside another, in blocked AIX format */ + +typedef struct _AIXSTREAMFILE { + STREAMFILE sf; + STREAMFILE *real_file; + off_t start_physical_offset; + off_t current_physical_offset; + off_t current_logical_offset; + off_t current_block_size; + int stream_id; +} AIXSTREAMFILE; + + +/*static*/ STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file, off_t start_offset, int stream_id); + + +static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) { + size_t sz = 0; + + /*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/ + while (length > 0) { + int read_something = 0; + + /* read the beginning of the requested block, if we can */ + if (offset >= streamfile->current_logical_offset) { + off_t to_read; + off_t length_available; + + length_available = (streamfile->current_logical_offset + streamfile->current_block_size) - offset; + + if (length < length_available) { + to_read = length; + } + else { + to_read = length_available; + } + + if (to_read > 0) { + size_t bytes_read; + + bytes_read = read_streamfile(dest, + streamfile->current_physical_offset+0x10 + (offset-streamfile->current_logical_offset), + to_read,streamfile->real_file); + + sz += bytes_read; + if (bytes_read != to_read) { + return sz; /* an error which we will not attempt to handle here */ + } + + read_something = 1; + + dest += bytes_read; + offset += bytes_read; + length -= bytes_read; + } + } + + if (!read_something) { + /* couldn't read anything, must seek */ + int found_block = 0; + + /* as we have no memory we must start seeking from the beginning */ + if (offset < streamfile->current_logical_offset) { + streamfile->current_logical_offset = 0; + streamfile->current_block_size = 0; + streamfile->current_physical_offset = streamfile->start_physical_offset; + } + + /* seek ye forwards */ + while (!found_block) { + /*printf("seek looks at %x\n",streamfile->current_physical_offset);*/ + switch (read_32bitBE(streamfile->current_physical_offset, streamfile->real_file)) { + case 0x41495850: /* AIXP */ + if (read_8bit(streamfile->current_physical_offset+8, streamfile->real_file) == streamfile->stream_id) { + streamfile->current_block_size = (uint16_t)read_16bitBE(streamfile->current_physical_offset+0x0a, streamfile->real_file); + + if (offset >= streamfile->current_logical_offset+ streamfile->current_block_size) { + streamfile->current_logical_offset += streamfile->current_block_size; + } + else { + found_block = 1; + } + } + + if (!found_block) { + streamfile->current_physical_offset += read_32bitBE(streamfile->current_physical_offset+0x04, streamfile->real_file) + 8; + } + + break; + case 0x41495846: /* AIXF */ + /* shouldn't ever see this */ + case 0x41495845: /* AIXE */ + /* shouldn't have reached the end o' the line... */ + default: + return sz; + break; + } /* end block/chunk type select */ + } /* end while !found_block */ + } /* end if !read_something */ + } /* end while length > 0 */ + + return sz; +} + +static void close_aix(AIXSTREAMFILE *streamfile) { + free(streamfile); + return; +} + +static size_t get_size_aix(AIXSTREAMFILE *streamfile) { + return 0; +} + +static size_t get_offset_aix(AIXSTREAMFILE *streamfile) { + return streamfile->current_logical_offset; +} + +static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length) { + strncpy(buffer,"ARBITRARY.ADX",length); + buffer[length-1]='\0'; +} + +static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) { + AIXSTREAMFILE *newfile; + if (strcmp(filename,"ARBITRARY.ADX")) + return NULL; + + newfile = malloc(sizeof(AIXSTREAMFILE)); + if (!newfile) + return NULL; + memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE)); + return &newfile->sf; +} + +/*static*/ STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file, off_t start_offset, int stream_id) { + AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE)); + + if (!streamfile) + return NULL; + + /* success, set our pointers */ + + streamfile->sf.read = (void*)read_aix; + streamfile->sf.get_size = (void*)get_size_aix; + streamfile->sf.get_offset = (void*)get_offset_aix; + streamfile->sf.get_name = (void*)get_name_aix; + streamfile->sf.get_realname = (void*)get_name_aix; + streamfile->sf.open = (void*)open_aix_impl; + streamfile->sf.close = (void*)close_aix; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = NULL; + streamfile->sf.get_error_count = NULL; +#endif + + streamfile->real_file = file; + streamfile->current_physical_offset = start_offset; + streamfile->start_physical_offset = start_offset; + streamfile->current_logical_offset = 0; + streamfile->current_block_size = 0; + streamfile->stream_id = stream_id; + + return &streamfile->sf; +} + +#endif /* _AIX_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/awc.c b/Frameworks/vgmstream/vgmstream/src/meta/awc.c index b91ccb3a8..4d3bf847d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/awc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/awc.c @@ -223,11 +223,12 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) { sample_rate = (uint16_t)read_16bit(offset + 0x0c + 0x10*ch + 0x0a,streamFile); codec = read_8bit(offset + 0x0c + 0x10*ch + 0x0c, streamFile); - /* validate as all channels should repeat this */ - if ((awc->num_samples && awc->num_samples != num_samples) || + /* validate as all channels should repeat this (when channels is even and > 2 seems + * it's stereo pairs, and num_samples can vary slightly but no matter) */ + if ((awc->num_samples && !(awc->num_samples >= num_samples - 10 && awc->num_samples <= num_samples + 10)) || (awc->sample_rate && awc->sample_rate != sample_rate) || (awc->codec && awc->codec != codec)) { - VGM_LOG("AWC: found header diffs between channels\n"); /* can rarely happen in stereo pairs */ + VGM_LOG("AWC: found header diffs between channels\n"); goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bar.c b/Frameworks/vgmstream/vgmstream/src/meta/bar.c new file mode 100644 index 000000000..636e80020 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/bar.c @@ -0,0 +1,77 @@ +#include "meta.h" +#include "bar_streamfile.h" + +/* Guitar Hero III Mobile .bar */ +VGMSTREAM * init_vgmstream_bar(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE* streamFileBAR = NULL; // don't close, this is just the source streamFile wrapped + char filename[PATH_LIMIT]; + off_t start_offset; + off_t ch2_start_offset; + int loop_flag; + int channel_count; + long file_size; + + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bar",filename_extension(filename))) goto fail; + + /* decryption wrapper for header reading */ + streamFileBAR = wrap_bar_STREAMFILE(streamFile); + if (!streamFileBAR) goto fail; + + file_size = get_streamfile_size(streamFileBAR); + + /* check header */ + if (read_32bitBE(0x00,streamFileBAR) != 0x11000100 || + read_32bitBE(0x04,streamFileBAR) != 0x01000200) goto fail; + if (read_32bitLE(0x50,streamFileBAR) != file_size) goto fail; + + start_offset = read_32bitLE(0x18,streamFileBAR); + if (0x54 != start_offset) goto fail; + ch2_start_offset = read_32bitLE(0x48,streamFileBAR); + if (ch2_start_offset >= file_size) goto fail; + + /* build the VGMSTREAM */ + channel_count = 2; + loop_flag = 0; + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = 11025; + vgmstream->coding_type = coding_IMA; + vgmstream->num_samples = (file_size-ch2_start_offset)*2; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_GH3_BAR; + + { + STREAMFILE *file1, *file2; + file1 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file1) goto fail; + file2 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file2) + { + close_streamfile(file1); + goto fail; + } + vgmstream->ch[0].streamfile = file1; + vgmstream->ch[1].streamfile = file2; + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + vgmstream->ch[1].channel_start_offset= + vgmstream->ch[1].offset=ch2_start_offset; + } + + // discard our decrypt wrapper, without closing the original streamfile + free(streamFileBAR); + + return vgmstream; +fail: + if (streamFileBAR) + free(streamFileBAR); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h new file mode 100644 index 000000000..8305020c5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h @@ -0,0 +1,100 @@ +#ifndef _BAR_STREAMFILE_H_ +#define _BAR_STREAMFILE_H_ +#include "../streamfile.h" + +/* a streamfile wrapping another for decryption */ + +enum {BAR_KEY_LENGTH = 16}; + +// don't know if this is unique, but seems accurate +static const uint8_t bar_key[BAR_KEY_LENGTH] = { + 0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6, + 0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80 +}; + +typedef struct _BARSTREAMFILE { + STREAMFILE sf; + STREAMFILE *real_file; +} BARSTREAMFILE; + + +/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file); + + +static size_t read_bar(BARSTREAMFILE *streamFile, uint8_t *dest, off_t offset, size_t length) { + off_t i; + size_t read_length = streamFile->real_file->read(streamFile->real_file, dest, offset, length); + + for (i = 0; i < read_length; i++) { + dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH]; + } + + return read_length; +} + +static size_t get_size_bar(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_size(streamFile->real_file); +} + +static size_t get_offset_bar(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_offset(streamFile->real_file); +} + +static void get_name_bar(BARSTREAMFILE *streamFile, char *name, size_t length) { + return streamFile->real_file->get_name(streamFile->real_file, name, length); +} + +static void get_realname_bar(BARSTREAMFILE *streamFile, char *name, size_t length) { + return streamFile->real_file->get_realname(streamFile->real_file, name, length); +} + +STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) { + STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize); + if (!newfile) + return NULL; + + return wrap_bar_STREAMFILE(newfile); +} + +static void close_bar(BARSTREAMFILE *streamFile) { + streamFile->real_file->close(streamFile->real_file); + free(streamFile); + return; +} + +#ifdef PROFILE_STREAMFILE +size_t get_bytes_read_bar(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_bytes_read(streamFile->real_file); +} + +int (*get_error_count)(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_error_count(streamFile->real_file); +} +#endif + +/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) { + BARSTREAMFILE *streamfile = malloc(sizeof(BARSTREAMFILE)); + + if (!streamfile) + return NULL; + + memset(streamfile, 0, sizeof(BARSTREAMFILE)); + + streamfile->sf.read = (void*)read_bar; + streamfile->sf.get_size = (void*)get_size_bar; + streamfile->sf.get_offset = (void*)get_offset_bar; + streamfile->sf.get_name = (void*)get_name_bar; + streamfile->sf.get_realname = (void*)get_realname_bar; + streamfile->sf.open = (void*)open_bar; + streamfile->sf.close = (void*)close_bar; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = get_bytes_read_bar; + streamfile->sf.get_error_count = get_error_count_bar; +#endif + + streamfile->real_file = file; + + return &streamfile->sf; +} + +#endif /* _BAR_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c b/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c index 93bb1d3e0..2d8c83659 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c @@ -3,166 +3,166 @@ /* BCSTM - Nintendo 3DS format */ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - coding_t coding_type; + VGMSTREAM * vgmstream = NULL; + coding_t coding_type; - off_t info_offset = 0, seek_offset = 0, data_offset = 0; - uint16_t temp_id; - int codec_number; - int channel_count, loop_flag; - int i, ima = 0; - off_t start_offset; - int section_count; + off_t info_offset = 0, seek_offset = 0, data_offset = 0; + uint16_t temp_id; + int codec_number; + int channel_count, loop_flag; + int i, ima = 0; + off_t start_offset; + int section_count; - /* check extension, case insensitive */ + /* check extension, case insensitive */ if ( !check_extensions(streamFile,"bcstm") ) - goto fail; + goto fail; - /* check header */ - if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */ - goto fail; + /* check header */ + if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */ + goto fail; + + if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF) + goto fail; + + section_count = read_16bitLE(0x10, streamFile); + for (i = 0; i < section_count; i++) { + temp_id = read_16bitLE(0x14 + i * 0xc, streamFile); + switch(temp_id) { + case 0x4000: + info_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + /* size_t info_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4001: + seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + /* size_t seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4002: + data_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + /* size_t data_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4003: + /* off_t regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */ + /* size_t regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4004: + /* off_t pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */ + /* size_t pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + default: + break; + } + } - if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF) - goto fail; - - section_count = read_16bitLE(0x10, streamFile); - for (i = 0; i < section_count; i++) { - temp_id = read_16bitLE(0x14 + i * 0xc, streamFile); - switch(temp_id) { - case 0x4000: - info_offset = read_32bitLE(0x18 + i * 0xc, streamFile); - /* size_t info_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ - break; - case 0x4001: - seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile); - /* size_t seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ - break; - case 0x4002: - data_offset = read_32bitLE(0x18 + i * 0xc, streamFile); - /* size_t data_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ - break; - case 0x4003: - /* off_t regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */ - /* size_t regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ - break; - case 0x4004: - /* off_t pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */ - /* size_t pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ - break; - default: - break; - } - } - if (info_offset == 0) goto fail; if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */ goto fail; - - /* check type details */ - codec_number = read_8bit(info_offset + 0x20, streamFile); - loop_flag = read_8bit(info_offset + 0x21, streamFile); - channel_count = read_8bit(info_offset + 0x22, streamFile); - switch (codec_number) { - case 0: - coding_type = coding_PCM8; - break; - case 1: - coding_type = coding_PCM16LE; - break; - case 2: - if (seek_offset == 0) goto fail; - if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */ - ima = 1; - coding_type = coding_IMA_int; - } - else - coding_type = coding_NGC_DSP; - break; - default: - goto fail; - } + /* check type details */ + codec_number = read_8bit(info_offset + 0x20, streamFile); + loop_flag = read_8bit(info_offset + 0x21, streamFile); + channel_count = read_8bit(info_offset + 0x22, streamFile); - if (channel_count < 1) goto fail; + switch (codec_number) { + case 0: + coding_type = coding_PCM8; + break; + case 1: + coding_type = coding_PCM16LE; + break; + case 2: + if (seek_offset == 0) goto fail; + if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */ + ima = 1; + coding_type = coding_3DS_IMA; + } + else + coding_type = coding_NGC_DSP; + break; + default: + goto fail; + } - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; + if (channel_count < 1) goto fail; - /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile); - vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile); - /* channels and loop flag are set by allocate_vgmstream */ - if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting - { - vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); - if (vgmstream->loop_start_sample > 10000) - { - vgmstream->loop_start_sample -= 5000; - vgmstream->loop_end_sample = vgmstream->num_samples - 5000; - } - else - vgmstream->loop_end_sample = vgmstream->num_samples; - } - else - { - vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - } + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; - vgmstream->coding_type = coding_type; - if (channel_count == 1) - vgmstream->layout_type = layout_none; - else - { - if (ima) - vgmstream->layout_type = layout_interleave; - else - vgmstream->layout_type = layout_interleave_shortblock; - } - vgmstream->meta_type = meta_CSTM; - - if (ima) - vgmstream->interleave_block_size = 0x200; - else { - vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile); - vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile); - } - - if (vgmstream->coding_type == coding_NGC_DSP) { - off_t coef_offset; - off_t tempoffset = info_offset; - int foundcoef = 0; - int i, j; - int coef_spacing = 0x2E; - - while (!(foundcoef)) - { - if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102) - { - coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset; - foundcoef++; - break; - } - tempoffset++; - } + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile); + vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting + { + vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); + if (vgmstream->loop_start_sample > 10000) + { + vgmstream->loop_start_sample -= 5000; + vgmstream->loop_end_sample = vgmstream->num_samples - 5000; + } + else + vgmstream->loop_end_sample = vgmstream->num_samples; + } + else + { + vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->coding_type = coding_type; + if (channel_count == 1) + vgmstream->layout_type = layout_none; + else + { + if (ima) + vgmstream->layout_type = layout_interleave; + else + vgmstream->layout_type = layout_interleave_shortblock; + } + vgmstream->meta_type = meta_CSTM; + + if (ima) + vgmstream->interleave_block_size = 0x200; + else { + vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile); + vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile); + } + + if (vgmstream->coding_type == coding_NGC_DSP) { + off_t coef_offset; + off_t tempoffset = info_offset; + int foundcoef = 0; + int i, j; + int coef_spacing = 0x2E; + + while (!(foundcoef)) + { + if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102) + { + coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset; + foundcoef++; + break; + } + tempoffset++; + } + + for (j = 0; jchannels; j++) { + for (i = 0; i<16; i++) { + vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(info_offset + coef_offset + j*coef_spacing + i * 2, streamFile); + } + } + } + + if (ima) { // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. + if (seek_offset == 0) goto fail; + start_offset = seek_offset; + } else { + if (data_offset == 0) goto fail; + start_offset = data_offset + 0x20; + } - for (j = 0; jchannels; j++) { - for (i = 0; i<16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(info_offset + coef_offset + j*coef_spacing + i * 2, streamFile); - } - } - } - - if (ima) { // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. - if (seek_offset == 0) goto fail; - start_offset = seek_offset; - } else { - if (data_offset == 0) goto fail; - start_offset = data_offset + 0x20; - } - /* open the file for reading by each channel */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bgw.c b/Frameworks/vgmstream/vgmstream/src/meta/bgw.c index 12830685e..f95ac9940 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bgw.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bgw.c @@ -1,12 +1,11 @@ #include "meta.h" +#include "../coding/coding.h" -/* BGW - from Final Fantasy XI (PC) music files - * Some info from POLUtils */ +/* BGW - from Final Fantasy XI (PC) music files */ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - uint32_t codec, filesize, blocksize, sample_rate; + uint32_t codec, file_size, block_size, sample_rate, block_align; int32_t loop_start; - uint8_t block_align; off_t start_offset; int channel_count, loop_flag = 0; @@ -22,11 +21,11 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) { goto fail; codec = read_32bitLE(0x0c,streamFile); - filesize = read_32bitLE(0x10,streamFile); + file_size = read_32bitLE(0x10,streamFile); /*file_id = read_32bitLE(0x14,streamFile);*/ - blocksize = read_32bitLE(0x18,streamFile); + block_size = read_32bitLE(0x18,streamFile); loop_start = read_32bitLE(0x1c,streamFile); - sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0xFFFFFFFF; /* bizarrely obfuscated sample rate */ + sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */ start_offset = read_32bitLE(0x28,streamFile); /*0x2c: unk (vol?) */ /*0x2d: unk (0x10?) */ @@ -35,7 +34,7 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) { /* check file size with header value */ - if (filesize != get_streamfile_size(streamFile)) + if (file_size != get_streamfile_size(streamFile)) goto fail; loop_flag = (loop_start > 0); @@ -54,15 +53,46 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */ - vgmstream->num_samples = blocksize * block_align; + vgmstream->num_samples = block_size * block_align; if (loop_flag) { vgmstream->loop_start_sample = (loop_start-1) * block_align; vgmstream->loop_end_sample = vgmstream->num_samples; } break; - - case 3: /* ATRAC3 (encrypted) */ + +#ifdef VGM_USE_FFMPEG + case 3: { /* ATRAC3 (encrypted) */ + uint8_t buf[0x100]; + int bytes, joint_stereo, skip_samples; + ffmpeg_custom_config cfg; + + vgmstream->num_samples = block_size; /* atrac3_bytes_to_samples gives the same value */ + if (loop_flag) { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + block_align = 0xC0 * vgmstream->channels; /* 0x00 in header */ + joint_stereo = 0; + skip_samples = 0; + + bytes = ffmpeg_make_riff_atrac3(buf, 0x100, vgmstream->num_samples, file_size - start_offset, vgmstream->channels, vgmstream->sample_rate, block_align, joint_stereo, skip_samples); + if (bytes <= 0) goto fail; + + memset(&cfg, 0, sizeof(ffmpeg_custom_config)); + cfg.type = FFMPEG_BGW_ATRAC3; + cfg.channels = vgmstream->channels; + + vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,file_size - start_offset, &cfg); + if (!vgmstream->codec_data) goto fail; + + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } +#endif + default: goto fail; } @@ -82,9 +112,8 @@ fail: /* SPW (SEWave) - from PlayOnline viewer for Final Fantasy XI (PC) */ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - uint32_t codec, filesize, blocksize, sample_rate; + uint32_t codec, file_size, block_size, sample_rate, block_align; int32_t loop_start; - uint8_t block_align; off_t start_offset; int channel_count, loop_flag = 0; @@ -102,12 +131,12 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { if (read_32bitLE(0x8,streamFile) != get_streamfile_size(streamFile)) goto fail; - filesize = read_32bitLE(0x08,streamFile); + file_size = read_32bitLE(0x08,streamFile); codec = read_32bitLE(0x0c,streamFile); /*file_id = read_32bitLE(0x10,streamFile);*/ - blocksize = read_32bitLE(0x14,streamFile); + block_size = read_32bitLE(0x14,streamFile); loop_start = read_32bitLE(0x18,streamFile); - sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0xFFFFFFFF; /* bizarrely obfuscated sample rate */ + sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */ start_offset = read_32bitLE(0x24,streamFile); /*0x2c: unk (0x00?) */ /*0x2d: unk (0x00/01?) */ @@ -116,7 +145,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { /*0x2c: unk (0x01 when PCM, 0x10 when VAG?) */ /* check file size with header value */ - if (filesize != get_streamfile_size(streamFile)) + if (file_size != get_streamfile_size(streamFile)) goto fail; loop_flag = (loop_start > 0); @@ -135,7 +164,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */ - vgmstream->num_samples = blocksize * block_align; + vgmstream->num_samples = block_size * block_align; if (loop_flag) { vgmstream->loop_start_sample = (loop_start-1) * block_align;; vgmstream->loop_end_sample = vgmstream->num_samples; @@ -148,7 +177,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x02; - vgmstream->num_samples = blocksize; + vgmstream->num_samples = block_size; if (loop_flag) { vgmstream->loop_start_sample = (loop_start-1); vgmstream->loop_end_sample = vgmstream->num_samples; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c b/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c index 91c020b00..1dfdb1197 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c @@ -1,243 +1,96 @@ #include "meta.h" -#include "../layout/layout.h" +#include "../coding/coding.h" #include "../util.h" -#include "../vgmstream.h" - -/* Namco Bandai's Bandai Namco Sound Format/File (BNSF) */ -/* similar to RIFX */ +/* BNSF - Namco Bandai's Bandai Namco Sound Format/File */ VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + off_t start_offset = 0, first_offset = 0x0C; + int loop_flag = 0, channel_count = 0; + int sample_rate, num_samples, loop_start = 0, loop_end = 0, block_size; + uint32_t codec, subcodec = 0; + size_t sdat_size; + off_t loop_chunk = 0, sfmt_chunk, sdat_chunk; - off_t file_size = -1; - uint32_t riff_size; - uint32_t bnsf_form; - enum { - form_IS14 = UINT32_C(0x49533134), /* IS14 */ - form_IS22 = UINT32_C(0x49533232), /* IS22 */ - }; - int channel_count = 0; - int sample_count = 0; - int sample_rate = 0; - int coding_type = -1; - off_t start_offset = -1; - - int loop_flag = 0; - off_t loop_start = -1; - off_t loop_end = -1; - uint32_t data_size = 0; - uint32_t block_size = 0; - uint32_t block_samples = 0; - - int FormatChunkFound = 0; - int DataChunkFound = 0; - int RiffSizeExtra = 8; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("bnsf",filename_extension(filename))) - { + if (!check_extensions(streamFile,"bnsf")) goto fail; - } - - /* check header */ - if ((uint32_t)read_32bitBE(0,streamFile)!=0x424E5346) /* BNSF */ + if (read_32bitBE(0,streamFile) != 0x424E5346) /* "BNSF" */ goto fail; - /* check form */ - bnsf_form = read_32bitBE(8,streamFile); - switch (bnsf_form) - { -#ifdef VGM_USE_G7221 - case form_IS14: - break; -#endif -#ifdef VGM_USE_G719 - case form_IS22: - RiffSizeExtra = 0; - break; -#endif - default: - goto fail; + codec = read_32bitBE(0x08,streamFile); + + /* check RIFF size (for siren22 it's full size) */ + if (read_32bitBE(0x04,streamFile) + (codec == 0x49533232 ? 0 : 8) != get_streamfile_size(streamFile)) + goto fail; + + if (!find_chunk_be(streamFile, 0x73666d74,first_offset,0, &sfmt_chunk,NULL)) /* "sfmt" */ + goto fail; + if (!find_chunk_be(streamFile, 0x73646174,first_offset,0, &sdat_chunk,&sdat_size)) /* "sdat" */ + goto fail; + if ( find_chunk_be(streamFile, 0x6C6F6F70,first_offset,0, &loop_chunk,NULL)) { /* "loop" */ + loop_flag = 1; + loop_start = read_32bitBE(loop_chunk+0x00, streamFile); + loop_end = read_32bitBE(loop_chunk+0x04,streamFile); } - riff_size = read_32bitBE(4,streamFile); - file_size = get_streamfile_size(streamFile); + subcodec = read_16bitBE(sfmt_chunk+0x00,streamFile); + channel_count = read_16bitBE(sfmt_chunk+0x02,streamFile); + sample_rate = read_32bitBE(sfmt_chunk+0x04,streamFile); + num_samples = read_32bitBE(sfmt_chunk+0x08,streamFile); + /* 0x0c: some kind of sample count (skip?), can be 0 when no loops */ + block_size = read_16bitBE(sfmt_chunk+0x10,streamFile); + //block_samples = read_16bitBE(sfmt_chunk+0x12,streamFile); + /* max_samples = sdat_size/block_size*block_samples //num_samples is smaller */ - /* check for tructated RIFF */ - if (file_size < riff_size+RiffSizeExtra) goto fail; + start_offset = sdat_chunk; - /* read through chunks to verify format and find metadata */ - { - off_t current_chunk = 0xc; /* start with first chunk */ - - while (current_chunk < file_size && current_chunk < riff_size+8) { - uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); - off_t chunk_size = read_32bitBE(current_chunk+4,streamFile); - - if (current_chunk+8+chunk_size > file_size) goto fail; - - switch(chunk_type) { - case 0x73666d74: /* "sfmt" */ - /* only one per file */ - if (FormatChunkFound) goto fail; - FormatChunkFound = 1; - - sample_rate = read_32bitBE(current_chunk+0x0c,streamFile); - channel_count = read_16bitBE(current_chunk+0x0a,streamFile); - // read_32bitBE(current_chunk+0x10,streamFile); // ? - // read_32bitBE(current_chunk+0x14,streamFile); // ? - block_size = read_16bitBE(current_chunk+0x18,streamFile); - block_samples = read_16bitBE(current_chunk+0x1a,streamFile); - - /* I assume this is still the codec id, but as the codec is - specified by the BNSF "form" I've only seen this zero */ - switch ((uint16_t)read_16bitBE(current_chunk+0x8,streamFile)) { - case 0: - break; - default: - goto fail; - } - break; - case 0x73646174: /* sdat */ - /* at most one per file */ - if (DataChunkFound) goto fail; - DataChunkFound = 1; - - start_offset = current_chunk + 8; - data_size = chunk_size; - break; - case 0x6C6F6F70: /* loop */ - loop_flag = 1; - loop_start = - read_32bitBE(current_chunk+8, streamFile); - loop_end = - read_32bitBE(current_chunk+0xc,streamFile); - break; - default: - /* ignorance is bliss */ - break; - } - - current_chunk += 8+chunk_size; - } - } - - if (!FormatChunkFound || !DataChunkFound) goto fail; - - switch (bnsf_form) { -#ifdef VGM_USE_G7221 - case form_IS14: - coding_type = coding_G7221C; - sample_count = data_size/block_size*block_samples; - - break; -#endif -#ifdef VGM_USE_G719 - case form_IS22: - coding_type = coding_G719; - sample_count = data_size/block_size*block_samples; - - break; -#endif - default: - goto fail; - } /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->num_samples = sample_count; vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; - vgmstream->coding_type = coding_type; + vgmstream->meta_type = meta_BNSF; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = block_size/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - } - vgmstream->meta_type = meta_BNSF; + /* some IS14 voice files have 0x02 (Tales of Zestiria, The Idolm@ster 2); data looks normal and silent + * frames decode ok but rest fails, must be some subtle decoding variation (not encryption) */ + if (subcodec != 0) + goto fail; + switch (codec) { #ifdef VGM_USE_G7221 - if (coding_G7221C == coding_type) - { - int i; - g7221_codec_data *data; + case 0x49533134: /* "IS14" */ + vgmstream->coding_type = coding_G7221C; + vgmstream->codec_data = init_g7221(vgmstream->channels, vgmstream->interleave_block_size); + if (!vgmstream->codec_data) goto fail; - /* one data structure per channel */ - data = malloc(sizeof(g7221_codec_data) * channel_count); - if (!data) - { - goto fail; - } - memset(data,0,sizeof(g7221_codec_data) * channel_count); - vgmstream->codec_data = data; - - for (i = 0; i < channel_count; i++) - { - /* Siren 14 == 14khz bandwidth */ - data[i].handle = g7221_init(vgmstream->interleave_block_size, 14000); - if (!data[i].handle) - { - goto fail; /* close_vgmstream is able to clean up */ - } - } - } + break; #endif - #ifdef VGM_USE_G719 - if (coding_G719 == coding_type) - { - int i; - g719_codec_data *data; - - /* one data structure per channel */ - data = malloc(sizeof(g719_codec_data) * channel_count); - if (!data) - { - goto fail; - } - memset(data,0,sizeof(g719_codec_data) * channel_count); - vgmstream->codec_data = data; - - for (i = 0; i < channel_count; i++) - { - /* Siren 22 == 22khz bandwidth */ - data[i].handle = g719_init(vgmstream->interleave_block_size); - if (!data[i].handle) - { - goto fail; /* close_vgmstream is able to clean up */ - } - } - } + case 0x49533232: /* "IS22" */ + vgmstream->coding_type = coding_G719; + vgmstream->codec_data = init_g719(vgmstream->channels, vgmstream->interleave_block_size); + if (!vgmstream->codec_data) goto fail; + + break; #endif - - /* open the file, set up each channel */ - { - int i; - - vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, - STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[0].streamfile) goto fail; - - for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; - vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = - start_offset+i*vgmstream->interleave_block_size; - } + default: + 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/dc_idvi.c b/Frameworks/vgmstream/vgmstream/src/meta/dc_idvi.c index a3962d5f2..0200f8cd3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/dc_idvi.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/dc_idvi.c @@ -1,40 +1,35 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* IDVI (Eldorado Gate Volume 1-7) */ +/* IDVI - from Capcom's Eldorado Gate Volume 1-7 (DC) */ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int loop_flag, channel_count; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("idvi",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x49445649) /* "IDVI." */ + /* check extension (.dvi: original, .idvi: renamed to header id) */ + if ( !check_extensions(streamFile,"dvi,idvi") ) goto fail; - loop_flag = read_32bitLE(0x0C,streamFile); - channel_count = read_32bitLE(0x04,streamFile); + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x49445649) /* "IDVI" */ + goto fail; + + loop_flag = (read_32bitLE(0x0C,streamFile) != 0); + channel_count = read_32bitLE(0x04,streamFile); /* always 2? */ + start_offset = 0x800; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ vgmstream->channels = channel_count; - start_offset = 0x800; vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count); + vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile); + vgmstream->loop_end_sample = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count); + vgmstream->coding_type = coding_DVI_IMA_int; - vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset); - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile); - vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset); - } vgmstream->meta_type = meta_DC_IDVI; /* Calculating the short block... */ @@ -47,24 +42,10 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) { } /* 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; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - + 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); return NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dc_kcey.c b/Frameworks/vgmstream/vgmstream/src/meta/dc_kcey.c index abf9f663a..2e5c48aea 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/dc_kcey.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/dc_kcey.c @@ -1,65 +1,42 @@ #include "meta.h" -#include "../coding/coding.h" -#include "../util.h" -VGMSTREAM * init_vgmstream_kcey(STREAMFILE *streamFile) { +/* DVI - from Konami KCE Yokohama DC games (Pop'n Music series) */ +VGMSTREAM * init_vgmstream_dc_kcey(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int loop_flag, channel_count; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("kcey",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x4B434559) /* "DVI." */ + /* check extension (.pcm: original, .kcey: renamed to header id) */ + if ( !check_extensions(streamFile,"pcm,kcey") ) goto fail; - loop_flag = (read_32bitBE(0x14,streamFile)!=0xFFFFFFFF); + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4B434559) /* "KCEY" (also "COMP") */ + goto fail; + + start_offset = read_32bitBE(0x10,streamFile); + loop_flag = (read_32bitBE(0x14,streamFile) != 0xFFFFFFFF); channel_count = read_32bitBE(0x08,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; - start_offset = read_32bitBE(0x10,streamFile); vgmstream->sample_rate = 37800; - vgmstream->coding_type = coding_EACS_IMA; - vgmstream->num_samples = read_32bitBE(0x0C,streamFile); - - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile); - } + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile); + vgmstream->coding_type = coding_DVI_IMA; /* stereo/mono, high nibble first */ vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_KCEY; - vgmstream->get_high_nibble=1; + vgmstream->meta_type = meta_DC_KCEY; - /* 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; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+(i*vgmstream->interleave_block_size); - vgmstream->ch[i].adpcm_history1_32=0; - vgmstream->ch[i].adpcm_step_index=0; - } - } + /* open the file for reading */ + 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); return NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/de2.c b/Frameworks/vgmstream/vgmstream/src/meta/de2.c deleted file mode 100644 index 83f004a7b..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/de2.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../util.h" - -/* Gurumin .de2 */ -/* A ways into the file we have a fake RIFF header wrapping MS ADPCM */ - -VGMSTREAM * init_vgmstream_de2(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - off_t riff_off; - int channel_count; - int sample_count; - int sample_rate; - off_t start_offset; - - int loop_flag = 0; - uint32_t data_size; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("de2",filename_extension(filename))) goto fail; - - /* still not sure what this is for, but consistently 0xb */ - if (read_32bitLE(0x04,streamFile)!=0xb) goto fail; - - /* legitimate! really! */ - riff_off = 0x10 + - (read_32bitLE(0x0c,streamFile) ^ read_32bitLE(0x04,streamFile)); - - /* check header */ - if ((uint32_t)read_32bitBE(riff_off+0,streamFile)!=0x52494646) /* "RIFF" */ - goto fail; - /* check for WAVE form */ - if ((uint32_t)read_32bitBE(riff_off+8,streamFile)!=0x57415645) /* "WAVE" */ - goto fail; - /* check for "fmt " */ - if ((uint32_t)read_32bitBE(riff_off+12,streamFile)!=0x666d7420) /* "fmt " */ - goto fail; - /* check for "data" */ - if ((uint32_t)read_32bitBE(riff_off+0x24,streamFile)!=0x64617461) /* "data" */ - goto fail; - /* check for bad fmt chunk size */ - if (read_32bitLE(riff_off+0x10,streamFile)!=0x12) goto fail; - - sample_rate = read_32bitLE(riff_off+0x18,streamFile); - - channel_count = read_16bitLE(riff_off+0x16,streamFile); - if (channel_count != 2) goto fail; - - /* PCM */ - if (read_16bitLE(riff_off+0x14,streamFile) != 1) goto fail; - - /* 16-bit */ - if (read_16bitLE(riff_off+0x20,streamFile) != 4 || - read_16bitLE(riff_off+0x22,streamFile) != 16) goto fail; - - start_offset = riff_off + 0x2c; - data_size = read_32bitLE(riff_off+0x28,streamFile); - - sample_count = data_size/2/channel_count; - - /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->num_samples = sample_count; - vgmstream->sample_rate = sample_rate; - - vgmstream->coding_type = coding_MSADPCM; - vgmstream->layout_type = layout_de2_blocked; - vgmstream->interleave_block_size = 0x800; - - vgmstream->meta_type = meta_DE2; - - /* open the file, set up each channel */ - { - int i; - - vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, - STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[0].streamfile) goto fail; - - for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; - } - } - - /* start me up */ - de2_block_update(start_offset,vgmstream); - - 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/dec.c b/Frameworks/vgmstream/vgmstream/src/meta/dec.c new file mode 100644 index 000000000..0d562b7a4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dec.c @@ -0,0 +1,183 @@ +#include "meta.h" +#include "../layout/layout.h" + +#define TXT_LINE_MAX 0x1000 +static int get_falcom_looping(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end); + +/* .DEC/DE2 - from Falcom PC games (Xanadu Next, Zwei!!, VM Japan, Gurumin) */ +VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + off_t riff_off = 0x00; + size_t pcm_size = 0; + int loop_flag, channel_count, sample_rate, loop_start = 0, loop_end = 0; + + + /* check extension (.dec: main, .de2: Gurumin) */ + if ( !check_extensions(streamFile,"dec,de2") ) + goto fail; + + /* Gurumin has extra data, maybe related to rhythm (~0x50000) */ + if (check_extensions(streamFile,"de2")) { + /* still not sure what this is for, but consistently 0xb */ + if (read_32bitLE(0x04,streamFile) != 0xb) goto fail; + + /* legitimate! really! */ + riff_off = 0x10 + (read_32bitLE(0x0c,streamFile) ^ read_32bitLE(0x04,streamFile)); + } + + + /* fake PCM RIFF header (the original WAV's) wrapping MS-ADPCM */ + if (read_32bitBE(riff_off+0x00,streamFile) != 0x52494646 || /* "RIFF" */ + read_32bitBE(riff_off+0x08,streamFile) != 0x57415645) /* "WAVE" */ + goto fail; + + if (read_32bitBE(riff_off+0x0c,streamFile) == 0x50414420) { /* "PAD " (Zwei!!), blank with wrong chunk size */ + sample_rate = 44100; + channel_count = 2; + pcm_size = read_32bitLE(riff_off+0x04,streamFile) - 0x24; + /* somehow there is garbage at the beginning of some tracks */ + } + else if (read_32bitBE(riff_off+0x0c,streamFile) == 0x666D7420) { /* "fmt " (rest) */ + //if (read_32bitLE(riff_off+0x10,streamFile) != 0x12) goto fail; /* 0x10 in some */ + if (read_16bitLE(riff_off+0x14,streamFile) != 0x01) goto fail; /* PCM (actually MS-ADPCM) */ + if (read_16bitLE(riff_off+0x20,streamFile) != 4 || + read_16bitLE(riff_off+0x22,streamFile) != 16) goto fail; /* 16-bit */ + + channel_count = read_16bitLE(riff_off+0x16,streamFile); + sample_rate = read_32bitLE(riff_off+0x18,streamFile); + if (read_32bitBE(riff_off+0x24,streamFile) == 0x64617461) { /* "data" size except in some Zwei!! */ + pcm_size = read_32bitLE(riff_off+0x28,streamFile); + } else { + pcm_size = read_32bitLE(riff_off+0x04,streamFile) - 0x24; + } + } + else { + goto fail; + } + + if (channel_count != 2) + goto fail; + + start_offset = riff_off + 0x2c; + loop_flag = get_falcom_looping(streamFile, &loop_start, &loop_end); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = pcm_size / 2 / channel_count; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + + vgmstream->coding_type = coding_MSADPCM; + vgmstream->interleave_block_size = 0x800; + vgmstream->layout_type = layout_blocked_dec; + + vgmstream->meta_type = meta_DEC; + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + + block_update_dec(start_offset, vgmstream); + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + + +/* Falcom loves loop points in external text files, here we parse them */ +typedef enum { XANADU_NEXT, ZWEI, DINOSAUR_RESURRECTION, GURUMIN } falcom_loop_t; +static int get_falcom_looping(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end) { + STREAMFILE *streamText; + off_t txt_offset = 0x00; + falcom_loop_t type; + int loop_start = 0, loop_end = 0, loop_flag = 0; + char filename[TXT_LINE_MAX]; + + + /* try one of the many loop files */ + if ((streamText = open_stream_name(streamFile,"bgm.tbl")) != NULL) { + type = XANADU_NEXT; + } + else if ((streamText = open_stream_name(streamFile,"bgm.scr")) != NULL) { + type = ZWEI; + } + else if ((streamText = open_stream_name(streamFile,"loop.txt")) != NULL) { /* actual name in Shift JIS, 0x838B815B8376 */ + type = DINOSAUR_RESURRECTION; + } + else if ((streamText = open_stream_name(streamFile,"map.itm")) != NULL) { + type = GURUMIN; + } + else { + goto end; + } + + get_streamfile_name(streamFile,filename,TXT_LINE_MAX); + + /* read line by line */ + while (txt_offset < get_streamfile_size(streamText)) { + char line[TXT_LINE_MAX]; + char name[TXT_LINE_MAX]; + int ok, line_done, loop, bytes_read; + + bytes_read = get_streamfile_text_line(TXT_LINE_MAX,line, txt_offset,streamText, &line_done); + if (!line_done) goto end; + + txt_offset += bytes_read; + + if (line[0]=='/' || line[0]=='#' || line[0]=='[' || line[0]=='\0') /* comment/empty */ + continue; + + /* each game changes line format, wee */ + switch(type) { + case XANADU_NEXT: /* "XANA000", 0, 0,99999990,0 */ + ok = sscanf(line,"\"%[^\"]\", %*d, %d, %d, %d", name,&loop_start,&loop_end,&loop); + if (ok == 4 && strncasecmp(filename,name,strlen(name)) == 0) { + loop_flag = (loop && loop_end != 0); + goto end; + } + break; + + case ZWEI: /* 1,.\wav\bgm01.wav,497010,7386720;//comment */ + ok = sscanf(line,"%*i,.\\wav\\%[^.].dec,%d,%d;%*s", name,&loop_start,&loop_end); + if (ok == 3 && strncasecmp(filename,name,strlen(name)) == 0) { + loop_flag = (loop_end != 9000000); + goto end; + } + break; + + case DINOSAUR_RESURRECTION: /* 01 970809 - 8015852 */ + strcpy(name,"dinow_"); /* for easier comparison */ + ok = sscanf(line,"%[^ ] %d - %d", (name+6), &loop_start,&loop_end); + if (ok == 3 && strncasecmp(filename,name,strlen(name)) == 0) { + loop_flag = 1; + goto end; + } + break; + + case GURUMIN: /* 0003 BGM03 dec 00211049 02479133 00022050 00000084 //comment */ + ok = sscanf(line,"%*i %[^ \t] %*[^ \t] %d %d %*d %*d %*s", name,&loop_start,&loop_end); + if (ok == 3 && strncasecmp(filename,name,strlen(name)) == 0) { + loop_flag = (loop_end != 99999999 && loop_end != 10000000); + goto end; + } + break; + } + } + +end: + if (loop_flag) { + *out_loop_start = loop_start; + *out_loop_end = loop_end; + } + + if (streamText) close_streamfile(streamText); + return loop_flag; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c new file mode 100644 index 000000000..bce32875f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c @@ -0,0 +1,173 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" + +#define EA_CODEC_PCM 0x00 +//#define EA_CODEC_??? 0x01 //used in SAT videos +#define EA_CODEC_IMA 0x02 +#define EA_CODEC_PSX 0xFF //fake value + +typedef struct { + int32_t sample_rate; + uint8_t bits; + uint8_t channels; + uint8_t codec; + uint8_t type; + int32_t num_samples; + int32_t loop_start; + int32_t loop_end; + int32_t loop_start_offset; + + int big_endian; + int loop_flag; +} ea_header; + +static int parse_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset); +static void set_ea_1snh_psx_samples(STREAMFILE* streamFile, off_t start_offset, ea_header* ea); + +/* EA 1SNh - from early EA games (~1996, ex. Need for Speed) */ +VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + ea_header ea = {0}; + + + /* check extension (.asf/as4: common, cnk: some PS games) */ + if (!check_extensions(streamFile,"asf,as4,cnk")) + goto fail; + + /* check header (first block) */ + if (read_32bitBE(0,streamFile)!=0x31534E68) /* "1SNh" */ + goto fail; + + /* use block size as endian marker (Saturn = BE) */ + ea.big_endian = !(read_32bitLE(0x04,streamFile) < 0x0000FFFF); + + if (!parse_header(streamFile,&ea, 0x08)) + goto fail; + + start_offset = 0x00; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(ea.channels, ea.loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = ea.sample_rate; + vgmstream->num_samples = ea.num_samples; + vgmstream->loop_start_sample = ea.loop_start; + vgmstream->loop_end_sample = ea.loop_end; + + vgmstream->codec_endian = ea.big_endian; + vgmstream->layout_type = layout_blocked_ea_1snh; + vgmstream->meta_type = meta_EA_1SNH; + + switch (ea.codec) { + case EA_CODEC_PCM: + vgmstream->coding_type = ea.bits==1 ? coding_PCM8_int : coding_PCM16_int; + break; + + case EA_CODEC_IMA: + if (ea.bits!=2) goto fail; + vgmstream->coding_type = coding_DVI_IMA; /* stereo/mono, high nibble first */ + break; + + case EA_CODEC_PSX: + vgmstream->coding_type = coding_PSX; + break; + + default: + VGM_LOG("EA: unknown codec 0x%02x\n", ea.codec); + goto fail; + } + + /* open files; channel offsets are updated below */ + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + + block_update_ea_1snh(start_offset,vgmstream); + + return vgmstream; + +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +static int parse_header(STREAMFILE* streamFile, ea_header* ea, off_t offset) { + int32_t (*read_32bit)(off_t,STREAMFILE*) = ea->big_endian ? read_32bitBE : read_32bitLE; + + if (read_32bitBE(offset+0x00, streamFile) == 0x45414353) { /* "EACS" */ + /* PC/SAT EACS subheader */ + ea->sample_rate = read_32bit(offset+0x04, streamFile); + ea->bits = read_8bit(offset+0x08, streamFile); + ea->channels = read_8bit(offset+0x09, streamFile); + ea->codec = read_8bit(offset+0x0a, streamFile); + ea->type = read_8bit(offset+0x0b, streamFile); + ea->num_samples = read_32bit(offset+0x0c, streamFile); + ea->loop_start = read_32bit(offset+0x10, streamFile); + ea->loop_end = read_32bit(offset+0x14, streamFile) + ea->loop_start; /* loop length */ + /* 0x18: data start? (0x00), 0x1c: pan/volume/etc? (0x7F), rest can be padding/garbage */ + VGM_ASSERT(ea->type != 0, "EA EACS: unknown type\n"); /* block type? */ + } + else { + /* PS subheader */ + ea->sample_rate = read_32bit(offset+0x00, streamFile); + ea->channels = read_8bit(offset+0x18, streamFile); + ea->codec = EA_CODEC_PSX; + set_ea_1snh_psx_samples(streamFile, 0x00, ea); + if (ea->loop_start_offset)/* found offset, now find sample start */ + set_ea_1snh_psx_samples(streamFile, 0x00, ea); + } + + ea->loop_flag = (ea->loop_end > 0); + + return 1; +} + +/* get total samples by parsing block headers, needed when EACS isn't present */ +static void set_ea_1snh_psx_samples(STREAMFILE* streamFile, off_t start_offset, ea_header* ea) { + int num_samples = 0, loop_start = 0, loop_end = 0, loop_start_offset = 0; + off_t block_offset = start_offset; + size_t file_size = get_streamfile_size(streamFile); + int32_t (*read_32bit)(off_t,STREAMFILE*) = ea->big_endian ? read_32bitBE : read_32bitLE; + + while (block_offset < file_size) { + uint32_t id = read_32bitBE(block_offset+0x00,streamFile); + size_t block_size = read_32bit(block_offset+0x04,streamFile); /* includes id/size */ + + if (id == 0x31534E68) { /* "1SNh" header block found */ + size_t block_header = read_32bitBE(block_offset+0x08, streamFile) == 0x45414353 ? 0x28 : 0x2c; /* "EACS" */ + if (block_header < block_size) /* sometimes has data */ + num_samples += ps_bytes_to_samples(block_size - block_header, ea->channels); + } + + if (id == 0x31534E64) { /* "1SNd" data block found */ + num_samples += ps_bytes_to_samples(block_size - 0x08, ea->channels); + } + + if (id == 0x31534E6C) { /* "1SNl" loop point found */ + loop_start_offset = read_32bit(block_offset+0x08,streamFile); + loop_end = num_samples; + } + + if (id == 0x00000000 || id == 0xFFFFFFFF) { /* EOF: possible? */ + break; + } + + /* if there is a loop start offset this was called again just to find it */ + if (ea->loop_start_offset && ea->loop_start_offset == block_offset) { + ea->loop_start = num_samples; + return; + } + + /* any other blocks "1SNl" "1SNe" etc */ //todo parse movie blocks + block_offset += block_size; + } + + + ea->num_samples = num_samples; + ea->loop_start = loop_start; + ea->loop_end = loop_end; + ea->loop_start_offset = loop_start_offset; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c new file mode 100644 index 000000000..2f77004ea --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -0,0 +1,254 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + +/* EAAudioCore formats, EA's current audio middleware */ + +static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, STREAMFILE * streamData, off_t header_offset, off_t start_offset, meta_t meta_type); + +/* .SNR+SNS - from EA latest games (~2008-2013), v0 header */ +VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamData = NULL; + + /* check extension, case insensitive */ + if (!check_extensions(streamFile,"snr")) + goto fail; + + /* SNR headers normally need an external SNS file, but some have data */ + 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; + + vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x00, start_offset, meta_EA_SNR_SNS); + if (!vgmstream) goto fail; + } + else { + streamData = open_stream_ext(streamFile,"sns"); + if (!streamData) goto fail; + + vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamData, 0x00, 0x00, meta_EA_SNR_SNS); + if (!vgmstream) goto fail; + } + + if (streamData) close_streamfile(streamData); + return vgmstream; + +fail: + if (streamData) close_streamfile(streamData); + return NULL; +} + +/* .SPS - from EA latest games (~2014), v1 header */ +VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + + /* check extension, case insensitive */ + if (!check_extensions(streamFile,"sps")) + goto fail; + + /* Very hacky but the original check for 0x48000000 rejected some playable files */ + if (((read_16bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x4800) && + ((read_8bit(0x00, streamFile) & 0xFFFFFF00) != 0x00)) + goto fail; + + start_offset = read_8bit(0x03, streamFile); + + vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x04, start_offset, meta_EA_SPS); + if (!vgmstream) goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* .SNU - from EA Redwood Shores/Visceral games (Dead Space, Dante's Inferno, The Godfather 2), v0 header */ +VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, header_offset; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + + /* check extension, case insensitive */ + if (!check_extensions(streamFile,"snu")) + goto fail; + + /* EA SNU header (BE/LE depending on platform) */ + /* 0x00(1): related to sample rate? (03=48000) + * 0x01(1): flags/count? (when set has extra block data before start_offset) + * 0x02(1): always 0? + * 0x03(1): channels? (usually matches but rarely may be 0) + * 0x04(4): some size, maybe >>2 ~= number of frames + * 0x08(4): start offset + * 0x0c(4): some sub-offset? (0x20, found when @0x01 is set) */ + + /* use start_offset as endianness flag */ + if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x0000FFFF) { + read_32bit = read_32bitBE; + } else { + read_32bit = read_32bitLE; + } + + header_offset = 0x10; /* SNR header */ + start_offset = read_32bit(0x08,streamFile); /* SPS blocks */ + + vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, header_offset, start_offset, meta_EA_SNU); + if (!vgmstream) goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + + +/* EA newest header from RwAudioCore (RenderWare?) / EAAudioCore library (still generated by sx.exe). + * Audio "assets" come in separate RAM headers (.SNR/SPH) and raw blocked streams (.SNS/SPS), + * or together in pseudoformats (.SNU, .SBR+.SBS banks, .AEMS, .MUS, etc). + * Some .SNR include stream data, while .SPS have headers so .SPH is optional. */ +static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, STREAMFILE * streamData, off_t header_offset, off_t start_offset, meta_t meta_type) { + VGMSTREAM * vgmstream = NULL; + int channel_count, loop_flag = 0, version, codec, channel_config, sample_rate, flags; + uint32_t num_samples, loop_start = 0, loop_end = 0; + + /* EA SNR/SPH header */ + version = (read_8bit(header_offset + 0x00,streamHead) >> 4) & 0xf; + codec = (read_8bit(header_offset + 0x00,streamHead) >> 0) & 0xf; + channel_config = read_8bit(header_offset + 0x01,streamHead); + 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) */ + + /* V0: SNR+SNS, V1: SPR+SPS (not apparent differences) */ + if (version != 0 && version != 1) { + VGM_LOG("EA SNS/SPS: unknown version\n"); + goto fail; + } + + /* 0x40: stream asset, 0x20: full loop, 0x00: default/RAM asset, 0x01: loop? */ + if (flags != 0x60 && flags != 0x40 && flags != 0x20 && flags != 0x00) { + VGM_LOG("EA SNS/SPS: unknown flag 0x%02x\n", flags); + } + + /* seen in sfx and Dead Space ambient tracks */ + if (flags & 0x20) { + loop_flag = 1; + loop_start = 0; + loop_end = num_samples; + } + + /* accepted channel configs only seem to be mono/stereo/quad/5.1/7.1 */ + //channel_count = ((channel_config >> 2) & 0xf) + 1; /* likely, but better fail with unknown values */ + switch(channel_config) { + case 0x00: channel_count = 1; break; + case 0x04: channel_count = 2; break; + case 0x0c: channel_count = 4; break; + case 0x14: channel_count = 6; break; + case 0x1c: channel_count = 8; break; + default: + VGM_LOG("EA SNS/SPS: unknown channel config 0x%02x\n", channel_config); + goto fail; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + vgmstream->meta_type = meta_type; + + /* EA decoder list and known internal FourCCs */ + switch(codec) { + + 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) */ + uint8_t buf[0x100]; + int bytes, block_size, block_count; + size_t stream_size, virtual_size; + ffmpeg_custom_config cfg = {0}; + + stream_size = get_streamfile_size(streamData) - start_offset; + virtual_size = ffmpeg_get_eaxma_virtual_size(vgmstream->channels, start_offset,stream_size, streamData); + block_size = 0x10000; /* todo unused and not correctly done by the parser */ + block_count = stream_size / block_size + (stream_size % block_size ? 1 : 0); + + bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, virtual_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + if (bytes <= 0) goto fail; + + cfg.type = FFMPEG_EA_XMA; + cfg.virtual_size = virtual_size; + cfg.channels = vgmstream->channels; + + vgmstream->codec_data = init_ffmpeg_config(streamData, buf,bytes, start_offset,stream_size, &cfg); + if (!vgmstream->codec_data) goto fail; + + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } +#endif + + 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) */ + 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); + + /* layout is still blocks, but should work fine with the custom mpeg decoder */ + vgmstream->codec_data = init_mpeg_custom_codec_data(streamData, mpeg_start_offset, &vgmstream->coding_type, vgmstream->channels, type, &cfg); + if (!vgmstream->codec_data) goto fail; + + vgmstream->layout_type = layout_blocked_ea_sns; + break; + } +#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 0x09: /* EASpeex (libspeex variant, base versions vary: 1.0.5, 1.2beta3) */ + case 0x0a: /* EATrax (ATRAC9 variant, has deflated fillers a la EA-XMA) */ + case 0x0b: /* ? */ + case 0x0c: /* EAOpus (inside each SNS/SPS block is 16b frame size + standard? Opus packet) */ + case 0x0d: /* ? */ + case 0x0e: /* ? */ + case 0x0f: /* ? */ + default: + VGM_LOG("EA SNS/SPS: unknown codec 0x%02x\n", codec); + goto fail; + } + + + /* open the file for reading by each channel */ + if (!vgmstream_open_stream(vgmstream,streamData,start_offset)) + goto fail; + + if (vgmstream->layout_type == layout_blocked_ea_sns) + block_update_ea_sns(start_offset, vgmstream); + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_old.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_old.c deleted file mode 100644 index d32878be3..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_old.c +++ /dev/null @@ -1,160 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "../layout/layout.h" -#include "../util.h" - -typedef struct -{ - char szID[4]; - int dwSampleRate; - char bBits; - char bChannels; - char bCompression; - char bType; - int dwNumSamples; - int dwLoopStart; - int dwLoopLength; - int dwDataStart; - int dwUnknown; -} EACSHeader; - -VGMSTREAM * init_vgmstream_eacs(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int channel_count; - int loop_flag=0; - char little_endian=0; - EACSHeader *ea_header = NULL; - int32_t samples_count=0; - int i; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("cnk",filename_extension(filename)) && - strcasecmp("as4",filename_extension(filename)) && - strcasecmp("asf",filename_extension(filename))) goto fail; - - ea_header=(EACSHeader *)malloc(sizeof(EACSHeader)); - - /* check header */ - if ((uint32_t)read_32bitBE(0,streamFile)!=0x31534E68) /* "1SNh" */ - goto fail; - - /* check if we are little or big endian */ - if ((uint32_t)read_32bitBE(4,streamFile)<0x40) - little_endian=1; - - /* check type details */ - - if((uint32_t)read_32bitBE(0x08,streamFile)==0x45414353) { /* EACS */ - read_streamfile((uint8_t*)ea_header,0x08,sizeof(EACSHeader),streamFile); - loop_flag = 0; //(ea_header->dwLoopStart!=0); - channel_count = (ea_header->bChannels); - /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count,0); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - init_get_high_nibble(vgmstream); - - vgmstream->sample_rate = ea_header->dwSampleRate; - - if(ea_header->bCompression==0) { - vgmstream->coding_type = coding_PCM16_int; - if(ea_header->bBits==1) - vgmstream->coding_type = coding_PCM8_int; - } - else - vgmstream->coding_type = coding_EACS_IMA; - - vgmstream->layout_type = layout_eacs_blocked; - vgmstream->meta_type = meta_EACS_PC; - - if(little_endian) - vgmstream->meta_type = meta_EACS_SAT; - - } else { - channel_count=read_32bitLE(0x20,streamFile); - - vgmstream = allocate_vgmstream(channel_count,0); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(0x08,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type=layout_eacs_blocked; - vgmstream->meta_type=meta_EACS_PSX; - } - - vgmstream->ea_platform=little_endian; - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); - if (!vgmstream->ch[i].streamfile) goto fail; - } - } - - // calc the samples length ... - if(little_endian) - vgmstream->next_block_offset=read_32bitBE(0x04,streamFile); - else - vgmstream->next_block_offset=read_32bitLE(0x04,streamFile); - - if(vgmstream->next_block_offset>0x30) { - vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader); - samples_count=(int32_t)vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream); - samples_count/=vgmstream->channels; - } - - do { - if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) { - ea_header->dwLoopStart=read_32bitLE(vgmstream->next_block_offset+0x08,vgmstream->ch[0].streamfile); - vgmstream->next_block_offset+=0x0C; - } - - if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E65) - break; - - eacs_block_update(vgmstream->next_block_offset,vgmstream); - samples_count+=vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream); - } while(vgmstream->next_block_offsetnext_block_offset=read_32bitBE(0x04,streamFile); - else - vgmstream->next_block_offset=read_32bitLE(0x04,streamFile); - - vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader); - - if(vgmstream->coding_type!=coding_PSX) - vgmstream->current_block_size-=8; - - if(vgmstream->coding_type==coding_PSX) - eacs_block_update(0x2C,vgmstream); - else - eacs_block_update(0x28,vgmstream); - - // re-allocate the sample count - vgmstream->num_samples=samples_count; - - if(loop_flag) { - vgmstream->loop_start_sample = ea_header->dwLoopStart; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - if(ea_header) - free(ea_header); - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if(ea_header) - free(ea_header); - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index 2d41606bf..5c409da92 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -140,7 +140,7 @@ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) { goto fail; /* use header size as endianness flag */ - if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x00F00000) { + if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x000F0000) { /* todo not very accurate */ read_32bit = read_32bitBE; read_16bit = read_16bitBE; } else { @@ -250,7 +250,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ } } else { - vgmstream->layout_type = layout_ea_blocked; + vgmstream->layout_type = layout_blocked_ea_schl; } if (is_bnk) @@ -311,14 +311,12 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ #ifdef VGM_USE_MPEG case EA_CODEC2_LAYER2: /* MPEG Layer II, aka MP2 */ case EA_CODEC2_LAYER3: { /* MPEG Layer III, aka MP3 */ - mpeg_custom_config cfg; + mpeg_custom_config cfg = {0}; off_t mpeg_start_offset = is_bnk ? start_offset : get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea); if (!mpeg_start_offset) goto fail; - memset(&cfg, 0, sizeof(mpeg_custom_config)); - /* layout is still blocks, but should work fine with the custom mpeg decoder */ vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, mpeg_start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_EA, &cfg); if (!vgmstream->codec_data) goto fail; @@ -326,14 +324,12 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ } case EA_CODEC2_EALAYER3: { /* MP3 variant */ - mpeg_custom_config cfg; + mpeg_custom_config cfg = {0}; off_t mpeg_start_offset = is_bnk ? start_offset : get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea); if (!mpeg_start_offset) goto fail; - memset(&cfg, 0, sizeof(mpeg_custom_config)); - /* layout is still blocks, but should work fine with the custom mpeg decoder */ vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, mpeg_start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_EAL31, &cfg); if (!vgmstream->codec_data) goto fail; @@ -343,6 +339,12 @@ 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; + case EA_CODEC2_ATRAC3PLUS: /* regular ATRAC3plus chunked in SCxx blocks, including RIFF header */ default: VGM_LOG("EA SCHl: unknown codec2 0x%02x for platform 0x%02x\n", ea->codec2, ea->platform); @@ -401,19 +403,10 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ } break; } - - /* reset channel sub offset for codecs using it */ - if (vgmstream->coding_type == coding_EA_XA - || vgmstream->coding_type == coding_EA_XA_int - || vgmstream->coding_type == coding_EA_XA_V2) { - for(i=0;ichannels;i++) { - vgmstream->ch[i].channel_start_offset = 0; - } - } } else { /* setup first block to update offsets */ - ea_schl_block_update(start_offset,vgmstream); + block_update_ea_schl(start_offset,vgmstream); } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c index 434f237ba..1b56893ec 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c @@ -58,7 +58,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) { vgmstream->meta_type = meta_EA_SCHL_fixed; - vgmstream->layout_type = layout_ea_blocked; + vgmstream->layout_type = layout_blocked_ea_schl; switch (ea.codec) { case EA_CODEC_PCM: @@ -66,7 +66,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) { break; case EA_CODEC_IMA: - vgmstream->coding_type = coding_EACS_IMA; + vgmstream->coding_type = coding_DVI_IMA; /* stereo/mono, high nibble first */ break; default: @@ -80,7 +80,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) { goto fail; /* setup first block to update offsets */ - ea_schl_block_update(start_offset,vgmstream); + block_update_ea_schl(start_offset,vgmstream); return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_snu.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_snu.c deleted file mode 100644 index 31fd41eb4..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_snu.c +++ /dev/null @@ -1,165 +0,0 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../coding/coding.h" - - -/* .SNU - from EA Redwood Shores/Visceral games (Dead Space, Dante's Inferno, The Godfather 2) */ -VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - int channel_count, loop_flag = 0, channel_config, codec, sample_rate, flags; - uint32_t num_samples, loop_start = 0, loop_end = 0; - off_t start_offset; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - - - /* check extension, case insensitive */ - if (!check_extensions(streamFile,"snu")) - goto fail; - - /* check header (the first 0x10 are BE/LE depending on platform) */ - /* 0x00(1): related to sample rate? (03=48000) - * 0x01(1): flags/count? (when set has extra block data before start_offset) - * 0x02(1): always 0? - * 0x03(1): channels? (usually matches but rarely may be 0) - * 0x04(4): some size, maybe >>2 ~= number of frames - * 0x08(4): start offset - * 0x0c(4): some sub-offset? (0x20, found when @0x01 is set) */ - - /* use start_offset as endianness flag */ - if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x0000FFFF) { - read_32bit = read_32bitBE; - } else { - read_32bit = read_32bitLE; - } - - start_offset = read_32bit(0x08,streamFile); - - codec = read_8bit(0x10,streamFile); - channel_config = read_8bit(0x11,streamFile); - sample_rate = (uint16_t)read_16bitBE(0x12,streamFile); - flags = (uint8_t)read_8bit(0x14,streamFile); /* upper nibble only? */ - num_samples = (uint32_t)read_32bitBE(0x14,streamFile) & 0x00FFFFFF; - /* 0x18: null?, 0x1c: null? */ - - if (flags != 0x60 && flags != 0x40) { - VGM_LOG("EA SNS: unknown flag\n"); - goto fail; - } - -#if 0 - //todo not working ok with blocks in XAS - //todo check if EA-XMA loops (Dante's Inferno doesn't) - if (flags & 0x60) { /* full loop, seen in ambient tracks */ - loop_flag = 1; - loop_start = 0; - loop_end = num_samples; - } -#endif - - //channel_count = (channel_config >> 2) + 1; //todo test - /* 01/02/03 = 1 ch?, 05/06/07 = 2/3 ch?, 0d/0e/0f = 4/5 ch?, 15/16/17 = 6/7 ch?, 1d/1e/1f = 8 ch? */ - switch(channel_config) { - case 0x00: channel_count = 1; break; - case 0x04: channel_count = 2; break; - case 0x0c: channel_count = 4; break; - case 0x14: channel_count = 6; break; - case 0x1c: channel_count = 8; break; - default: - VGM_LOG("EA SNU: unknown channel config 0x%02x\n", channel_config); - goto fail; - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - - vgmstream->meta_type = meta_EA_SNU; - - switch(codec) { - case 0x04: /* "Xas1": EA-XAS (Dead Space PC/PS3) */ - vgmstream->coding_type = coding_EA_XAS; - vgmstream->layout_type = layout_ea_sns_blocked; - break; - -#if 0 -#ifdef VGM_USE_MPEG - case 0x07: { /* "EL32S": EALayer3 v2 "S" (Dante's Inferno PS3) */ - mpeg_custom_config cfg; - off_t mpeg_start_offset = start_offset + 0x08; - - memset(&cfg, 0, sizeof(mpeg_custom_config)); - - /* layout is still blocks, but should work fine with the custom mpeg decoder */ - vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, mpeg_start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_EAL32S, &cfg); - if (!vgmstream->codec_data) goto fail; - - vgmstream->layout_type = layout_ea_sns_blocked; - break; - } -#endif -#endif - -#ifdef VGM_USE_FFMPEG - 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; - ffmpeg_custom_config cfg; - - stream_size = get_streamfile_size(streamFile) - start_offset; - virtual_size = ffmpeg_get_eaxma_virtual_size(vgmstream->channels, start_offset,stream_size, streamFile); - block_size = 0x10000; /* todo unused and not correctly done by the parser */ - block_count = stream_size / block_size + (stream_size % block_size ? 1 : 0); - - bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, virtual_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); - if (bytes <= 0) goto fail; - - memset(&cfg, 0, sizeof(ffmpeg_custom_config)); - cfg.type = FFMPEG_EA_XMA; - cfg.virtual_size = virtual_size; - cfg.channels = vgmstream->channels; - - vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,stream_size, &cfg); - if (!vgmstream->codec_data) goto fail; - - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - break; - } -#endif - case 0x00: /* "NONE" */ - case 0x01: /* not used? */ - case 0x02: /* "P6B0": PCM16BE */ - - case 0x05: /* "EL31": EALayer3 v1 b (with PCM blocks in normal EA-frames?) */ - case 0x06: /* "EL32P": EALayer3 v2 "P" */ - case 0x09: /* EASpeex? */ - case 0x0c: /* EAOpus? */ - case 0x0e: /* XAS variant? */ - case 0x0f: /* EALayer3 variant? */ - /* also 0x1n variations, used in other headers */ - default: - VGM_LOG("EA SNU: unknown codec 0x%02x\n", codec); - goto fail; - } - - - /* open the file for reading by each channel */ - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - if (vgmstream->layout_type == layout_ea_sns_blocked) - ea_sns_block_update(start_offset, vgmstream); - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ezw.c b/Frameworks/vgmstream/vgmstream/src/meta/ezw.c new file mode 100644 index 000000000..cd7d7924c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ezw.c @@ -0,0 +1,41 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* EZWAVE - EZ2DJ (Arcade) */ +VGMSTREAM * init_vgmstream_ezw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, data_size; + int loop_flag, channel_count; + + /* check extension, case insensitive */ + if ( !check_extensions(streamFile,"ezw")) + goto fail; + + + loop_flag = 0; + channel_count = read_8bit(0x0, streamFile); + data_size = read_32bitLE(0xE,streamFile); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + + start_offset = 0x12; + vgmstream->sample_rate = read_32bitLE(0x2,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = data_size/(channel_count*2); + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_EZW; + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/flx.c b/Frameworks/vgmstream/vgmstream/src/meta/flx.c new file mode 100644 index 000000000..ab28a3221 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/flx.c @@ -0,0 +1,107 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* FLX - from Ultima IX (.FLX is actually an archive format with sometimes sound data, let's support both anyway) */ +VGMSTREAM * init_vgmstream_flx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, stream_offset = 0; + size_t data_size; + int loop_flag, channel_count, codec; + int total_streams = 0, target_stream = streamFile->stream_index; + + + /* check extensions (.flx: name of archive, files inside don't have extensions) */ + if (!check_extensions(streamFile,"flx")) + goto fail; + + /* all spaces up to 0x50 = archive FLX */ + if (read_32bitBE(0x00,streamFile) == 0x20202020 && read_32bitBE(0x40,streamFile) == 0x20202020) { + int i; + int entries = read_32bitLE(0x50,streamFile); + off_t offset = 0x80; + + if (read_32bitLE(0x54,streamFile) != 0x02 + || read_32bitLE(0x58,streamFile) != get_streamfile_size(streamFile)) + goto fail; + + if (target_stream == 0) target_stream = 1; + + for (i = 0; i < entries; i++) { + off_t entry_offset = read_32bitLE(offset + 0x00, streamFile); + /* 0x04: stream size */ + offset += 0x08; + + if (entry_offset != 0x00) + total_streams++; /* many entries are empty */ + if (total_streams == target_stream && stream_offset == 0) + stream_offset = entry_offset; /* found but let's keep adding total_streams */ + } + if (target_stream < 0 || target_stream > total_streams || total_streams < 1) goto fail; + if (stream_offset == 0x00) goto fail; + } + else { + stream_offset = 0x00; + } + + if (read_32bitLE(stream_offset + 0x30,streamFile) != 0x10) + goto fail; + data_size = read_32bitLE(stream_offset + 0x28,streamFile); + channel_count = read_32bitLE(stream_offset + 0x34,streamFile); + codec = read_32bitLE(stream_offset + 0x38,streamFile); + loop_flag = (channel_count > 1); /* full seamless repeats in music */ + start_offset = stream_offset + 0x3c; + /* 0x00: id */ + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(stream_offset + 0x2c,streamFile); + vgmstream->num_streams = total_streams; + vgmstream->meta_type = meta_PC_FLX; + + switch(codec) { + case 0x00: /* PCM (sfx) */ + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + + vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 16); + break; + + case 0x01: /* EA-XA (music, sfx) */ + vgmstream->coding_type = channel_count > 1 ? coding_EA_XA : coding_EA_XA_int; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = read_32bitLE(stream_offset + 0x28,streamFile) / 0x0f*channel_count * 28; /* ea_xa_bytes_to_samples */ + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + break; + + case 0x02: /* EA-MT (voices) */ + vgmstream->coding_type = coding_EA_MT; + vgmstream->codec_data = init_ea_mt(vgmstream->channels, 0); + if (!vgmstream->codec_data) goto fail; + + vgmstream->num_samples = read_32bitLE(start_offset,streamFile); + start_offset += 0x04; + break; + + default: + VGM_LOG("FLX: unknown codec 0x%x\n", codec); + goto fail; + } + + read_string(vgmstream->stream_name,0x20+1, stream_offset + 0x04,streamFile); + + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + + 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 cd84c40cf..cdce31cba 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c @@ -254,7 +254,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) { /* sometimes there is garbage at the end or missing bytes due to improper demuxing */ VGM_ASSERT(fsbh.hdrsize + fsbh.shdrsize + fsbh.datasize != streamFile->get_size(streamFile) - offset, - "FSB wrong head/datasize found\n"); + "FSB wrong head/datasize found (expected 0x%x vs 0x%lx)\n", + fsbh.hdrsize + fsbh.shdrsize + fsbh.datasize, streamFile->get_size(streamFile) - offset); /* Loops unless disabled. FMOD default seems full loops (0/num_samples-1) without flags, for repeating tracks * that should loop and jingles/sfx that shouldn't. We'll try to disable looping is it looks jingly enough. */ @@ -352,8 +353,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) { } else if (fsbh.mode & FSOUND_GCADPCM) { /* FSB3: ?; FSB4: de Blob (Wii), Night at the Museum, M. Night Shyamalan Avatar: The Last Airbender */ - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave_byte; + vgmstream->coding_type = coding_NGC_DSP_subint; + vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = 0x2; dsp_read_coefs_be(vgmstream, streamFile, custom_data_offset, 0x2e); } @@ -379,6 +380,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) { /* full channel interleave, used in short streams (ex. de Blob Wii SFXs) */ if (fsbh.numchannels > 1 && (fsbh.flags & FMOD_FSB_SOURCE_NOTINTERLEAVED)) { + if (vgmstream->coding_type == coding_NGC_DSP_subint) + vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = fsbh.lengthcompressedbytes / fsbh.numchannels; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c index f6395b690..eb8f0d376 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c @@ -193,27 +193,22 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { goto fail; case 0x01: /* FMOD_SOUND_FORMAT_PCM8 [Anima - Gate of Memories (PC)] */ + vgmstream->coding_type = coding_PCM8_U; vgmstream->layout_type = ChannelCount == 1 ? layout_none : layout_interleave; vgmstream->interleave_block_size = 0x01; - vgmstream->coding_type = coding_PCM8_U; break; case 0x02: /* FMOD_SOUND_FORMAT_PCM16 */ - if (ChannelCount == 1) { - vgmstream->layout_type = layout_none; - } else { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x02; - } - vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = ChannelCount == 1 ? layout_none : layout_interleave; + vgmstream->interleave_block_size = 0x02; break; case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */ - goto fail; + goto fail; /* not used */ case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */ - goto fail; + goto fail; /* not used */ case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima - Gate of Memories (PC)] */ vgmstream->coding_type = coding_PCMFLOAT; @@ -222,31 +217,25 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { break; case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM [Sonic Boom - Fire and Ice (3DS)] */ - if (ChannelCount == 1) { - vgmstream->layout_type = layout_none; - } else { - vgmstream->layout_type = layout_interleave_byte; - vgmstream->interleave_block_size = 0x02; - } + vgmstream->coding_type = coding_NGC_DSP_subint; + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x02; dsp_read_coefs_be(vgmstream,streamFile,DSPInfoStart,0x2E); - vgmstream->coding_type = coding_NGC_DSP; break; case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */ + vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX; vgmstream->layout_type = layout_none; - vgmstream->coding_type = coding_XBOX; - if (vgmstream->channels > 2) /* multichannel FSB IMA (interleaved header) */ - vgmstream->coding_type = coding_FSB_IMA; break; case 0x08: /* FMOD_SOUND_FORMAT_VAG */ - goto fail; + goto fail; /* not used */ case 0x09: /* FMOD_SOUND_FORMAT_HEVAG */ + vgmstream->coding_type = coding_HEVAG; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; - vgmstream->coding_type = coding_HEVAG; break; #ifdef VGM_USE_FFMPEG @@ -270,9 +259,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { #ifdef VGM_USE_MPEG case 0x0B: {/* FMOD_SOUND_FORMAT_MPEG */ - mpeg_custom_config cfg; + mpeg_custom_config cfg = {0}; - memset(&cfg, 0, sizeof(mpeg_custom_config)); cfg.fsb_padding = (vgmstream->channels > 2 ? 16 : 4); /* observed default */ vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, StartOffset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg); @@ -295,9 +283,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { #ifdef VGM_USE_VORBIS case 0x0F: {/* FMOD_SOUND_FORMAT_VORBIS */ - vorbis_custom_config cfg; + vorbis_custom_config cfg = {0}; - memset(&cfg, 0, sizeof(vorbis_custom_config)); cfg.channels = vgmstream->channels; cfg.sample_rate = vgmstream->sample_rate; cfg.setup_id = VorbisSetupId; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/g1l.c b/Frameworks/vgmstream/vgmstream/src/meta/g1l.c index ca447d119..81b767d35 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/g1l.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/g1l.c @@ -88,11 +88,10 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t vgmstream->loop_start_sample = read_32bitBE(offset+0x14, streamFile); vgmstream->loop_end_sample = vgmstream->num_samples; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave_byte; - vgmstream->meta_type = meta_KT_WIIBGM; - + vgmstream->coding_type = coding_NGC_DSP_subint; + vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = 0x1; + vgmstream->meta_type = meta_KT_WIIBGM; dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60); start_offset = offset+0x800; @@ -101,7 +100,7 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t goto fail; return vgmstream; - fail: - close_vgmstream(vgmstream); - return NULL; +fail: + close_vgmstream(vgmstream); + return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/genh.c b/Frameworks/vgmstream/vgmstream/src/meta/genh.c index 0849aa8a6..f42d442e7 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/genh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/genh.c @@ -3,6 +3,8 @@ #include "../layout/layout.h" #include "../util.h" + + /* known GENH types */ typedef enum { PSX = 0, /* PSX ADPCM */ @@ -28,26 +30,45 @@ typedef enum { XMA1 = 20, /* raw XMA1 */ XMA2 = 21, /* raw XMA2 */ FFMPEG = 22, /* any headered FFmpeg format */ + AC3 = 23, /* AC3/SPDIF */ } genh_type; +typedef struct { + genh_type codec; + int codec_mode; + size_t interleave; + + int channels; + int32_t sample_rate; + + size_t data_size; + off_t start_offset; + + int32_t num_samples; + int32_t loop_start_sample; + int32_t loop_end_sample; + int skip_samples_mode; + int32_t skip_samples; + + int loop_flag; + + int32_t coef[2]; + int32_t coef_splitted[2]; + int32_t coef_type; + int32_t coef_interleave_type; + int coef_big_endian; + +} genh_header; + +static int parse_genh(STREAMFILE * streamFile, genh_header * genh); + /* GENH is an artificial "generic" header for headerless streams */ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - - int channel_count, loop_flag, sample_rate, interleave; - int32_t num_samples = 0, loop_start, loop_end, skip_samples = 0; - int32_t start_offset, header_size; - off_t datasize = 0; - - int32_t coef[2]; - int32_t coef_splitted[2]; - int32_t dsp_interleave_type; - int32_t coef_type; - int skip_samples_mode, atrac3_mode, xma_mode; + genh_header genh = {0}; + coding_t coding; int i, j; - coding_t coding; - genh_type type; /* check extension, case insensitive */ if (!check_extensions(streamFile,"genh")) goto fail; @@ -55,12 +76,13 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { /* check header magic */ if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail; - channel_count = read_32bitLE(0x4,streamFile); - if (channel_count < 1) goto fail; + /* process the header */ + if (!parse_genh(streamFile, &genh)) + goto fail; + - type = read_32bitLE(0x18,streamFile); /* type to coding conversion */ - switch (type) { + switch (genh.codec) { case PSX: coding = coding_PSX; break; case XBOX: coding = coding_XBOX; break; case NGC_DTK: coding = coding_NGC_DTK; break; @@ -86,68 +108,27 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { case ATRAC3PLUS: case XMA1: case XMA2: + case AC3: case FFMPEG: coding = coding_FFmpeg; break; #endif default: goto fail; } - start_offset = read_32bitLE(0x1C,streamFile); - header_size = read_32bitLE(0x20,streamFile); - - /* HACK to support old genh */ - if (header_size == 0) { - start_offset = 0x800; - header_size = 0x800; - } - - /* check for audio data start past header end */ - if (header_size > start_offset) goto fail; - - interleave = read_32bitLE(0x8,streamFile); - sample_rate = read_32bitLE(0xc,streamFile); - loop_start = read_32bitLE(0x10,streamFile); - loop_end = read_32bitLE(0x14,streamFile); - - coef[0] = read_32bitLE(0x24,streamFile); - coef[1] = read_32bitLE(0x28,streamFile); - dsp_interleave_type = read_32bitLE(0x2C,streamFile); - - /* DSP coefficient variants */ - /* bit 0 - split coefs (2 arrays) */ - /* bit 1 - little endian coefs */ - coef_type = read_32bitLE(0x30,streamFile); - /* when using split coefficients, 2nd array is at: */ - coef_splitted[0] = read_32bitLE(0x34,streamFile); - coef_splitted[1] = read_32bitLE(0x38,streamFile); - - /* other fields */ - num_samples = read_32bitLE(0x40,streamFile); - skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */ - skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */ - atrac3_mode = read_8bit(0x49,streamFile); /* 0=autodetect, 1=force joint stereo, 2=force full stereo */ - xma_mode = read_8bit(0x4a,streamFile); /* 0=default (4ch = 2ch + 2ch), 1=single (4ch = 1ch + 1ch + 1ch + 1ch) */ - datasize = read_32bitLE(0x50,streamFile); - if (!datasize) - datasize = get_streamfile_size(streamFile)-start_offset; - - num_samples = num_samples > 0 ? num_samples : loop_end; - loop_flag = loop_start != -1; - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(genh.channels,genh.loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; + vgmstream->sample_rate = genh.sample_rate; + vgmstream->num_samples = genh.num_samples; + vgmstream->loop_start_sample = genh.loop_start_sample; + vgmstream->loop_end_sample = genh.loop_end_sample; /* codec specific */ switch (coding) { case coding_PCM8_U_int: - vgmstream->layout_type=layout_none; + vgmstream->layout_type = layout_none; break; case coding_PCM16LE: case coding_PCM16BE: @@ -160,14 +141,14 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { case coding_IMA: case coding_AICA: case coding_APPLE_IMA4: - vgmstream->interleave_block_size = interleave; - if (channel_count > 1) + vgmstream->interleave_block_size = genh.interleave; + if (vgmstream->channels > 1) { if (coding == coding_SDX2) { coding = coding_SDX2_int; } - if (vgmstream->interleave_block_size==0xffffffff) { + if (vgmstream->interleave_block_size==0xffffffff) {// || vgmstream->interleave_block_size == 0) { vgmstream->layout_type = layout_none; } else { @@ -179,7 +160,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { } /* to avoid endless loops */ - if (!interleave && ( + if (!genh.interleave && ( coding == coding_PSX || coding == coding_PSX_badflags || coding == coding_IMA_int || @@ -194,64 +175,62 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { /* setup adpcm */ if (coding == coding_AICA) { int i; - for (i=0;ichannels;i++) { vgmstream->ch[i].adpcm_step_index = 0x7f; } } break; case coding_MS_IMA: - if (!interleave) goto fail; /* creates garbage */ + if (!genh.interleave) goto fail; /* creates garbage */ - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = genh.interleave; vgmstream->layout_type = layout_none; break; case coding_MSADPCM: - if (channel_count > 2) goto fail; - if (!interleave) goto fail; /* creates garbage */ + if (vgmstream->channels > 2) goto fail; + if (!genh.interleave) goto fail; /* creates garbage */ - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = genh.interleave; vgmstream->layout_type = layout_none; break; case coding_XBOX: vgmstream->layout_type = layout_none; break; case coding_NGC_DTK: - if (channel_count != 2) goto fail; + if (vgmstream->channels != 2) goto fail; vgmstream->layout_type = layout_none; break; case coding_NGC_DSP: - if (dsp_interleave_type == 0) { - if (!interleave) goto fail; + if (genh.coef_interleave_type == 0) { + if (!genh.interleave) goto fail; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - } else if (dsp_interleave_type == 1) { - if (!interleave) goto fail; - vgmstream->layout_type = layout_interleave_byte; - vgmstream->interleave_block_size = interleave; - } else if (dsp_interleave_type == 2) { + vgmstream->interleave_block_size = genh.interleave; + } else if (genh.coef_interleave_type == 1) { + if (!genh.interleave) goto fail; + coding = coding_NGC_DSP_subint; + vgmstream->interleave_block_size = genh.interleave; vgmstream->layout_type = layout_none; - } + } else if (genh.coef_interleave_type == 2) { + vgmstream->layout_type = layout_none; + }// else { + // goto fail; + //} /* get coefs */ - for (i=0;ichannels;i++) { + int16_t (*read_16bit)(off_t , STREAMFILE*) = genh.coef_big_endian ? read_16bitBE : read_16bitLE; - /* bit 0 - split coefs (2 arrays) */ - if ((coef_type & 1) == 0) { + /* normal/split coefs bit flag */ + if ((genh.coef_type & 1) == 0) { /* not set: normal coefs, all 16 interleaved into one array */ for (j=0;j<16;j++) { - vgmstream->ch[i].adpcm_coef[j] = read_16bit(coef[i]+j*2,streamFile); + vgmstream->ch[i].adpcm_coef[j] = read_16bit(genh.coef[i]+j*2,streamFile); } - } else { + } + else { /* set: split coefs, 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right */ for (j=0;j<8;j++) { - vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(coef[i]+j*2,streamFile); - vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(coef_splitted[i]+j*2,streamFile); + vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(genh.coef[i]+j*2,streamFile); + vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(genh.coef_splitted[i]+j*2,streamFile); } } } @@ -260,7 +239,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { #ifdef VGM_USE_MPEG case coding_MPEG_layer3: vgmstream->layout_type = layout_none; - vgmstream->codec_data = init_mpeg_codec_data(streamFile, start_offset, &coding, vgmstream->channels); + vgmstream->codec_data = init_mpeg_codec_data(streamFile, genh.start_offset, &coding, vgmstream->channels); if (!vgmstream->codec_data) goto fail; break; @@ -269,50 +248,53 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { case coding_FFmpeg: { ffmpeg_codec_data *ffmpeg_data = NULL; - if (type == FFMPEG) { + if (genh.codec == FFMPEG || genh.codec == AC3) { /* default FFmpeg */ - ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,datasize); + ffmpeg_data = init_ffmpeg_offset(streamFile, genh.start_offset,genh.data_size); if ( !ffmpeg_data ) goto fail; + + //if (vgmstream->num_samples == 0) + // vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */ } else { /* fake header FFmpeg */ uint8_t buf[200]; int32_t bytes; - if (type == ATRAC3) { - int block_size = interleave; + if (genh.codec == ATRAC3) { + int block_size = genh.interleave; int joint_stereo; - switch(atrac3_mode) { - case 0: joint_stereo = vgmstream->channels > 1 && interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */ + switch(genh.codec_mode) { + case 0: joint_stereo = vgmstream->channels > 1 && genh.interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */ case 1: joint_stereo = 1; break; /* force joint stereo */ case 2: joint_stereo = 0; break; /* force stereo */ default: goto fail; } - bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples); + bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, genh.skip_samples); } - else if (type == ATRAC3PLUS) { - int block_size = interleave; + else if (genh.codec == ATRAC3PLUS) { + int block_size = genh.interleave; - bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, skip_samples); + bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples); } - else if (type == XMA1) { - int xma_stream_mode = xma_mode == 1 ? 1 : 0; + else if (genh.codec == XMA1) { + int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0; - bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode); + bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode); } - else if (type == XMA2) { - int block_size = interleave ? interleave : 2048; - int block_count = datasize / block_size; + else if (genh.codec == XMA2) { + int block_size = genh.interleave ? genh.interleave : 2048; + int block_count = genh.data_size / block_size; - bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); } else { goto fail; } if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size); if ( !ffmpeg_data ) goto fail; } @@ -320,8 +302,8 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { vgmstream->layout_type = layout_none; /* force encoder delay */ - if (skip_samples_mode && skip_samples >= 0) { - ffmpeg_set_skip_samples(ffmpeg_data, skip_samples); + if (genh.skip_samples_mode && genh.skip_samples >= 0) { + ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples); } break; @@ -335,7 +317,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { vgmstream->meta_type = meta_GENH; - if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) + if ( !vgmstream_open_stream(vgmstream,streamFile,genh.start_offset) ) goto fail; return vgmstream; @@ -344,3 +326,60 @@ fail: close_vgmstream(vgmstream); return NULL; } + + +static int parse_genh(STREAMFILE * streamFile, genh_header * genh) { + size_t header_size; + + genh->channels = read_32bitLE(0x4,streamFile); + + genh->interleave = read_32bitLE(0x8,streamFile); + genh->sample_rate = read_32bitLE(0xc,streamFile); + genh->loop_start_sample = read_32bitLE(0x10,streamFile); + genh->loop_end_sample = read_32bitLE(0x14,streamFile); + + genh->codec = read_32bitLE(0x18,streamFile); + genh->start_offset = read_32bitLE(0x1C,streamFile); + header_size = read_32bitLE(0x20,streamFile); + /* HACK to support old genh */ + if (header_size == 0) { + genh->start_offset = 0x800; + header_size = 0x800; + } + /* check for audio data start past header end */ + if (header_size > genh->start_offset) goto fail; + + genh->coef[0] = read_32bitLE(0x24,streamFile); + genh->coef[1] = read_32bitLE(0x28,streamFile); + genh->coef_interleave_type = read_32bitLE(0x2C,streamFile); + + /* DSP coefficient variants */ + /* bit 0 flag - split coefs (2 arrays) */ + /* bit 1 flag - little endian coefs (for some 3DS) */ + genh->coef_type = read_32bitLE(0x30,streamFile); + genh->coef_big_endian = ((genh->coef_type & 2) == 0); + + /* when using split coefficients, 2nd array is at: */ + genh->coef_splitted[0] = read_32bitLE(0x34,streamFile); + genh->coef_splitted[1] = read_32bitLE(0x38,streamFile); + + /* other fields */ + genh->num_samples = read_32bitLE(0x40,streamFile); + genh->skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */ + genh->skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */ + if (genh->codec == ATRAC3 || genh->codec == ATRAC3PLUS) + genh->codec_mode = read_8bit(0x49,streamFile); /* 0=autodetect, 1=force joint stereo, 2=force full stereo */ + if (genh->codec == XMA1 || genh->codec == XMA2) + genh->codec_mode = read_8bit(0x4a,streamFile); /* 0=default (4ch = 2ch + 2ch), 1=single (4ch = 1ch + 1ch + 1ch + 1ch) */ + genh->data_size = read_32bitLE(0x50,streamFile); + if (genh->data_size == 0) + genh->data_size = get_streamfile_size(streamFile) - genh->start_offset; + + genh->num_samples = genh->num_samples > 0 ? genh->num_samples : genh->loop_end_sample; + genh->loop_flag = genh->loop_start_sample != -1; + + return 1; + +fail: + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gh3_bar.c b/Frameworks/vgmstream/vgmstream/src/meta/gh3_bar.c deleted file mode 100644 index b54ce2c71..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/gh3_bar.c +++ /dev/null @@ -1,182 +0,0 @@ -#include "meta.h" - -// Guitar Hero III Mobile .bar - -enum {BAR_KEY_LENGTH = 16}; - -// don't know if this is unique, but seems accurate -static const uint8_t bar_key[BAR_KEY_LENGTH] = - {0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6, - 0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80}; - -typedef struct _BARSTREAM -{ - STREAMFILE sf; - STREAMFILE *real_file; -} BARSTREAM; - -STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file); - -VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - // don't close, this is just the source streamFile wrapped - STREAMFILE* streamFileBAR = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - off_t ch2_start_offset; - int loop_flag; - int channel_count; - long file_size; - - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("bar",filename_extension(filename))) goto fail; - - /* decryption wrapper for header reading */ - streamFileBAR = wrap_bar_STREAMFILE(streamFile); - if (!streamFileBAR) goto fail; - - file_size = get_streamfile_size(streamFileBAR); - - /* check header */ - if (read_32bitBE(0x00,streamFileBAR) != 0x11000100 || - read_32bitBE(0x04,streamFileBAR) != 0x01000200) goto fail; - if (read_32bitLE(0x50,streamFileBAR) != file_size) goto fail; - - start_offset = read_32bitLE(0x18,streamFileBAR); - if (0x54 != start_offset) goto fail; - ch2_start_offset = read_32bitLE(0x48,streamFileBAR); - if (ch2_start_offset >= file_size) goto fail; - - /* build the VGMSTREAM */ - channel_count = 2; - loop_flag = 0; - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = 11025; - vgmstream->coding_type = coding_IMA; - vgmstream->num_samples = (file_size-ch2_start_offset)*2; - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_GH3_BAR; - - { - STREAMFILE *file1, *file2; - file1 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file1) goto fail; - file2 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file2) - { - close_streamfile(file1); - goto fail; - } - vgmstream->ch[0].streamfile = file1; - vgmstream->ch[1].streamfile = file2; - vgmstream->ch[0].channel_start_offset= - vgmstream->ch[0].offset=start_offset; - vgmstream->ch[1].channel_start_offset= - vgmstream->ch[1].offset=ch2_start_offset; - } - - // discard our decrypt wrapper, without closing the original streamfile - free(streamFileBAR); - - return vgmstream; -fail: - if (streamFileBAR) - free(streamFileBAR); - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - -static size_t read_bar(BARSTREAM *streamFile, uint8_t *dest, off_t offset, size_t length) -{ - off_t i; - size_t read_length = - streamFile->real_file->read(streamFile->real_file, dest, offset, length); - - for (i = 0; i < read_length; i++) - { - dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH]; - } - - return read_length; -} - -static size_t get_size_bar(BARSTREAM *streamFile) -{ - return streamFile->real_file->get_size(streamFile->real_file); -} - -static size_t get_offset_bar(BARSTREAM *streamFile) -{ - return streamFile->real_file->get_offset(streamFile->real_file); -} - -static void get_name_bar(BARSTREAM *streamFile, char *name, size_t length) -{ - return streamFile->real_file->get_name(streamFile->real_file, name, length); -} - -static void get_realname_bar(BARSTREAM *streamFile, char *name, size_t length) -{ - return streamFile->real_file->get_realname(streamFile->real_file, name, length); -} - -STREAMFILE *open_bar(BARSTREAM *streamFile, const char * const filename, size_t buffersize) -{ - STREAMFILE *newfile = streamFile->real_file->open( - streamFile->real_file,filename,buffersize); - if (!newfile) - return NULL; - - return wrap_bar_STREAMFILE(newfile); -} - -static void close_bar(BARSTREAM *streamFile) -{ - streamFile->real_file->close(streamFile->real_file); - free(streamFile); - return; -} - -#ifdef PROFILE_STREAMFILE -size_t get_bytes_read_bar(BARSTREAM *streamFile) -{ - return streamFile->real_file->get_bytes_read(streamFile->real_file); -} - -int (*get_error_count)(BARSTREAM *streamFile) -{ - return streamFile->real_file->get_error_count(streamFile->real_file); -} -#endif - -STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) -{ - BARSTREAM *streamfile = malloc(sizeof(BARSTREAM)); - - if (!streamfile) - return NULL; - - memset(streamfile, 0, sizeof(BARSTREAM)); - - streamfile->sf.read = (void*)read_bar; - streamfile->sf.get_size = (void*)get_size_bar; - streamfile->sf.get_offset = (void*)get_offset_bar; - streamfile->sf.get_name = (void*)get_name_bar; - streamfile->sf.get_realname = (void*)get_realname_bar; - streamfile->sf.open = (void*)open_bar; - streamfile->sf.close = (void*)close_bar; -#ifdef PROFILE_STREAMFILE - streamfile->sf.get_bytes_read = get_bytes_read_bar; - streamfile->sf.get_error_count = get_error_count_bar; -#endif - - streamfile->real_file = file; - - return &streamfile->sf; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca.c b/Frameworks/vgmstream/vgmstream/src/meta/hca.c index 2f99ab2eb..102614604 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca.c @@ -155,7 +155,6 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe f++; } - //;VGM_LOG("HCA: key %08x%08x clip_count=%i\n", ciphKey2,ciphKey1, clip_count); if (min_clip_count < 0 || clip_count < min_clip_count) { min_clip_count = clip_count; best_key2 = key2; @@ -176,7 +175,7 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe read_streamfile(buffer, hca_data->start, header_size, hca_data->streamfile); end: - VGM_LOG("HCA: best key=%08x%08x (clips=%i)\n", best_key2,best_key1, min_clip_count); + VGM_ASSERT(min_clip_count > 0, "HCA: best key=%08x%08x (clips=%i)\n", best_key2,best_key1, min_clip_count); *out_key2 = best_key2; *out_key1 = best_key1; free(testbuf);//free(temp); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index 48ac33945..21c9ef92a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h @@ -12,7 +12,7 @@ typedef struct { */ static const hcakey_info hcakey_list[] = { - // HCA Decoder default + // CRI HCA decoder default {9621963164387704}, // CF222F1FE0748978 // Phantasy Star Online 2 (multi?) @@ -28,7 +28,13 @@ static const hcakey_info hcakey_list[] = { // Ro-Kyu-Bu! Himitsu no Otoshimono (PSP) {2012082716}, // 0000000077EDF21C - // Ro-Kyu-Bu! Naisho no Shutter Chance (PSV) + // VRIDGE Inc. games: + // - HatsuKare * Renai Debut Sengen! (PSP) + // - Seitokai no Ichizon Lv. 2 Portable (PSP) + // - Koi wa Kousoku ni Shibararenai! (PSP) + // - StormLover 2nd (PSP) + // - Prince of Stride (PSVita) + // - Ro-Kyu-Bu! Naisho no Shutter Chance (PSVita) {1234253142}, // 0000000049913556 // Idolm@ster Cinderella Stage (iOS/Android) @@ -99,18 +105,45 @@ static const hcakey_info hcakey_list[] = { // World Chain (iOS/Android) {4892292804961027794}, // 43E4EA62B8E6C6D2 - // Yuyuyui (iOS/Android) *unconfirmed + // Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android) {4867249871962584729}, // 438BF1F883653699 // Tekken Mobile (iOS/Android) - {0xFFFFFFFFFFFFFFFF}, // + {0xFFFFFFFFFFFFFFFF}, // FFFFFFFFFFFFFFFF / 18446744073709551615 // Tales of the Rays (iOS/Android) {9516284}, // 00000000009134FC - // Skylock - Kamigami to Unmei no Itsutsuko [iOS] + // Skylock - Kamigami to Unmei no Itsutsuko (iOS/Android) {49160768297}, // 0000000B7235CB29 + // Tokyo Ghoul: Re Invoke (iOS/Android) + {6929101074247145}, // 00189DFB1024ADE9 + + // Azur Lane (iOS/Android) + {621561580448882}, // 0002354E95356C72 + + // One Piece Treasure Cruise (iOS/Android) + {1224}, // 00000000000004C8 + + // Schoolgirl Strikers ~Twinkle Melodies~ (iOS/Android) + {0xDB5B61B8343D0000}, // DB5B61B8343D0000 + + // Bad Apple Wars (PSVita) + {241352432}, // 000000000E62BEF0 + + // Koi to Senkyo to Chocolate Portable (PSP) + {243812156}, // 000000000E88473C + + // Custom Drive (PSP) + {2012062010}, // 0000000077EDA13A + + // Root Letter (PSVita) + {1547531215412131}, // 00057F78B05F9BA3 + + // Pro Evolution Soccer 2018 / Winning Eleven 2018 (Android) + {14121473}, // 0000000000D77A01 + }; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ivaud.c b/Frameworks/vgmstream/vgmstream/src/meta/ivaud.c index 0d585207f..5584dc318 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ivaud.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ivaud.c @@ -38,7 +38,7 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) { vgmstream->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile); vgmstream->coding_type = coding_IMA_int; - vgmstream->layout_type = layout_ivaud_blocked; + vgmstream->layout_type = layout_blocked_ivaud; vgmstream->meta_type = meta_PC_IVAUD; /* open the file for reading */ @@ -57,7 +57,7 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) { // to avoid troubles with "extra" samples vgmstream->num_samples=((read_32bitLE(0x60,streamFile)/2)*2); - ivaud_block_update(start_offset,vgmstream); + block_update_ivaud(start_offset,vgmstream); return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c b/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c index 73dcbebee..955aca458 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c @@ -5,7 +5,7 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count, i; + int loop_flag, channel_count; /* check extension, case insensitive */ if (!check_extensions(streamFile,"xa")) @@ -18,30 +18,22 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) { loop_flag = 0; channel_count = read_16bitLE(0x0A,streamFile); + start_offset = 0x18; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - start_offset = 0x18; - vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); - vgmstream->coding_type = coding_MAXIS_XA; vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count; - vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_MAXIS_XA; + vgmstream->coding_type = coding_MAXIS_XA; + vgmstream->layout_type = layout_none; /* open streams */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; - - /* fix channel offsets as needed by the codec (could be simplified) */ - for (i = 0; i < channel_count; i++) { - vgmstream->ch[i].channel_start_offset = start_offset+i; - vgmstream->ch[i].offset = 0; - } - return vgmstream; fail: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index a8da4c878..bc0ba6b03 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -15,7 +15,7 @@ VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_gcsw(STREAMFILE *streamFile); @@ -80,8 +80,6 @@ VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile); @@ -160,7 +158,7 @@ VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nwa(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_eacs(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_xss(STREAMFILE * streamFile); @@ -173,7 +171,6 @@ VGMSTREAM * init_vgmstream_aus(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_rws(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_fsb(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_fsb5(STREAMFILE * streamFile); @@ -200,11 +197,11 @@ VGMSTREAM * init_vgmstream_ikm(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_sfs(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_dvi(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_sat_dvi(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_bg00(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_kcey(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_dc_kcey(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE * streamFile); @@ -218,9 +215,9 @@ VGMSTREAM * init_vgmstream_ps2_psh(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_pcm_scd(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_scd_pcm(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_pcm_ps2(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ps2_pcm(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE * streamFile); @@ -243,16 +240,14 @@ VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_capdsp(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_de2(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile); @@ -276,14 +271,8 @@ VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE * streamFile); - -//VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_idsp2(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_idsp3(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_idsp4(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE * streamFile); @@ -323,7 +312,6 @@ VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE * streamFile); @@ -361,7 +349,6 @@ VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile); @@ -389,6 +376,7 @@ VGMSTREAM * init_vgmstream_ps2_vsf(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile); @@ -449,7 +437,6 @@ VGMSTREAM * init_vgmstream_wii_bns(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_wii_was(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_xbox_hlwav(STREAMFILE* streamFile); @@ -494,8 +481,6 @@ VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_p3d(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_ps2_adsc(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE* streamFile); @@ -505,9 +490,7 @@ VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE* streamFile); @@ -528,7 +511,7 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_xau(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_bar(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ffw(STREAMFILE* streamFile); @@ -581,10 +564,10 @@ VGMSTREAM * init_vgmstream_hyperscan_kvag(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ios_psnd(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile); + VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE* streamFile); @@ -670,6 +653,7 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_txth(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile); @@ -678,12 +662,30 @@ VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_stm(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_pc_ast(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_naac(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ezw(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_vxn(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_flx(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_mogg(STREAMFILE * streamFile); + #endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c b/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c index 833c17431..5706963dd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c @@ -45,6 +45,9 @@ VGMSTREAM * init_vgmstream_mn_str(STREAMFILE *streamFile) { vgmstream->interleave_block_size = 0x800; vgmstream->layout_type = layout_none; } + break; + default: + goto fail; } vgmstream->num_samples = read_32bitLE(0x4C,streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mogg.c b/Frameworks/vgmstream/vgmstream/src/meta/mogg.c new file mode 100644 index 000000000..d14e7e1a7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/mogg.c @@ -0,0 +1,42 @@ +/* +2017-12-10: Preliminary MOGG Support. As long as the stream is unencrypted, this should be fine. + This will also work on unconventional 5 channel Vorbis streams but some sound cards might not like it. + TODO (Eventually): Add decryption for encrypted MOGG types (Rock Band, etc.) + + -bxaimc +*/ + +#include "meta.h" +#include "../coding/coding.h" + +/* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */ +VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) { +#ifdef VGM_USE_VORBIS + char filename[PATH_LIMIT]; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile, filename, sizeof(filename)); + if (strcasecmp("mogg", filename_extension(filename))) goto fail; + + { + vgm_vorbis_info_t inf; + VGMSTREAM * result = NULL; + + memset(&inf, 0, sizeof(inf)); + inf.layout_type = layout_ogg_vorbis; + inf.meta_type = meta_MOGG; + + start_offset = read_32bitLE(0x04, streamFile); + result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + + if (result != NULL) { + return result; + } + } + +fail: + /* clean up anything we may have opened */ +#endif + return NULL; +} \ No newline at end of file diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mus_acm.c b/Frameworks/vgmstream/vgmstream/src/meta/mus_acm.c index 6d488785b..185e29367 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mus_acm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mus_acm.c @@ -15,7 +15,7 @@ #define NAME_LENGTH PATH_LIMIT -int exists(char *filename, STREAMFILE *streamfile) { +static int exists(char *filename, STREAMFILE *streamfile) { STREAMFILE * temp = streamfile->open(streamfile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!temp) return 0; @@ -25,7 +25,7 @@ int exists(char *filename, STREAMFILE *streamfile) { } /* needs the name of a file in the directory to test, as all we can do reliably is attempt to open a file */ -int find_directory_name(char *name_base, char *dir_name, int subdir_name_size, char *subdir_name, char *name, char *file_name, STREAMFILE *streamfile) { +static int find_directory_name(char *name_base, char *dir_name, int subdir_name_size, char *subdir_name, char *name, char *file_name, STREAMFILE *streamfile) { /* find directory name */ { char temp_dir_name[NAME_LENGTH]; @@ -125,7 +125,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) { if (strcasecmp("mus",filename_extension(filename))) goto fail; /* read file name base */ - line_bytes = get_streamfile_dos_line(sizeof(line_buffer),line_buffer, + line_bytes = get_streamfile_text_line(sizeof(line_buffer),line_buffer, mus_offset, streamFile, &whole_line_read); if (!whole_line_read) goto fail; mus_offset += line_bytes; @@ -140,7 +140,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) { /*printf("name base: %s\n",name_base);*/ /* read track entry count */ - line_bytes = get_streamfile_dos_line(sizeof(line_buffer),line_buffer, + line_bytes = get_streamfile_text_line(sizeof(line_buffer),line_buffer, mus_offset, streamFile, &whole_line_read); if (!whole_line_read) goto fail; if (line_buffer[0] == '\0') goto fail; @@ -184,7 +184,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) { { int fields_matched; line_bytes = - get_streamfile_dos_line(sizeof(line_buffer),line_buffer, + get_streamfile_text_line(sizeof(line_buffer),line_buffer, mus_offset, streamFile, &whole_line_read); if (!whole_line_read) goto fail; mus_offset += line_bytes; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/myspd.c b/Frameworks/vgmstream/vgmstream/src/meta/myspd.c index cfcb6d444..373f23031 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/myspd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/myspd.c @@ -1,59 +1,42 @@ #include "meta.h" -#include "../util.h" - -/* U-Sing (Wii) .myspd */ +#include "../coding/coding.h" +/* .MYSPF - from U-Sing (Wii) */ VGMSTREAM * init_vgmstream_myspd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int channel_count; - int loop_flag = 0; + int loop_flag = 0, channel_count; off_t start_offset; + size_t channel_size; /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("myspd",filename_extension(filename))) goto fail; + if (!check_extensions(streamFile,"myspd")) + goto fail; channel_count = 2; start_offset = 0x20; + channel_size = read_32bitBE(0x00,streamFile); /* check size */ - if ((read_32bitBE(0x0,streamFile)*channel_count+start_offset) != get_streamfile_size(streamFile)) + if ((channel_size * channel_count + 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 */ - vgmstream->num_samples = read_32bitBE(0x0,streamFile) * 2; - vgmstream->sample_rate = read_32bitBE(0x4,streamFile); + vgmstream->num_samples = ima_bytes_to_samples(channel_size*channel_count, channel_count); + vgmstream->sample_rate = read_32bitBE(0x04,streamFile); - vgmstream->coding_type = coding_IMA; vgmstream->meta_type = meta_MYSPD; - vgmstream->layout_type = layout_none; + vgmstream->coding_type = coding_IMA_int; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = channel_size; - /* open the file for reading */ - { - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - vgmstream->ch[0].streamfile = file; + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; - vgmstream->ch[0].channel_start_offset= - vgmstream->ch[0].offset=start_offset; - - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - vgmstream->ch[1].streamfile = file; - - vgmstream->ch[0].channel_start_offset= - vgmstream->ch[1].offset=start_offset + read_32bitBE(0x0,streamFile); - } - 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/naac.c b/Frameworks/vgmstream/vgmstream/src/meta/naac.c new file mode 100644 index 000000000..b657e598b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/naac.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* .NAAC - from Namco 3DS games (Ace Combat - Assault Horizon Legacy, Taiko no Tatsujin Don to Katsu no Jikuu Daibouken) */ +VGMSTREAM * init_vgmstream_naac(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + size_t data_size; + + /* check extension */ + if ( !check_extensions(streamFile,"naac") ) + goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x41414320) /* "AAC " */ + goto fail; + if (read_32bitLE(0x04,streamFile) != 0x01) /* version? */ + goto fail; + + start_offset = 0x1000; + loop_flag = (read_32bitLE(0x18,streamFile) != 0); + channel_count = read_32bitLE(0x08,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(0x0c,streamFile); + vgmstream->num_samples = read_32bitLE(0x10,streamFile); /* without skip_samples */ + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); /* with skip_samples */ + vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile); + /* 0x1c: loop start offset, 0x20: loop end offset (within data) */ + data_size = read_32bitLE(0x24,streamFile); + /* 0x28: unknown; 0x2c: table start offset?; 0x30: seek table (always 0xFD0, padded) */ + + vgmstream->meta_type = meta_NAAC; + +#ifdef VGM_USE_FFMPEG + { + ffmpeg_codec_data *ffmpeg_data = NULL; + + ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,data_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + /* observed default, some files start without silence though seems correct when loop_start=0 */ + if (!ffmpeg_data->skipSamples) /* FFmpeg doesn't seem to use not report it */ + ffmpeg_set_skip_samples(ffmpeg_data, 1024); + vgmstream->num_samples -= 1024; + } +#else + goto fail; +#endif + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_hwas.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_hwas.c index f9b9d0de1..e50e614ea 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nds_hwas.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_hwas.c @@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) { off_t start_offset; int channel_count, loop_flag = 0; - /* check extension, case insensitive */ + /* check extension, case insensitive (made-up extension) */ if (!check_extensions(streamFile,"hwas")) goto fail; @@ -33,7 +33,7 @@ VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) { vgmstream->meta_type = meta_NDS_HWAS; - vgmstream->coding_type = coding_IMA; + vgmstream->coding_type = coding_IMA_int; vgmstream->layout_type = layout_hwas_blocked; vgmstream->full_block_size = read_32bitLE(0x04,streamFile); /* usually 0x2000, 0x4000 or 0x8000 */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_rrds.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_rrds.c index c38e9d649..ac28b64cd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nds_rrds.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_rrds.c @@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile) { int loop_flag; off_t start_offset; - /* check extension, case insensitive */ + /* check extension, case insensitive (made-up extension) */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("rrds",filename_extension(filename))) goto fail; @@ -37,7 +37,7 @@ VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile) { vgmstream->loop_end_sample = vgmstream->num_samples; } - vgmstream->coding_type = coding_IMA; + vgmstream->coding_type = coding_IMA_int; vgmstream->meta_type = meta_NDS_RRDS; vgmstream->layout_type = layout_none; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_strm.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm.c index c41cd9ed8..adef717aa 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nds_strm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm.c @@ -19,11 +19,11 @@ VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) { if (strcasecmp("strm",filename_extension(filename))) goto fail; /* check header */ - if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */ + if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */ + goto fail; + if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */ + ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */ goto fail; - if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */ - ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */ - goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c index 9f1e0e2e7..fcb0fa33d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm_ffta2.c @@ -1,5 +1,4 @@ #include "meta.h" -#include "../util.h" /* STRM - from Final Fantasy Tactics A2 (NDS) */ VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) { @@ -18,25 +17,24 @@ VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) { loop_flag = (read_32bitLE(0x20,streamFile) !=0); channel_count = read_32bitLE(0x24,streamFile); + start_offset = 0x2C; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - start_offset = 0x2C; vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); - vgmstream->coding_type = coding_IMA_int; //todo: seems it has some diffs vs regular IMA vgmstream->num_samples = (read_32bitLE(0x04,streamFile)-start_offset); - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x28,streamFile); - } + vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x28,streamFile); - vgmstream->interleave_block_size = 0x80; - vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_NDS_STRM_FFTA2; + vgmstream->coding_type = coding_DVI_IMA_int; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c index 06eeabcde..71d4b9a5e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c @@ -1214,6 +1214,7 @@ fail: Lego Indiana Jones - The Original Adventures (Wii) Lego Indiana Jones 2 - The Adventure Continues (Wii) Lego Star Wars - The Complete Saga (Wii) + Lego The Lord of the Rings (Wii) The Chronicles of Narnia - Prince Caspian (Wii) */ VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; @@ -1249,6 +1250,14 @@ VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) { start_offset = 0xe0; } + else if (read_32bitBE(0x4, streamFile) == 3 && //Lego The Lord of the Rings (Wii) + read_32bitBE(0x8, streamFile) == 0x12c) + { + if (read_dsp_header(&ch0_header, 0x20, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, 0x80, streamFile)) goto fail; + + start_offset = 0xe0; + } else goto fail; interleave = read_32bitBE(0xc, streamFile); @@ -2070,8 +2079,8 @@ VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) { vgmstream->loop_end_sample = dsp_nibbles_to_samples( ch0_header.loop_end_offset)+1; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave_byte; + vgmstream->coding_type = coding_NGC_DSP_subint; + vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = 0x4; vgmstream->meta_type = meta_WII_NDP; @@ -2089,22 +2098,12 @@ VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) { vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; /* open the file for reading */ - vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[0].streamfile) - goto fail; - vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; - - vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[1].streamfile) - goto fail; - vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; - + if (!vgmstream_open_stream(vgmstream,streamFile,ch1_start)) + 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/ngc_dsp_ygo.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_ygo.c index 76de70baf..776080188 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_ygo.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_ygo.c @@ -2,17 +2,17 @@ #include "../util.h" /* .dsp found in: - Hikaru No Go 3 (NGC) - Yu-Gi-Oh! The Falsebound Kingdom (NGC) + Hikaru No Go 3 (NGC) + Yu-Gi-Oh! The Falsebound Kingdom (NGC) - 2010-01-31 - added loop stuff and some header checks... + 2010-01-31 - added loop stuff and some header checks... */ VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - int loop_flag; - int channel_count; + int loop_flag; + int channel_count; off_t start_offset; int i; @@ -24,29 +24,29 @@ VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) { if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile))) goto fail; - loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0); + loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0); channel_count = 1; - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0xE0; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x28,streamFile); + /* fill in the vital statistics */ + start_offset = 0xE0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x28,streamFile); vgmstream->coding_type = coding_NGC_DSP; vgmstream->num_samples = read_32bitBE(0x20,streamFile); vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_DSP_YGO; - if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16); - vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16); - } + vgmstream->meta_type = meta_DSP_YGO; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16); + vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16); + } - // read coef stuff - { - for (i=0;i<16;i++) { + // read coef stuff + { + for (i=0;i<16;i++) { vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c index ad9e1498a..edf1ed678 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c @@ -8,63 +8,63 @@ VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; + VGMSTREAM * vgmstream = NULL; STREAMFILE * streamFileDSP = NULL; char filename[PATH_LIMIT]; - char filenameDSP[PATH_LIMIT]; - - int i; - int channel_count; - int loop_flag; + char filenameDSP[PATH_LIMIT]; + + int i; + int channel_count; + int loop_flag; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("sck",filename_extension(filename))) goto fail; - strcpy(filenameDSP,filename); - strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp"); + strcpy(filenameDSP,filename); + strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp"); + + streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE); - streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (read_32bitBE(0x5C,streamFile) != 0x60A94000) goto fail; - if (!streamFile) goto fail; - - channel_count = 2; - loop_flag = 0; + if (!streamFile) goto fail; + + channel_count = 2; + loop_flag = 0; /* 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_32bitBE(0x18,streamFile); - vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14; - vgmstream->coding_type = coding_NGC_DSP; - - if(loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14; - } + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x18,streamFile); + vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14; + vgmstream->coding_type = coding_NGC_DSP; - if (channel_count == 1) { - vgmstream->layout_type = layout_none; - } else if (channel_count == 2) { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile); - } + if(loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14; + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile); + } vgmstream->meta_type = meta_NGC_SCK_DSP; - + /* open the file for reading */ { for (i=0;ich[i].streamfile = streamFile->open(streamFileDSP,filenameDSP,0x8000); vgmstream->ch[i].offset = 0; @@ -74,7 +74,7 @@ VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) { - if (vgmstream->coding_type == coding_NGC_DSP) { + if (vgmstream->coding_type == coding_NGC_DSP) { int i; for (i=0;i<16;i++) { vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x2C+i*2,streamFile); @@ -87,7 +87,7 @@ VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) { } - close_streamfile(streamFileDSP); streamFileDSP=NULL; + close_streamfile(streamFileDSP); streamFileDSP=NULL; return vgmstream; /* clean up anything we may have opened */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_vid1.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_vid1.c new file mode 100644 index 000000000..ec2576423 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_vid1.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../util.h" +#include "../coding/coding.h" + + +/* VID1 - from Neversoft games (Gun, Tony Hawk's American Wasteland GC) */ +VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, header_offset, header_size; + int loop_flag = 0, channel_count; + + + /* check extension */ + if (!check_extensions(streamFile,"ogg,logg")) + goto fail; + + /* chunked/blocked format containing video or audio frames */ + if (read_32bitBE(0x00,streamFile) != 0x56494431) /* "VID1" */ + goto fail; + + /* find actual header start/size in the chunks */ + { + header_offset = read_32bitBE(0x04, streamFile); + if (read_32bitBE(header_offset,streamFile) != 0x48454144) /* "HEAD" */ + goto fail; + start_offset = header_offset + read_32bitBE(header_offset + 0x04, streamFile); + header_offset += 0x0c; + + /* videos have VIDH before AUDH, and VIDD in blocks, but aren't parsed ATM */ + + if (read_32bitBE(header_offset,streamFile) != 0x41554448) /* "AUDH" */ + goto fail; + header_size = read_32bitBE(header_offset + 0x04, streamFile); + header_offset += 0x0c; + + if (read_32bitBE(header_offset,streamFile) != 0x56415544) /* "VAUD" (Vorbis audio?) */ + goto fail; + header_offset += 0x04; + header_size -= 0x10; + + } + channel_count = read_8bit(header_offset + 0x04,streamFile); + /* other values unknown, maybe related to vorbis (ex. bitrate/encoding modes) */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitBE(header_offset + 0x00, streamFile); + vgmstream->num_samples = read_32bitBE(header_offset + 0x1c, streamFile); + vgmstream->meta_type = meta_NGC_VID1; + +#ifdef VGM_USE_VORBIS + { + vorbis_custom_config cfg = {0}; + + vgmstream->layout_type = layout_none; + vgmstream->coding_type = coding_VORBIS_custom; + vgmstream->codec_data = init_vorbis_custom_codec_data(streamFile, header_offset + 0x20, VORBIS_VID1, &cfg); + if (!vgmstream->codec_data) goto fail; + } +#else + goto fail; +#endif + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c b/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c index 9339d477d..a0e8ca078 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nsw_opus.c @@ -2,30 +2,61 @@ #include "../util.h" #include "../coding/coding.h" -/* .OPUS - from Lego City Undercover (Switch) */ +/* .OPUS - from Switch games (Lego City Undercover, Ultra SF II, Disgaea 5) */ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag = 0, channel_count; + int num_samples = 0, loop_start = 0, loop_end = 0; + off_t offset = 0; /* check extension, case insensitive */ if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */ goto fail; - if (read_32bitBE(0x00,streamFile) != 0x01000080) + /* variations, maybe custom */ + if (read_32bitBE(0x00,streamFile) == 0x01000080) { /* Lego City Undercover */ + offset = 0x00; + } + else if ((read_32bitBE(0x04,streamFile) == 0x00000000 && read_32bitBE(0x0c,streamFile) == 0x00000000) || + (read_32bitBE(0x04,streamFile) == 0xFFFFFFFF && read_32bitBE(0x0c,streamFile) == 0xFFFFFFFF)) { /* Disgaea 5 */ + offset = 0x10; + + loop_start = read_32bitLE(0x00,streamFile); + loop_end = read_32bitLE(0x08,streamFile); + } + else if (read_32bitLE(0x04,streamFile) == 0x02) { /* Ultra Street Fighter II */ + offset = read_32bitLE(0x1c,streamFile); + + num_samples = read_32bitLE(0x00,streamFile); + loop_start = read_32bitLE(0x08,streamFile); + loop_end = read_32bitLE(0x0c,streamFile); + } + else { + offset = 0x00; + } + + if (read_32bitBE(offset + 0x00,streamFile) != 0x01000080) goto fail; - start_offset = 0x28; - channel_count = read_8bit(0x09,streamFile); /* assumed */ - /* other values in the header: no idea */ + start_offset = offset + 0x28; + channel_count = read_8bit(offset + 0x09,streamFile); /* assumed */ + /* 0x0a: packet size if CBR?, other values: no idea */ + + loop_flag = (loop_end > 0); /* -1 when not set */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = read_32bitLE(0x0c,streamFile); + vgmstream->sample_rate = read_32bitLE(offset + 0x0c,streamFile); vgmstream->meta_type = meta_NSW_OPUS; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + #ifdef VGM_USE_FFMPEG { uint8_t buf[0x100]; @@ -47,7 +78,8 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - 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); } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/omu.c b/Frameworks/vgmstream/vgmstream/src/meta/omu.c new file mode 100644 index 000000000..c45a00203 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/omu.c @@ -0,0 +1,45 @@ +#include "meta.h" + +/* IMU - found in Alter Echo (PS2) */ +VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + + + /* check extension */ + if ( !check_extensions(streamFile,"omu") ) + goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4F4D5520 && /* "OMU " */ + read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */ + goto fail; + + loop_flag = 1; + channel_count = (int)read_8bit(0x14,streamFile); + start_offset = 0x40; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->num_samples = (int32_t)(read_32bitLE(0x3C,streamFile)/(vgmstream->channels*2)); + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x200; + vgmstream->meta_type = meta_PS2_OMU; + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_adp.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_adp.c index 66d174bd8..4ff7c07ce 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/pc_adp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_adp.c @@ -1,5 +1,4 @@ #include "meta.h" -#include "../util.h" /* ADP - from Balls of Steel */ VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE *streamFile) { @@ -31,7 +30,7 @@ VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE *streamFile) { vgmstream->loop_end_sample = vgmstream->num_samples; } - vgmstream->coding_type = coding_DVI_IMA; + vgmstream->coding_type = coding_DVI_IMA_int; vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_BOS_ADP; @@ -48,45 +47,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -/* ADP - from Omikron: The Nomad Soul (PC/DC) */ -VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, datasize; - int loop_flag = 0, channel_count, stereo_flag; - - if (!check_extensions(streamFile,"adp")) goto fail; - - /* no ID, only a basic 0x10 header with filesize and nulls; do some extra checks */ - datasize = read_32bitLE(0x00,streamFile) & 0x00FFFFFF; /*24 bit*/ - if (datasize + 0x10 != streamFile->get_size(streamFile) - || read_32bitLE(0x04,streamFile) != 0 - || read_32bitLE(0x08,streamFile) != 0 - || read_32bitLE(0x10,streamFile) != 0) - goto fail; - - stereo_flag = read_8bit(0x03, streamFile); - if (stereo_flag > 1 || stereo_flag < 0) goto fail; - channel_count = stereo_flag ? 2 : 1; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - start_offset = 0x10; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 22050; - vgmstream->num_samples = channel_count== 1 ? datasize*2 : datasize; - - vgmstream->coding_type = coding_OTNS_IMA; - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_OTNS_ADP; - - if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_adp_otns.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_adp_otns.c new file mode 100644 index 000000000..6efc43d58 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_adp_otns.c @@ -0,0 +1,43 @@ +#include "meta.h" + +/* ADP - from Omikron: The Nomad Soul (PC/DC) */ +VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, datasize; + int loop_flag = 0, channel_count, stereo_flag; + + if (!check_extensions(streamFile,"adp")) goto fail; + + /* no ID, only a basic 0x10 header with filesize and nulls; do some extra checks */ + datasize = read_32bitLE(0x00,streamFile) & 0x00FFFFFF; /*24 bit*/ + if (datasize + 0x10 != streamFile->get_size(streamFile) + || read_32bitLE(0x04,streamFile) != 0 + || read_32bitLE(0x08,streamFile) != 0 + || read_32bitLE(0x0c,streamFile) != 0) + goto fail; + + stereo_flag = read_8bit(0x03, streamFile); + if (stereo_flag > 1 || stereo_flag < 0) goto fail; + channel_count = stereo_flag ? 2 : 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + start_offset = 0x10; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 22050; + vgmstream->num_samples = channel_count== 1 ? datasize*2 : datasize; + + vgmstream->coding_type = coding_OTNS_IMA; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_OTNS_ADP; + + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_ast.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_ast.c new file mode 100644 index 000000000..e678f2632 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_ast.c @@ -0,0 +1,44 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* ASTL - found in Dead Rising (PC) */ +VGMSTREAM * init_vgmstream_pc_ast(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, data_size; + int loop_flag, channel_count; + + /* check extension, case insensitive */ + if ( !check_extensions(streamFile,"ast")) + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x4153544C) /* "ASTL" */ + goto fail; + + + loop_flag = 0; //TODO - Find hidden loop point calc and flag + channel_count = read_8bit(0x32, streamFile); + data_size = read_32bitLE(0x20,streamFile); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* TODO - Find non-obvious loop points and flag (if any) */ + start_offset = read_32bitLE(0x10,streamFile); + vgmstream->sample_rate = read_32bitLE(0x34,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = data_size/(channel_count*2); + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_PC_AST; + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_sob.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_sob.c deleted file mode 100644 index 3754a2c22..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/pc_sob.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* SOB/SAB combination as found in Worms 4: Mayhem -they are actually soundpacks, but the audio data is just streamed as one big stream -*/ - -VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE* sob = NULL; - char filename[PATH_LIMIT]; - int i; - int loop_flag, channel_count, numSounds; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("sab",filename_extension(filename))) goto fail; - - /* read information from sob file*/ - filename[strlen(filename)-2]='o'; //change extension in sob of file - sob = open_stdio_streamfile(filename); - if(!sob) goto fail; - filename[strlen(filename)-2]='a';//change back to original file - - if (read_32bitBE(0,streamFile)!=0x43535732)//CSW2 header sab file - { - goto fail; - } - if (read_32bitBE(0,sob)!=0x43544632)//CTF2 header sob file - { - goto fail; - } - numSounds = read_32bitLE(8,sob); - if(numSounds==1) - {//it means it's a single stream and not a voice bank - loop_flag = 1; - }else - { - loop_flag = 0; - } - - /* Read channels */ - channel_count = read_32bitLE(0x30,sob); - if( (channel_count>2)||(numSounds>1))/* dirty hack for number of channels*/ - channel_count = 1; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - //is offset OK. sab files can contain more audio files, but without the sob it's just a long stream of sound effects - vgmstream->current_block_offset=8+32*numSounds; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x20,streamFile); - vgmstream->coding_type = coding_PCM16_int; - vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile)-vgmstream->current_block_offset)/2/channel_count); - if(loop_flag) - { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_PC_SOB_SAB; - - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[i].streamfile) goto fail; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=vgmstream->current_block_offset+2*i; - } - } - close_streamfile(sob); - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (sob) close_streamfile(sob); - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pcm.c b/Frameworks/vgmstream/vgmstream/src/meta/pcm.c deleted file mode 100644 index ff6371069..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/pcm.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* PCM (from Lunar: Eternal Blue (Sega CD) */ -VGMSTREAM * init_vgmstream_pcm_scd(STREAMFILE *streamFile) { - - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("pcm",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x0,streamFile) != 0x00020000) - goto fail; - - loop_flag = (read_32bitLE(0x02,streamFile)!=0); - channel_count = 1; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x200; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 32000; - vgmstream->coding_type = coding_PCM8_SB_int; - vgmstream->num_samples = read_32bitBE(0x06,streamFile)*2; - if(loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x02,streamFile)*0x400*2; - vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile)*2; - } - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x1; - vgmstream->meta_type = meta_PCM_SCD; - - /* 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; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - - -/* PCM - Custom header from Konami, which contains only loop infos... - found in: Ephemeral Fantasia [Reiselied] - Yu-Gi-Oh! The Duelists of the Roses [Yu-Gi-Oh! Shin Duel Monsters II] -*/ -VGMSTREAM * init_vgmstream_pcm_ps2(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("pcm",filename_extension(filename))) goto fail; - - // if ((read_32bitLE(0x00,streamFile)+0x800) != (get_streamfile_size(streamFile))) - // goto fail; - if ((read_32bitLE(0x00,streamFile)) != (read_32bitLE(0x04,streamFile)*4)) - goto fail; - - loop_flag = (read_32bitLE(0x08,streamFile) != 0x0); - channel_count = 2; - - /* 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 = 24000; - vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = read_32bitLE(0x0,streamFile)/2/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile); - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x2; - vgmstream->meta_type = meta_PCM_PS2; - - /* 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; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - 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/ps2_ads.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c index e8316ebde..628aba3ec 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c @@ -9,17 +9,17 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { int loop_flag=0; int channel_count; - off_t start_offset; - off_t check_offset; - int32_t streamSize; + off_t start_offset; + off_t check_offset; + int32_t streamSize; - uint8_t testBuffer[0x10]; - uint8_t isPCM = 0; + uint8_t testBuffer[0x10]; + uint8_t isPCM = 0; - off_t readOffset = 0; - off_t loopEnd = 0; + off_t readOffset = 0; + off_t loopEnd = 0; - int i; + int i; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -35,27 +35,27 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { goto fail; /* check if file is not corrupt */ - /* seems the Gran Turismo 4 ADS files are considered corrupt,*/ - /* so I changed it to adapt the stream size if that's the case */ - /* instead of failing playing them at all*/ - streamSize = read_32bitLE(0x24,streamFile); + /* seems the Gran Turismo 4 ADS files are considered corrupt,*/ + /* so I changed it to adapt the stream size if that's the case */ + /* instead of failing playing them at all*/ + streamSize = read_32bitLE(0x24,streamFile); - if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28)) - { - streamSize = get_streamfile_size(streamFile) - 0x28; - } + if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28)) + { + streamSize = get_streamfile_size(streamFile) - 0x28; + } /* check loop */ - if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) || - ((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0))) - { - loop_flag = 0; - } - else - { - loop_flag = 1; - } - + if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) || + ((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0))) + { + loop_flag = 0; + } + else + { + loop_flag = 1; + } + channel_count=read_32bitLE(0x10,streamFile); /* build the VGMSTREAM */ @@ -70,9 +70,9 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { vgmstream->coding_type = coding_PSX; vgmstream->num_samples = ((streamSize-0x40)/16*28)/vgmstream->channels; - /* SS2 container with RAW Interleaved PCM */ + /* SS2 container with RAW Interleaved PCM */ if (read_32bitLE(0x08,streamFile)!=0x10) - { + { vgmstream->coding_type=coding_PCM16LE; vgmstream->num_samples = streamSize/2/vgmstream->channels; @@ -84,100 +84,100 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { /* Get loop point values */ if(vgmstream->loop_flag) { - if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile)) - { - // Search for Loop Value - readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size); + if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile)) + { + // Search for Loop Value + readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size); - do { - readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); - - // Loop End ... - if(testBuffer[0x01]==0x01) { - if(loopEnd==0) loopEnd = readOffset-0x10; - break; - } + do { + readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); - } while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile)); + // Loop End ... + if(testBuffer[0x01]==0x01) { + if(loopEnd==0) loopEnd = readOffset-0x10; + break; + } - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28; - vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28; - vgmstream->loop_end_sample /=vgmstream->channels; + } while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile)); - } else { - if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) { - vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); - } else { - vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;; - vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels; - } - } + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28; + vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28; + vgmstream->loop_end_sample /=vgmstream->channels; + + } else { + if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) { + vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + } else { + vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;; + vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels; + } + } } /* don't know why, but it does happen, in ps2 too :( */ if (vgmstream->loop_end_sample > vgmstream->num_samples) vgmstream->loop_end_sample = vgmstream->num_samples; - { - start_offset=0x28; - } + { + start_offset=0x28; + } - - if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18)) - { - // True Fortune PS2 - streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10; - vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels; - } - else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800) - { - // Hack for files with start_offset = 0x800 - start_offset=0x800; - } - if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28)) - { - start_offset=0x800; - - for(i=0;i<0x1f6;i+=4) - { - if(read_32bitLE(0x28+(i*4),streamFile)!=0) - { - start_offset=0x28; - break; - } - } - } + if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18)) + { + // True Fortune PS2 + streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10; + vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels; + } + else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800) + { + // Hack for files with start_offset = 0x800 + start_offset=0x800; + } - // check if we got a real pcm (ex: Clock Tower 3) - if(vgmstream->coding_type==coding_PCM16LE) - { - check_offset=start_offset; - do - { - if(read_8bit(check_offset+1,streamFile)>7) - { - isPCM=1; - break; - } - else - { - check_offset+=0x10; - } - - } while (check_offsetcoding_type == coding_PSX) && (start_offset==0x28)) + { + start_offset=0x800; - if(!isPCM) - { - vgmstream->num_samples=(get_streamfile_size(streamFile)-start_offset)/16*28/vgmstream->channels; - vgmstream->coding_type=coding_PSX; - } - } + for(i=0;i<0x1f6;i+=4) + { + if(read_32bitLE(0x28+(i*4),streamFile)!=0) + { + start_offset=0x28; + break; + } + } + } - /* expect pcm format allways start @ 0x800, don't know if it's true :P */ - /*if(vgmstream->coding_type == coding_PCM16LE) - start_offset=0x800;*/ + // check if we got a real pcm (ex: Clock Tower 3) + if(vgmstream->coding_type==coding_PCM16LE) + { + check_offset=start_offset; + do + { + if(read_8bit(check_offset+1,streamFile)>7) + { + isPCM=1; + break; + } + else + { + check_offset+=0x10; + } + + } while (check_offsetnum_samples=(get_streamfile_size(streamFile)-start_offset)/16*28/vgmstream->channels; + vgmstream->coding_type=coding_PSX; + } + } + + /* expect pcm format allways start @ 0x800, don't know if it's true :P */ + /*if(vgmstream->coding_type == coding_PCM16LE) + start_offset=0x800;*/ /* open the file for reading by each channel */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_filp.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_filp.c index 4f888bdc7..ec5d6757f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_filp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_filp.c @@ -8,8 +8,8 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; int loop_flag = 0; - int channel_count; - int i; + int channel_count; + int i; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -18,23 +18,23 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) { /* check header */ if (read_32bitBE(0x0,streamFile) != 0x46494C70) /* "FILp" */ goto fail; - if (read_32bitBE(0x100,streamFile) != 0x56414770) /* "VAGp" */ + if (read_32bitBE(0x100,streamFile) != 0x56414770) /* "VAGp" */ goto fail; - if (read_32bitBE(0x130,streamFile) != 0x56414770) /* "VAGp" */ + if (read_32bitBE(0x130,streamFile) != 0x56414770) /* "VAGp" */ + goto fail; + if (get_streamfile_size(streamFile) != read_32bitLE(0xC,streamFile)) goto fail; - if (get_streamfile_size(streamFile) != read_32bitLE(0xC,streamFile)) - goto fail; loop_flag = (read_32bitLE(0x34,streamFile) == 0); channel_count = read_32bitLE(0x4,streamFile); - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ + /* fill in the vital statistics */ start_offset = 0x0; - vgmstream->channels = channel_count; + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x110,streamFile); vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_filp_blocked; @@ -47,9 +47,9 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) { if (!file) goto fail; for (i=0;ich[i].streamfile = file; - } - } - + } + } + filp_block_update(start_offset,vgmstream); vgmstream->num_samples = read_32bitLE(0x10C,streamFile)/16*28; if (loop_flag) { @@ -57,7 +57,7 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) { vgmstream->loop_end_sample = vgmstream->num_samples; } - + return vgmstream; /* clean up anything we may have opened */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_gcm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_gcm.c index 92a07800a..aea990a3a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_gcm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_gcm.c @@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE *streamFile) { off_t start_offset; int loop_flag; - int channel_count; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -17,19 +17,19 @@ VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE *streamFile) { /* check header */ if (read_32bitBE(0x00,streamFile) != 0x4D434700) /* "MCG" */ goto fail; - if (read_32bitBE(0x20,streamFile) != 0x56414770) /* "VAGp" */ + if (read_32bitBE(0x20,streamFile) != 0x56414770) /* "VAGp" */ goto fail; loop_flag = 0; 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 */ + /* fill in the vital statistics */ start_offset = 0x80; - vgmstream->channels = channel_count; + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitBE(0x30,streamFile); vgmstream->coding_type = coding_PSX; vgmstream->num_samples = read_32bitLE(0x10,streamFile)*28/32; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_hsf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_hsf.c index 679792390..8c00a312b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_hsf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_hsf.c @@ -8,14 +8,14 @@ VGMSTREAM * init_vgmstream_ps2_hsf(STREAMFILE *streamFile) char filename[PATH_LIMIT]; off_t start_offset; int loop_flag = 0; - int channel_count; - size_t fileLength; - size_t frequencyFlag; - + int channel_count; + size_t fileLength; + size_t frequencyFlag; + #if 0 - off_t readOffset = 0; - uint8_t testBuffer[0x10]; - off_t loopEndOffset; + off_t readOffset = 0; + uint8_t testBuffer[0x10]; + off_t loopEndOffset; #endif /* check extension, case insensitive */ @@ -26,56 +26,56 @@ VGMSTREAM * init_vgmstream_ps2_hsf(STREAMFILE *streamFile) if (read_32bitBE(0x00,streamFile) != 0x48534600) // "HSF" goto fail; - loop_flag = 0; + loop_flag = 0; channel_count = 2; fileLength = get_streamfile_size(streamFile); - frequencyFlag = read_32bitLE(0x08, streamFile); + frequencyFlag = 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 = 0x10; - vgmstream->channels = channel_count; + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; - if (frequencyFlag == 0x0EB3) - { - vgmstream->sample_rate = 44100; - } - else if (frequencyFlag == 0x1000) - { - vgmstream->sample_rate = 48000; - } - - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = ((fileLength - 0x10) / 16 * 28) / vgmstream->channels; + if (frequencyFlag == 0x0EB3) + { + vgmstream->sample_rate = 44100; + } + else if (frequencyFlag == 0x1000) + { + vgmstream->sample_rate = 48000; + } + + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((fileLength - 0x10) / 16 * 28) / vgmstream->channels; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x0C, streamFile); vgmstream->meta_type = meta_PS2_HSF; - if (vgmstream->loop_flag) - { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; #if 0 - readOffset = fileLength - 0x10; + readOffset = fileLength - 0x10; - do - { - readOffset -=(off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + do + { + readOffset -=(off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); - if (testBuffer[1] == 0x07) - { - loopEndOffset = readOffset + 0x10; - vgmstream->loop_end_sample = ((loopEndOffset - 0x10) / 16 * 28) / vgmstream->channels; - break; - } + if (testBuffer[1] == 0x07) + { + loopEndOffset = readOffset + 0x10; + vgmstream->loop_end_sample = ((loopEndOffset - 0x10) / 16 * 28) / vgmstream->channels; + break; + } - } while (readOffset > 0); + } while (readOffset > 0); #endif - } + } /* open the file for reading */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ild.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ild.c index ea6a846f1..7ef439efa 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ild.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ild.c @@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; int loop_flag=0; - int channel_count; + int channel_count; off_t start_offset; int i; @@ -19,33 +19,33 @@ VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x494C4400) goto fail; - /* check loop */ - loop_flag = (read_32bitLE(0x2C,streamFile)!=0); + /* check loop */ + loop_flag = (read_32bitLE(0x2C,streamFile)!=0); 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 = read_32bitLE(0x04,streamFile); + /* fill in the vital statistics */ + vgmstream->channels = read_32bitLE(0x04,streamFile); vgmstream->sample_rate = read_32bitLE(0x28,streamFile); - /* Check for Compression Scheme */ - vgmstream->coding_type = coding_PSX; + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels; - /* Get loop point values */ - if(vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x2C,streamFile)/16*28; - vgmstream->loop_end_sample = read_32bitLE(0x30,streamFile)/16*28; - } + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x2C,streamFile)/16*28; + vgmstream->loop_end_sample = read_32bitLE(0x30,streamFile)/16*28; + } - vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile)/2; + vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile)/2; vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_ILD; - start_offset = (off_t)read_32bitLE(0x08,streamFile); + start_offset = (off_t)read_32bitLE(0x08,streamFile); /* open the file for reading by each channel */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_int.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_int.c index e7aa1a84e..fc623fa39 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_int.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_int.c @@ -27,6 +27,10 @@ VGMSTREAM * init_vgmstream_ps2_int(STREAMFILE *streamFile) { else channel_count = 4; + /* ignore A2M .int */ + if (read_32bitBE(0x00,streamFile) == 0x41324D00) /* "A2M\0" */ + goto fail; + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,0); if (!vgmstream) goto fail; @@ -59,57 +63,3 @@ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; } - - -// OMU is a PS2 .INT file with header ... -// found in Alter Echo -VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int i,channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("omu",filename_extension(filename))) goto fail; - - /* check header */ - if((read_32bitBE(0,streamFile)!=0x4F4D5520) && (read_32bitBE(0x08,streamFile)!=0x46524D54)) - goto fail; - - channel_count = (int)read_8bit(0x14,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,1); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels=channel_count; - vgmstream->sample_rate = read_32bitLE(0x10,streamFile); - vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = (int32_t)(read_32bitLE(0x3C,streamFile)/(vgmstream->channels*2)); - vgmstream->interleave_block_size = 0x200; - vgmstream->layout_type = layout_interleave; - vgmstream->meta_type = meta_PS2_OMU; - - vgmstream->loop_start_sample=0; - vgmstream->loop_end_sample=vgmstream->num_samples; - - /* open the file for reading by each channel */ - { - for (i=0;ichannels;i++) { - vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=0x40+(i*vgmstream->interleave_block_size); - } - } - - 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/ps2_mcg.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mcg.c index 0cb4c057c..ba3eaec94 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mcg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mcg.c @@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; int loop_flag = 0; - int channel_count; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -16,31 +16,31 @@ VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile) { /* check header */ if (!((read_32bitBE(0x00,streamFile) == 0x4D434700) && (read_32bitBE(0x20,streamFile) == 0x56414770) && - (read_32bitBE(0x50,streamFile) == 0x56414770))) + (read_32bitBE(0x50,streamFile) == 0x56414770))) goto fail; - loop_flag = (read_32bitLE(0x34,streamFile)!=0); + loop_flag = (read_32bitLE(0x34,streamFile)!=0); 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 */ - start_offset = 0x80; - vgmstream->channels = channel_count; + /* fill in the vital statistics */ + start_offset = 0x80; + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitBE(0x30,streamFile); vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = read_32bitBE(0x2C,streamFile)/16*14*channel_count; + vgmstream->num_samples = read_32bitBE(0x2C,streamFile)/16*14*channel_count; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); vgmstream->meta_type = meta_PS2_MCG; - if (vgmstream->loop_flag) - { - vgmstream->loop_start_sample = read_32bitLE(0x34,streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - } + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x34,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + } /* open the file for reading */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mihb.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mihb.c index b1dcbea6f..826d1d5c4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mihb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mihb.c @@ -6,9 +6,9 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; off_t start_offset; - int mib_blocks; + int mib_blocks; int loop_flag = 0; - int channel_count; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -17,18 +17,18 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) { /* check header */ if (read_32bitBE(0x00,streamFile) != 0x40000000) goto fail; - - mib_blocks = read_32bitLE(0x14,streamFile); + + mib_blocks = read_32bitLE(0x14,streamFile); loop_flag = 0; 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 */ + /* fill in the vital statistics */ start_offset = 0x40; - vgmstream->channels = channel_count; + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); vgmstream->coding_type = coding_PSX; vgmstream->num_samples = ((read_32bitLE(0x10,streamFile))*mib_blocks)*28/16; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c index 5289bdaae..76ec20b2f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c @@ -14,20 +14,20 @@ VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x4E505346) /* "NPSF" */ goto fail; - loop_flag = (read_32bitLE(0x14,streamFile) != 0xFFFFFFFF); + loop_flag = (read_32bitLE(0x14,streamFile) != 0xFFFFFFFF); channel_count = read_32bitLE(0x0C,streamFile); - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - vgmstream->channels = read_32bitLE(0x0C,streamFile); + vgmstream->channels = read_32bitLE(0x0C,streamFile); vgmstream->sample_rate = read_32bitLE(0x18,streamFile); vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); /* single channel data */ - if(vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); - vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); - } + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); + vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); + } vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_pcm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_pcm.c new file mode 100644 index 000000000..07d1fbfc7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_pcm.c @@ -0,0 +1,48 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* .PCM - KCE Japan East PS2 games (Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses, 7 Blades) */ +VGMSTREAM * init_vgmstream_ps2_pcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + + /* check extension */ + if ( !check_extensions(streamFile,"pcm") ) + goto fail; + + /* check header (data_size vs num_samples) */ + if (pcm_bytes_to_samples(read_32bitLE(0x00,streamFile), 2, 16) != read_32bitLE(0x04,streamFile)) + goto fail; + /* should work too */ + //if (read_32bitLE(0x00,streamFile)+0x800 != get_streamfile_size(streamFile)) + // goto fail; + + loop_flag = (read_32bitLE(0x0C,streamFile) != 0x00); + channel_count = 2; + start_offset = 0x800; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->channels = channel_count; + vgmstream->sample_rate = 24000; + vgmstream->num_samples = read_32bitLE(0x04,streamFile); + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile); + + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_PS2_PCM; + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rstm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rstm.c index 3e501c69f..664a24395 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rstm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rstm.c @@ -1,17 +1,15 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* RSTM (from Midnight Club 3, Bully - Canis Canim Edit) */ +/* RSTM - from Rockstar games [Midnight Club 3, Bully - Canis Canim Edit (PS2)] */ VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; - int loop_flag = 0; - int channel_count; + int loop_flag, channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("rstm",filename_extension(filename))) goto fail; + /* check extension (.rsm: in filelist, .rstm: renamed to header id) */ + if ( !check_extensions(streamFile,"rsm,rstm") ) + goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x5253544D) /* "RSTM" */ @@ -19,46 +17,28 @@ VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE *streamFile) { loop_flag = (read_32bitLE(0x24,streamFile)!=0xFFFFFFFF); channel_count = read_32bitLE(0x0C,streamFile); + start_offset = 0x800; /* 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(0x08,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = read_32bitLE(0x20,streamFile)*28/16/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x24,streamFile)*28/16/channel_count; - vgmstream->loop_end_sample = read_32bitLE(0x20,streamFile)*28/16/channel_count; - } + vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x20,streamFile),channel_count); + vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x24,streamFile),channel_count); + vgmstream->loop_end_sample = vgmstream->num_samples; + vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; vgmstream->meta_type = meta_PS2_RSTM; /* 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; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - + 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/ps2_rxws.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxws.c index 01b0ea904..d59062431 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxws.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxws.c @@ -186,30 +186,30 @@ VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile) { /* check RXWS/FORM Header */ if (!((read_32bitBE(0x00,streamFile) == 0x52585753) && - (read_32bitBE(0x10,streamFile) == 0x464F524D))) + (read_32bitBE(0x10,streamFile) == 0x464F524D))) goto fail; - loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF); - channel_count=2; /* Always stereo files */ + loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF); + channel_count=2; /* Always stereo files */ - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = read_32bitLE(0x2E,streamFile); vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2; - /* Get loop point values */ - if(vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14; - vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14; - } + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14; + vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14; + } vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_RXWS; - start_offset = 0x40; + start_offset = 0x40; /* open the file for reading */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_smpl.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_smpl.c index 0c4b76f5f..e44bd7edd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_smpl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_smpl.c @@ -1,63 +1,48 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* SMPL (from Homura) */ +/* SMPL - from Homura (PS2) */ VGMSTREAM * init_vgmstream_ps2_smpl(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int loop_flag, channel_count; + size_t channel_size; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("smpl",filename_extension(filename))) goto fail; + /* check extension (.v0: left channel, .v1: right channel, .smpl: header id) */ + if ( !check_extensions(streamFile,"v0,v1,smpl") ) + goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x534D504C) /* "SMPL" */ goto fail; - loop_flag = 1; channel_count = 1; + loop_flag = (read_32bitLE(0x30,streamFile) != 0); /* .v1 doesn't have loop points */ + start_offset = 0x40; + channel_size = read_32bitBE(0x0c,streamFile) - 0x10; - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x40; - vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitBE(0x10,streamFile); - vgmstream->coding_type = coding_PSX_badflags; - vgmstream->num_samples = read_32bitBE(0xc,streamFile)*56/32; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x30,streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - } - vgmstream->layout_type = layout_none; + vgmstream->num_samples = ps_bytes_to_samples(channel_size*channel_count, channel_count); + vgmstream->loop_start_sample = read_32bitLE(0x30,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + vgmstream->meta_type = meta_PS2_SMPL; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_none; + + /* always, but can be null or used as special string */ + read_string(vgmstream->stream_name,0x10+1, 0x20,streamFile); /* 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; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - + 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/ps2_tk5.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_tk5.c index 631e7f788..bf7efc3a1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_tk5.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_tk5.c @@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; int loop_flag = 0; - int channel_count; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -18,28 +18,28 @@ VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x544B3553) goto fail; - loop_flag = (read_32bitLE(0x0C,streamFile)!=0); + loop_flag = (read_32bitLE(0x0C,streamFile)!=0); 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 */ - start_offset = 0x800; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 48000; + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_PSX_badflags; - vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x800))/16*28/2; + vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x800))/16*28/2; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; vgmstream->meta_type = meta_PS2_TK5; - if (vgmstream->loop_flag) - { - vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; - vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); - } + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; + vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); + } /* open the file for reading */ { @@ -71,7 +71,7 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; int loop_flag = 0; - int channel_count; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -81,28 +81,28 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x544B3553) goto fail; - loop_flag = (read_32bitLE(0x0C,streamFile)!=0); + loop_flag = (read_32bitLE(0x0C,streamFile)!=0); 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 */ - start_offset = 0x800; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; vgmstream->coding_type = coding_PSX_badflags; - vgmstream->num_samples = read_32bitLE(0x08,streamFile)/16*28; + vgmstream->num_samples = read_32bitLE(0x08,streamFile)/16*28; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; vgmstream->meta_type = meta_PS2_TK1; - if (vgmstream->loop_flag) - { - vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; - vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); - } + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; + vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); + } /* open the file for reading */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c index 96f9552d7..9af6a79e1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c @@ -17,8 +17,8 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { int channel_count = 0; int is_swag = 0; - /* check extension, case insensitive */ - if ( !check_extensions(streamFile,"vag,swag,str") ) + /* check extension (.swag: Frantix PSP, .str: Ben10 Galactic Racing, .vig: MX vs. ATV Untamed PS2) */ + if ( !check_extensions(streamFile,"vag,swag,str,vig") ) goto fail; /* check VAG Header */ @@ -63,7 +63,11 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { break; case 'p': /* "VAGp" (extended) [most common, ex Ratchet & Clank] */ - if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */ + if (check_extensions(streamFile,"vig")) { /* MX vs. ATV Untamed PS2 */ + channel_count = 2; /* normal interleave */ + loop_flag = 0; + } + else if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */ channel_count = 2; /* The Simpsons Wrestling PSX interleave */ loop_flag = 0; } @@ -79,13 +83,16 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { /* channels are usually at 0x1e, but not in Ukiyo no Roushi which has some kind * of loop-like values instead (who designs this crap?) */ - if (read_32bitBE(0x18,streamFile) != 0 || read_32bitBE(0x1c,streamFile) > 0x20) { - channel_count = 1; - } else { + if (read_32bitBE(0x18,streamFile) == 0 + && (read_32bitBE(0x1c,streamFile) & 0xFFFF00FF) == 0 + && read_8bit(0x1e,streamFile) < 16) { channel_count = read_8bit(0x1e,streamFile); if (channel_count == 0) channel_count = 1; /* ex. early Vita vag (Lumines) */ } + else { + channel_count = 1; + } } else { loop_flag = vag_find_loop_offsets(streamFile, 0x30, &loopStart, &loopEnd); @@ -133,7 +140,14 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { case 'p': // VAGp interleave=0x10; - if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */ + if (check_extensions(streamFile,"vig")) { /* MX vs. ATV Untamed PS2 */ + vgmstream->layout_type=layout_interleave; + vgmstream->meta_type=meta_PS2_VAGp; + + vgmstream->num_samples = (datasize - 0x10*channel_count) / 16 * 28; + start_offset = 0x800; + } + else if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* interleaved "VAGp" */ interleave = 0x6000; /* The Simpsons Wrestling PSX interleave, includes header */ vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_VAGs; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgs.c index 8196aa174..ea19558e3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgs.c @@ -9,15 +9,15 @@ VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - size_t fileLength; - off_t readOffset = 0; - off_t start_offset; - off_t loop_start_offset = 0; - off_t loop_end_offset = 0; + size_t fileLength; + off_t readOffset = 0; + off_t start_offset; + off_t loop_start_offset = 0; + off_t loop_end_offset = 0; - uint8_t testBuffer[0x10]; - int loop_flag = 0; - int channel_count; + uint8_t testBuffer[0x10]; + int loop_flag = 0; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -27,71 +27,71 @@ VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x56475300) goto fail; - // get file length - fileLength = get_streamfile_size(streamFile); + // get file length + fileLength = get_streamfile_size(streamFile); - // Find loop start - do { - readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); - - // Loop Start ... - if(testBuffer[0x01] == 0x06) - { - loop_start_offset = readOffset - 0x10; - break; - } + // Find loop start + do { + readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); - } while (streamFile->get_offset(streamFile)<((int32_t)fileLength)); + // Loop Start ... + if(testBuffer[0x01] == 0x06) + { + loop_start_offset = readOffset - 0x10; + break; + } - // start at last line of file and move up - readOffset = (int32_t)fileLength - 0x10; - - // Find loop end - do { - readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); - - // Loop End ... - if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) - { - loop_end_offset = readOffset + 0x20; - break; - } - } while (readOffset > 0); + } while (streamFile->get_offset(streamFile)<((int32_t)fileLength)); - // setup loops - if (loop_start_offset > 0) - { - loop_flag = 1; - - // if we have a start loop, use EOF if end loop is not found - if (loop_end_offset == 0) - { - loop_end_offset = (int32_t)fileLength - 0x10; - } - } - else - { - loop_flag = 0; - } + // start at last line of file and move up + readOffset = (int32_t)fileLength - 0x10; + + // Find loop end + do { + readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + + // Loop End ... + if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) + { + loop_end_offset = readOffset + 0x20; + break; + } + } while (readOffset > 0); + + // setup loops + if (loop_start_offset > 0) + { + loop_flag = 1; + + // if we have a start loop, use EOF if end loop is not found + if (loop_end_offset == 0) + { + loop_end_offset = (int32_t)fileLength - 0x10; + } + } + else + { + loop_flag = 0; + } 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 */ - start_offset = 0x30; - vgmstream->channels = channel_count; + /* fill in the vital statistics */ + start_offset = 0x30; + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitBE(0x10,streamFile); vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x30)/16/channel_count*28); + vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x30)/16/channel_count*28); - if (loop_flag) - { - vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28; - vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28; - } + if (loop_flag) + { + vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28; + vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28; + } vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile)*0x1000; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vms.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vms.c index fb11ad7ce..274047fa8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vms.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vms.c @@ -7,9 +7,9 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; - int loop_flag = 0; - int channel_count; - int header_size; + int loop_flag = 0; + int channel_count; + int header_size; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -19,27 +19,27 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x564D5320) goto fail; - loop_flag = 1; - channel_count = read_8bit(0x08,streamFile); - header_size = read_32bitLE(0x1C, streamFile); + loop_flag = 1; + channel_count = read_8bit(0x08,streamFile); + header_size = read_32bitLE(0x1C, 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 = header_size; - - vgmstream->channels = channel_count; + /* fill in the vital statistics */ + start_offset = header_size; + + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitLE(0x14,streamFile); vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = ((get_streamfile_size(streamFile) - header_size)/16/ channel_count * 28); + vgmstream->num_samples = ((get_streamfile_size(streamFile) - header_size)/16/ channel_count * 28); vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); - vgmstream->meta_type = meta_PS2_VMS; - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (get_streamfile_size(streamFile))/16/ channel_count * 28; + vgmstream->meta_type = meta_PS2_VMS; + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile))/16/ channel_count * 28; /* open the file for reading */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vpk.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vpk.c index 4fc58fc4d..2f1622b36 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vpk.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vpk.c @@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; int loop_flag=0; - int channel_count; + int channel_count; off_t start_offset; int i; @@ -20,33 +20,33 @@ VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x204B5056) goto fail; - /* check loop */ - loop_flag = (read_32bitLE(0x7FC,streamFile)!=0); + /* check loop */ + loop_flag = (read_32bitLE(0x7FC,streamFile)!=0); channel_count=read_32bitLE(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 = read_32bitLE(0x14,streamFile); + /* fill in the vital statistics */ + vgmstream->channels = read_32bitLE(0x14,streamFile); vgmstream->sample_rate = read_32bitLE(0x10,streamFile); - /* Check for Compression Scheme */ - vgmstream->coding_type = coding_PSX; + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28; - /* Get loop point values */ - if(vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x7FC,streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - } + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x7FC,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + } - vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile)/2; + vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile)/2; vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_VPK; - start_offset = (off_t)read_32bitLE(0x08,streamFile); + start_offset = (off_t)read_32bitLE(0x08,streamFile); /* open the file for reading by each channel */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2.c index a16d380e9..ffad6f751 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2.c @@ -58,61 +58,3 @@ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; } - - -/* XA2 (RC Revenge Pro) */ -VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xa2",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0xC,streamFile) != 0x00000000) - goto fail; - - loop_flag = 0; - channel_count = read_32bitLE(0x0,streamFile); - - /* 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 = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x1000; - vgmstream->meta_type = meta_PS2_XA2_RRP; - - /* 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; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - return vgmstream; - -fail: - /* clean up anything we may have opened */ - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2_rrp.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2_rrp.c new file mode 100644 index 000000000..2eff2f3ad --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2_rrp.c @@ -0,0 +1,59 @@ +#include "meta.h" + + +/* XA2 (RC Revenge Pro) */ +VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xa2",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0xC,streamFile) != 0x00000000) + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x0,streamFile); + + /* 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 = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1000; + vgmstream->meta_type = meta_PS2_XA2_RRP; + + /* 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; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_ivag.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_ivag.c index 0f3fa2c5f..1348cced5 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_ivag.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_ivag.c @@ -2,19 +2,19 @@ #include "../util.h" /* IVAG - - The Idolm@ster: Gravure For You! Vol. 3 (PS3) + - The Idolm@ster: Gravure For You! Vol. 3 (PS3) - Appears to be two VAGp streams interleaved. + Appears to be two VAGp streams interleaved. */ VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - off_t start_offset; + off_t start_offset; - int loop_flag = 0; - int channel_count; + int loop_flag = 0; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -24,34 +24,34 @@ VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile) if (read_32bitBE(0x00,streamFile) != 0x49564147) // "IVAG" goto fail; - // channel count - channel_count = read_32bitBE(0x08, streamFile); + // channel count + channel_count = read_32bitBE(0x08, streamFile); - // header size - start_offset = 0x40 + (0x40 * channel_count); + // header size + start_offset = 0x40 + (0x40 * channel_count); - // loop flag - if ((read_32bitBE(0x14, streamFile) != 0 || - (read_32bitBE(0x18, streamFile) != 0))) - { - loop_flag = 1; - } + // loop flag + if ((read_32bitBE(0x14, streamFile) != 0 || + (read_32bitBE(0x18, streamFile) != 0))) + { + loop_flag = 1; + } - /* 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; + /* fill in the vital statistics */ + vgmstream->channels = channel_count; vgmstream->sample_rate = read_32bitBE(0x0C,streamFile); vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = read_32bitBE(0x10,streamFile); + vgmstream->num_samples = read_32bitBE(0x10,streamFile); - if (loop_flag) - { - vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); - } + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); + } vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitBE(0x1C,streamFile); @@ -64,15 +64,15 @@ VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile) file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!file) goto fail; - for (i=0;ich[i].streamfile = file; vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i); } - + } return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c index 0951945bb..272c5c53d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c @@ -7,15 +7,15 @@ VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE *streamFile) VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - size_t fileLength; - off_t readOffset = 0; - off_t start_offset; - off_t loop_start_offset = 0; - off_t loop_end_offset = 0; + size_t fileLength; + off_t readOffset = 0; + off_t start_offset; + off_t loop_start_offset = 0; + off_t loop_end_offset = 0; - uint8_t testBuffer[0x10]; - int loop_flag = 0; - int channel_count; + uint8_t testBuffer[0x10]; + int loop_flag = 0; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -25,77 +25,77 @@ VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE *streamFile) if (read_32bitBE(0x20,streamFile) != 0x6B6C4253) goto fail; - // get file length - fileLength = get_streamfile_size(streamFile); + // get file length + fileLength = get_streamfile_size(streamFile); - // Find loop start - start_offset = read_32bitBE(0x10,streamFile); - readOffset = start_offset; + // Find loop start + start_offset = read_32bitBE(0x10,streamFile); + readOffset = start_offset; - do { - readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); - - // Loop Start ... - if(testBuffer[0x01] == 0x06) - { - loop_start_offset = readOffset - 0x10; - break; - } + do { + readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); - } while (streamFile->get_offset(streamFile)<((int32_t)fileLength)); + // Loop Start ... + if(testBuffer[0x01] == 0x06) + { + loop_start_offset = readOffset - 0x10; + break; + } - // start at last line of file and move up - readOffset = (int32_t)fileLength - 0x10; - - // Find loop end - do { - readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); - - // Loop End ... - if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) - { - loop_end_offset = readOffset + 0x20; - break; - } - } while (readOffset > 0); + } while (streamFile->get_offset(streamFile)<((int32_t)fileLength)); - // setup loops - if (loop_start_offset > 0) - { - loop_flag = 1; - - // if we have a start loop, use EOF if end loop is not found - if (loop_end_offset == 0) - { - loop_end_offset = (int32_t)fileLength - 0x10; - } - } - else - { - loop_flag = 0; - } + // start at last line of file and move up + readOffset = (int32_t)fileLength - 0x10; + + // Find loop end + do { + readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + + // Loop End ... + if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) + { + loop_end_offset = readOffset + 0x20; + break; + } + } while (readOffset > 0); + + // setup loops + if (loop_start_offset > 0) + { + loop_flag = 1; + + // if we have a start loop, use EOF if end loop is not found + if (loop_end_offset == 0) + { + loop_end_offset = (int32_t)fileLength - 0x10; + } + } + else + { + loop_flag = 0; + } 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 */ + /* fill in the vital statistics */ vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = read_32bitBE(0x90, streamFile); vgmstream->meta_type = meta_PS3_KLBS; - vgmstream->channels = channel_count; + vgmstream->channels = channel_count; vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = ((vgmstream->interleave_block_size * channel_count)/16/channel_count*28); + vgmstream->num_samples = ((vgmstream->interleave_block_size * channel_count)/16/channel_count*28); - if (loop_flag) - { - vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28; - vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28; - } + if (loop_flag) + { + vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28; + vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28; + } /* open the file for reading */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c index 86f3fb6e5..2d3e4e72d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c @@ -11,8 +11,8 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { int loop_flag = 0, channel_count; - /* check extension, case insensitive */ - if (!check_extensions(streamFile,"msf,at3")) goto fail; /* .at3: Silent Hill HD Collection */ + /* check extension, case insensitive (.at3: Silent Hill HD Collection, .mp3: Darkstalkers Resurrection) */ + if (!check_extensions(streamFile,"msf,at3,mp3")) goto fail; /* "WMSF" variation with a mini header over the MSFC header, same extension */ if (read_32bitBE(0x00,streamFile) == 0x574D5346) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c index c2aeb8373..6e612c09a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c @@ -1,135 +1,118 @@ #include "meta.h" #include "../layout/layout.h" -#include "../util.h" - -/* Sony PSX CD-XA */ -/* No looped file ! */ - -off_t init_xa_channel(int *channel,STREAMFILE *streamFile); - -uint8_t AUDIO_CODING_GET_STEREO(uint8_t value) { - return (uint8_t)(value & 3); -} - -uint8_t AUDIO_CODING_GET_FREQ(uint8_t value) { - return (uint8_t)((value >> 2) & 3); -} +#include "../coding/coding.h" +/* CD-XA - from Sony PS1 CDs */ VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0, channel_count, sample_rate; + int xa_channel=0; + int is_blocked; + size_t file_size = get_streamfile_size(streamFile); - int channel_count; - int headerless=0; - int xa_channel=0; - uint8_t bCoding; - off_t start_offset; + /* check extension (.xa: common, .str: sometimes used) */ + if ( !check_extensions(streamFile,"xa,str") ) + goto fail; - int i; + /* Proper XA comes in raw (BIN 2352 mode2/form2) CD sectors, that contain XA subheaders. + * This also has minimal support for headerless (ISO 2048 mode1/data) mode. */ - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xa",filename_extension(filename))) goto fail; + /* check RIFF header = raw (optional, added when ripping and not part of the CD data) */ + if (read_32bitBE(0x00,streamFile) == 0x52494646 && /* "RIFF" */ + read_32bitBE(0x08,streamFile) == 0x43445841 && /* "CDXA" */ + read_32bitBE(0x0C,streamFile) == 0x666D7420) { /* "fmt " */ + is_blocked = 1; + start_offset = 0x2c; /* after "data" (chunk size tends to be a bit off) */ + } + else { + /* sector sync word = raw */ + if (read_32bitBE(0x00,streamFile) == 0x00FFFFFF && + read_32bitBE(0x04,streamFile) == 0xFFFFFFFF && + read_32bitBE(0x08,streamFile) == 0xFFFFFF00) { + is_blocked = 1; + start_offset = 0x00; + } + else { /* headerless */ + is_blocked = 0; + start_offset = 0x00; + } + } - /* check RIFF Header */ - if (!((read_32bitBE(0x00,streamFile) == 0x52494646) && - (read_32bitBE(0x08,streamFile) == 0x43445841) && - (read_32bitBE(0x0C,streamFile) == 0x666D7420))) - headerless=1; + /* test first block (except when RIFF) */ + if (start_offset == 0) { + int i, j; - /* don't misdetect Reflections' XA ("XA30" / "04SW") */ - if (read_32bitBE(0x00,streamFile) == 0x58413330 || read_32bitBE(0x00,streamFile) == 0x30345357) goto fail; - /* don't misdetect Maxis XA ("XAI\0" / "XAJ\0") */ - if (read_32bitBE(0x00,streamFile) == 0x58414900 || read_32bitBE(0x00,streamFile) == 0x58414A00) goto fail; + /* 0x80 frames for 1 sector (max ~0x800 for ISO mode) */ + for (i = 0; i < (0x800/0x80); i++) { + off_t test_offset = start_offset + (is_blocked ? 0x18 : 0x00) + 0x80*i; - /* First init to have the correct info of the channel */ - if (!headerless) { - start_offset=init_xa_channel(&xa_channel,streamFile); + /* ADPCM predictors should be 0..3 index */ + for (j = 0; j < 16; j++) { + uint8_t header = read_8bit(test_offset + i, streamFile); + if (((header >> 4) & 0xF) > 3) + goto fail; + } + } + } - /* No sound ? */ - if(start_offset==0) - goto fail; - bCoding = read_8bit(start_offset-5,streamFile); + /* data is ok: parse header */ + if (is_blocked) { + uint8_t xa_header; - switch (AUDIO_CODING_GET_STEREO(bCoding)) { - case 0: channel_count = 1; break; - case 1: channel_count = 2; break; - default: channel_count = 0; break; - } + /* parse 0x18 sector header (also see xa_blocked.c) */ + xa_channel = read_8bit(start_offset + 0x11,streamFile); + xa_header = read_8bit(start_offset + 0x13,streamFile); - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,0); - if (!vgmstream) goto fail; + switch((xa_header >> 0) & 3) { /* 0..1: stereo */ + case 0: channel_count = 1; break; + case 1: channel_count = 2; break; + default: goto fail; + } + switch((xa_header >> 2) & 3) { /* 2..3: sample rate */ + case 0: sample_rate = 37800; break; + case 1: sample_rate = 18900; break; + default: goto fail; + } + VGM_ASSERT(((xa_header >> 4) & 3) == 1, /* 4..5: bits per sample (0=4, 1=8) */ + "XA: 8 bits per sample mode found\n"); /* spec only? */ + /* 6: emphasis (applies a filter but apparently not used by games) + * XA is also filtered when resampled to 44100 during output, differently from PS-ADPCM */ + /* 7: reserved */ + } + else { + /* headerless, probably will go wrong */ + channel_count = 2; + sample_rate = 44100; /* not 37800? */ + } - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->xa_channel = xa_channel; - switch (AUDIO_CODING_GET_FREQ(bCoding)) { - case 0: vgmstream->sample_rate = 37800; break; - case 1: vgmstream->sample_rate = 18900; break; - default: vgmstream->sample_rate = 0; break; - } + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; - /* Check for Compression Scheme */ - vgmstream->num_samples = (int32_t)((((get_streamfile_size(streamFile) - 0x3C)/2352)*0x1F80)/(2*channel_count)); - } else - { - channel_count=2; - vgmstream = allocate_vgmstream(2,0); - if (!vgmstream) goto fail; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = xa_bytes_to_samples(file_size - start_offset, channel_count, is_blocked); + vgmstream->xa_headerless = !is_blocked; + vgmstream->xa_channel = xa_channel; - vgmstream->xa_headerless=1; - vgmstream->sample_rate=44100; - vgmstream->channels=2; - vgmstream->num_samples = (int32_t)(((get_streamfile_size(streamFile)/ 0x80)*0xE0)/2); - start_offset=0; - } - - vgmstream->coding_type = coding_XA; + vgmstream->coding_type = coding_XA; vgmstream->layout_type = layout_xa_blocked; vgmstream->meta_type = meta_PSX_XA; - /* open the file for reading by each channel */ - { - STREAMFILE *chstreamfile; - chstreamfile = streamFile->open(streamFile,filename,2352); + if (is_blocked) + start_offset += 0x18; /* move to first frame (hack for xa_blocked.c) */ - if (!chstreamfile) goto fail; + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; - for (i=0;ich[i].streamfile = chstreamfile; - } - } - - xa_block_update(start_offset,vgmstream); + xa_block_update(start_offset,vgmstream); - return vgmstream; + return vgmstream; - /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; } - -off_t init_xa_channel(int* channel,STREAMFILE* streamFile) { - - off_t block_offset=0x44; - size_t filelength=get_streamfile_size(streamFile); - - int8_t currentChannel; - - // 0 can't be a correct value - if(block_offset>=(off_t)filelength) - return 0; - - currentChannel=read_8bit(block_offset-7,streamFile); - //subAudio=read_8bit(block_offset-6,streamFile); - *channel=currentChannel; - //if (!((currentChannel==channel) && (subAudio==0x64))) { - // block_offset+=2352; - // goto begin; - //} - return block_offset; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c index d58a8c6b3..e49344291 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c @@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; int loop_flag = 0; - int channel_count; + int channel_count; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -15,27 +15,27 @@ VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE *streamFile) { /* check header */ - /* Look if there's more than 1 one file... */ + /* Look if there's more than 1 one file... */ if (read_32bitBE(0x00,streamFile) != 0x01000000) goto fail; - loop_flag = 0; + loop_flag = 0; 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 */ - start_offset = read_32bitLE(0x04,streamFile); - vgmstream->channels = channel_count; + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x04,streamFile); + vgmstream->channels = channel_count; vgmstream->sample_rate = 24000; vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/32*28; + vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/32*28; if (loop_flag) { vgmstream->loop_start_sample = 0; vgmstream->loop_end_sample = (read_32bitLE(0x08,streamFile))/channel_count/32*28; - } + } vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x8000; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index e3933e4f9..c7c4265b3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -7,7 +7,7 @@ /* Resource Interchange File Format */ /* return milliseconds */ -long parse_marker(unsigned char * marker) { +static long parse_marker(unsigned char * marker) { long hh,mm,ss,ms; if (memcmp("Marker ",marker,7)) return -1; @@ -18,8 +18,7 @@ long parse_marker(unsigned char * marker) { } /* loop points have been found hiding here */ -void parse_adtl(off_t adtl_offset, off_t adtl_length, STREAMFILE *streamFile, - long *loop_start, long *loop_end, int *loop_flag) { +static void parse_adtl(off_t adtl_offset, off_t adtl_length, STREAMFILE *streamFile, long *loop_start, long *loop_end, int *loop_flag) { int loop_start_found = 0; int loop_end_found = 0; @@ -92,12 +91,7 @@ struct riff_fmt_chunk { int interleave; }; -int read_fmt(int big_endian, - STREAMFILE * streamFile, - off_t current_chunk, - struct riff_fmt_chunk * fmt, - int sns, - int mwv) { +static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk, struct riff_fmt_chunk * fmt, int sns, int mwv) { int codec, bps; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; @@ -262,25 +256,32 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("wav",filename_extension(filename)) && - strcasecmp("lwav",filename_extension(filename)) && - strcasecmp("da",filename_extension(filename)) /* SD Gundam - Over Galaxian, The Great Battle VI (PS) */ + if (strcasecmp("wav",filename_extension(filename)) + && strcasecmp("lwav",filename_extension(filename)) + && strcasecmp("da",filename_extension(filename)) /* SD Gundam - Over Galaxian, The Great Battle VI (PS) */ + && strcasecmp("cd",filename_extension(filename)) /* Exector (PS) */ #ifndef VGM_USE_FFMPEG - && strcasecmp("sgb",filename_extension(filename)) /* SGB has proper support with FFmpeg in sgxd */ + && strcasecmp("sgb",filename_extension(filename)) /* SGB has proper support with FFmpeg in sgxd */ #endif - && strcasecmp("med",filename_extension(filename)) + && strcasecmp("med",filename_extension(filename)) ) { - if (!strcasecmp("mwv",filename_extension(filename))) + if (!strcasecmp("mwv",filename_extension(filename))) { mwv = 1; - else if (!strcasecmp("sns",filename_extension(filename))) + } + else if (!strcasecmp("sns",filename_extension(filename))) { sns = 1; + } #if defined(VGM_USE_MAIATRAC3PLUS) || defined(VGM_USE_FFMPEG) - else if ( check_extensions(streamFile, "at3,rws") ) /* Renamed .RWS AT3 found in Climax games (Silent Hill Origins PSP, Oblivion PSP) */ + /* .RWS: AT3 found in Climax games (Silent Hill Origins PSP, Oblivion PSP) + * .AUD: EA Replay */ + else if ( check_extensions(streamFile, "at3,rws,aud") ) { at3 = 1; + } #endif - else + else { goto fail; + } } /* check header */ @@ -403,7 +404,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { * (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)) goto fail; + && (fmt.coding_type==coding_MSADPCM || fmt.coding_type==coding_MS_IMA)) + goto fail; + switch (fmt.coding_type) { case coding_PCM16LE: @@ -730,6 +733,7 @@ VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) { break; case 0x4A554E4B: /* JUNK */ JunkFound = 1; + break; default: /* ignorance is bliss */ break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c index e1aa3cc74..34d041569 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c @@ -888,15 +888,12 @@ fail: /* RSD6WADP */ VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; - - int loop_flag; - int channel_count; + int loop_flag, channel_count; /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("rsd",filename_extension(filename))) goto fail; + if (!check_extensions(streamFile,"rsd")) + goto fail; /* check header */ if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ @@ -906,54 +903,25 @@ VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE *streamFile) { loop_flag = 0; channel_count = read_32bitLE(0x8,streamFile); + start_offset = 0x800; /* 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_NGC_DSP; vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = loop_flag; - vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; - } - vgmstream->layout_type = layout_interleave_byte; //layout_interleave; - vgmstream->interleave_block_size = 2; //read_32bitLE(0xC,streamFile); + vgmstream->coding_type = coding_NGC_DSP_subint; + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x02; //read_32bitLE(0xC,streamFile); vgmstream->meta_type = meta_RSD6WADP; - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1A4+i*2,streamFile); - } - if (vgmstream->channels) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x1CC+i*2,streamFile); - } - } - } - /* 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; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - - } + dsp_read_coefs_be(vgmstream,streamFile,0x1a4,0x28); + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; return vgmstream; fail: @@ -1158,6 +1126,8 @@ VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile) { #endif break; } + default: + goto fail; } /* open the file for reading */ if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c index 7192d229f..44cb6a508 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c @@ -245,7 +245,7 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) { coding_type = coding_NGC_DSP; break; case 3: - coding_type = coding_IMA; + coding_type = coding_3DS_IMA; break; default: goto fail; @@ -343,7 +343,7 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) { } } - if (vgmstream->coding_type == coding_IMA) { + if (vgmstream->coding_type == coding_3DS_IMA) { vgmstream->ch[j].adpcm_history1_16 = read_16bit(codec_info_offset,streamFile); vgmstream->ch[j].adpcm_step_index = read_16bit(codec_info_offset+2,streamFile); } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/s14_sss.c b/Frameworks/vgmstream/vgmstream/src/meta/s14_sss.c index e85db9814..e1aed3303 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/s14_sss.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/s14_sss.c @@ -1,105 +1,66 @@ -#include "../vgmstream.h" - -#ifdef VGM_USE_G7221 - #include "meta.h" #include "../util.h" #include "../coding/coding.h" +#include -/* .s14 and .sss - from Idolm@ster DS (and others?) - * Raw 24kbit Siren 14 stream, s14 is mono and sss is - * frame-interleaved stereo - */ - +/* .s14 and .sss - headerless siren14 stream (The Idolm@ster DS, Korogashi Puzzle Katamari Damacy DS) */ VGMSTREAM * init_vgmstream_s14_sss(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int channel_count; + off_t start_offset = 0; + int channel_count, loop_flag = 0, interleave; - size_t file_size; - /* check extension, case insensitive */ - /* this is all we have to go on, rsf is completely headerless */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (!strcasecmp("sss",filename_extension(filename))) - { + /* check extension */ + if (check_extensions(streamFile,"sss")) { channel_count = 2; - } - else if (!strcasecmp("s14",filename_extension(filename))) - { - channel_count = 1; - } - else - { + } else if (check_extensions(streamFile,"s14")) { + channel_count = 1; //todo missing dual _0ch.s14 _1ch.s14, but dual_ext thing doesn't work properly with siren14 decoder + } else { goto fail; } - file_size = get_streamfile_size(streamFile); + /* raw siren comes in 3 frame sizes, try to guess the correct one + * (should try to decode and check the error flag but it isn't currently reported) */ + { + char filename[PATH_LIMIT]; + streamFile->get_name(streamFile,filename,sizeof(filename)); + + /* horrid but I ain't losing sleep over it (besides the header must be somewhere as some tracks loop) */ + if (strstr(filename,"S037")==filename || strstr(filename,"b06")==filename) /* Korogashi Puzzle Katamari Damacy */ + interleave = 0x78; + else if (strstr(filename,"32700")==filename || /* Hottarake no Shima - Kanata to Nijiiro no Kagami */ + (strstr(filename,"b0")==filename || strstr(filename,"puzzle")==filename || strstr(filename,"M09")==filename) ) /* Korogashi Puzzle Katamari Damacy */ + interleave = 0x50; + else + interleave = 0x3c; /* The Idolm@ster - Dearly Stars */ + } + /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count,0); + vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; + vgmstream->num_samples = get_streamfile_size(streamFile) / (interleave * channel_count) * (32000/50); + vgmstream->sample_rate = 32768; /* maybe 32700? */ - /* fill in the vital statistics */ - vgmstream->num_samples = file_size/0x3c/channel_count*(32000/50); - vgmstream->sample_rate = 32768; - - vgmstream->coding_type = coding_G7221C; + vgmstream->meta_type = channel_count==1 ? meta_S14 : meta_SSS; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x3c; - if (1 == channel_count) - { - vgmstream->meta_type = meta_S14; - } - else - { - vgmstream->meta_type = meta_SSS; - } + vgmstream->interleave_block_size = interleave; { - int i; - g7221_codec_data *data; - - /* one data structure per channel */ - data = malloc(sizeof(g7221_codec_data) * channel_count); - if (!data) - { - goto fail; - } - memset(data,0,sizeof(g7221_codec_data) * channel_count); - vgmstream->codec_data = data; - - for (i = 0; i < channel_count; i++) - { - /* Siren 14 == 14khz bandwidth */ - data[i].handle = g7221_init(vgmstream->interleave_block_size, 14000); - if (!data[i].handle) - { - goto fail; /* close_vgmstream is able to clean up */ - } - } - } - - /* open the file for reading by each channel */ - { - int i; - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=0x3c*i; - } +#ifdef VGM_USE_G7221 + vgmstream->coding_type = coding_G7221C; + vgmstream->codec_data = init_g7221(vgmstream->channels, vgmstream->interleave_block_size); + if (!vgmstream->codec_data) goto fail; +#else + goto fail; +#endif } + 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; } - -#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sab.c b/Frameworks/vgmstream/vgmstream/src/meta/sab.c new file mode 100644 index 000000000..450fd8d4b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sab.c @@ -0,0 +1,157 @@ +#include "meta.h" +#include "../util.h" +#include "../coding/coding.h" + +static void get_stream_name(char * stream_name, STREAMFILE *streamFile, int target_stream); + +/* SAB - from Worms 4: Mayhem (PC/Xbox/PS2) */ +VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count = 0, is_stream, align, codec, sample_rate, data_size, loop_start, loop_end; + int total_streams, target_stream = streamFile->stream_index; + + /* .sab: main, .sob: config/names */ + if (!check_extensions(streamFile,"sab")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x43535732 && /* "CSW2" (Windows) */ + read_32bitBE(0x00,streamFile) != 0x43535032 && /* "CSP2" (PS2) */ + read_32bitBE(0x00,streamFile) != 0x43535832) /* "CSX2" (Xbox) */ + goto fail; + + is_stream = read_32bitLE(0x04,streamFile) & 0x04; /* other flags don't seem to matter */ + total_streams = is_stream ? 1 : read_32bitLE(0x08,streamFile); + if (target_stream == 0) target_stream = 1; + if (target_stream < 0 || target_stream > total_streams || total_streams < 1) goto fail; + + align = read_32bitLE(0x0c,streamFile); /* doubles as interleave */ + + /* stream config */ + codec = read_32bitLE(0x18 + 0x1c*(target_stream-1) + 0x00,streamFile); + channel_count = read_32bitLE(0x18 + 0x1c*(target_stream-1) + 0x04,streamFile); + sample_rate = read_32bitLE(0x18 + 0x1c*(target_stream-1) + 0x08,streamFile); + data_size = read_32bitLE(0x18 + 0x1c*(target_stream-1) + 0x0c,streamFile); + loop_start = read_32bitLE(0x18 + 0x1c*(target_stream-1) + 0x10,streamFile); + loop_end = read_32bitLE(0x18 + 0x1c*(target_stream-1) + 0x14,streamFile); + loop_flag = (loop_end > 0); + + start_offset = 0x18 + 0x1c*total_streams; + if (start_offset % align) + start_offset += align - (start_offset % align); + start_offset += read_32bitLE(0x18 + 0x1c*(target_stream-1) + 0x18,streamFile); + + if (is_stream) { + channel_count = read_32bitLE(0x08,streamFile); /* uncommon, but non-stream stereo exists */ + data_size *= channel_count; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + + vgmstream->num_streams = total_streams; + vgmstream->meta_type = meta_SAB; + + switch(codec) { + case 0x01: + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = is_stream ? align : 0x02; + + vgmstream->num_samples = pcm_bytes_to_samples(data_size, vgmstream->channels, 16); + vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, vgmstream->channels, 16); + vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, vgmstream->channels, 16); + + break; + + case 0x04: + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = is_stream ? align : 0x10; + + vgmstream->num_samples = ps_bytes_to_samples(data_size, vgmstream->channels); + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, vgmstream->channels); + 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; + 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(data_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); + break; + + default: + VGM_LOG("SAB: unknown codec\n"); + goto fail; + } + + get_stream_name(vgmstream->stream_name, streamFile, target_stream); + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* multiple streams may share a name, also sometimes won't a the name */ +static void get_stream_name(char * stream_name, STREAMFILE *streamFile, int target_stream) { + STREAMFILE * streamInfo = NULL; + int i, j, total_cues, num_cue = -1; + size_t name_size = 0; + off_t name_offset = 0x10; + + streamInfo = open_stream_ext(streamFile, "sob"); + if (!streamInfo) goto end; + if (read_32bitBE(0x00,streamInfo) != 0x43544632) /* "CTF2" */ + goto end; + + total_cues = read_32bitLE(0x08,streamInfo); + + for (i = 0; i < total_cues; i++) { + uint32_t flags, num_subsections, subsection_1_size, subsection_2_size; + + flags = (uint32_t)read_32bitLE(name_offset + 0x00,streamInfo); + num_subsections = (uint32_t)read_32bitLE(name_offset + 0x20,streamInfo); + subsection_1_size = (flags & 0x00000001) ? 0x40 : 0x00; + subsection_1_size +=(flags & 0x00000040) ? 0x20 : 0x00; + subsection_2_size = (flags & 0x00000100) ? 0x1c : 0x10; + + for (j = 0; j < num_subsections; j++) { + int num_stream = read_32bitLE(name_offset + 0x2c + subsection_1_size + j*subsection_2_size + 0x08,streamInfo); + if (target_stream-1 == num_stream) + num_cue = i; + } + + name_offset += 0x2c + subsection_1_size + subsection_2_size * num_subsections; + } + if (num_cue < 0) + goto end; + + for (i = 0; i < total_cues; i++) { + /* 0x00: id */ + name_size = read_32bitLE(name_offset + 0x04,streamInfo); /* non null-terminated */ + if (i == num_cue) { + name_offset += 0x08; + break; + } + name_offset += 0x08 + name_size; + } + + if (name_size > STREAM_NAME_SIZE-1) + name_size = STREAM_NAME_SIZE-1; + + read_string(stream_name,name_size+1, name_offset,streamInfo); + +end: + if (streamInfo) + close_streamfile(streamInfo); +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c b/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c index 4c5f45291..68a483d24 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c @@ -1,67 +1,54 @@ #include "meta.h" -#include "../util.h" -/* DVI (Castlevania Symphony of the Night) */ -VGMSTREAM * init_vgmstream_dvi(STREAMFILE *streamFile) { +/* DVI - from Konami KCE Nayoga SAT games (Castlevania Symphony of the Night, Jikkyou Oshaberi Parodius - Forever with Me) */ +VGMSTREAM * init_vgmstream_sat_dvi(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; + int loop_flag, channel_count; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("dvi",filename_extension(filename))) goto fail; + /* check extension (.pcm: original, .dvi: renamed to header id) */ + if ( !check_extensions(streamFile,"pcm,dvi") ) + goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x4456492E) /* "DVI." */ goto fail; - loop_flag = (read_32bitBE(0x0C,streamFile)!=0xFFFFFFFF); - channel_count = 2; - - /* build the VGMSTREAM */ + start_offset = read_32bitBE(0x04,streamFile); + loop_flag = (read_32bitBE(0x0C,streamFile) != 0xFFFFFFFF); + channel_count = 2; /* no mono files seem to exists */ + + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - start_offset = read_32bitBE(0x04,streamFile); vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_DVI_IMA_int; - vgmstream->num_samples = read_32bitBE(0x08,streamFile); - - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0x08,streamFile); - } + vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x08,streamFile); + vgmstream->coding_type = coding_DVI_IMA_int; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 4; - vgmstream->meta_type = meta_DVI; - vgmstream->get_high_nibble=1; + vgmstream->interleave_block_size = 0x4; + vgmstream->meta_type = meta_SAT_DVI; + /* at 0x10 (L) / 0x20 (R): probably ADPCM loop history @+0x00 and step @+0x17 (not init values) */ - /* 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; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+(i*vgmstream->interleave_block_size); - vgmstream->ch[i].adpcm_history1_32=0; - vgmstream->ch[i].adpcm_step_index=0; - } + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + + /* for some reason right channel goes first (tested in SOTN vs emu and PS/OST version), swap offsets */ + if (channel_count == 2) { + off_t temp = vgmstream->ch[0].offset; + vgmstream->ch[0].channel_start_offset = + vgmstream->ch[0].offset = vgmstream->ch[1].offset; + vgmstream->ch[1].channel_start_offset = + vgmstream->ch[1].offset = temp; } 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/scd_pcm.c b/Frameworks/vgmstream/vgmstream/src/meta/scd_pcm.c new file mode 100644 index 000000000..1e374beda --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/scd_pcm.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* PCM (from Lunar: Eternal Blue (Sega CD) */ +VGMSTREAM * init_vgmstream_scd_pcm(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pcm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x00020000) + goto fail; + + loop_flag = (read_32bitLE(0x02,streamFile)!=0); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x200; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PCM8_SB_int; + vgmstream->num_samples = read_32bitBE(0x06,streamFile)*2; + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x02,streamFile)*0x400*2; + vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile)*2; + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1; + vgmstream->meta_type = meta_SCD_PCM; + + /* 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; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + 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/sli.c b/Frameworks/vgmstream/vgmstream/src/meta/sli.c index 78d2950d7..a2852667e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sli.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sli.c @@ -54,7 +54,7 @@ VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE *streamFile) { while ((loop_start == -1 || loop_length == -1) && sli_offset < get_streamfile_size(streamFile)) { char *endptr; char *foundptr; - bytes_read=get_streamfile_dos_line(sizeof(linebuffer),linebuffer,sli_offset,streamFile,&done); + bytes_read=get_streamfile_text_line(sizeof(linebuffer),linebuffer,sli_offset,streamFile,&done); if (!done) goto fail; if (!memcmp("LoopStart=",linebuffer,10) && linebuffer[10]!='\0') { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c index f55532618..248281871 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c @@ -1,31 +1,14 @@ #include "meta.h" #include "../coding/coding.h" +#include "sqex_scd_streamfile.h" -/* Square-Enix SCD (FF XIII, XIV) */ - -/* special streamfile type to handle deinterleaving of complete files, - (based heavily on AIXSTREAMFILE */ -typedef struct _SCDINTSTREAMFILE -{ - STREAMFILE sf; - STREAMFILE *real_file; - const char * filename; - off_t start_physical_offset; - off_t current_logical_offset; - off_t interleave_block_size; - off_t stride_size; - size_t total_size; -} SCDINTSTREAMFILE; - -static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size); #ifdef VGM_USE_VORBIS static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read); static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read); #endif - - +/* SCD - Square-Enix console games (FF XIII, XIV) */ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; @@ -34,39 +17,39 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { int32_t loop_start, loop_end; int target_stream = streamFile->stream_index; - int loop_flag = 0, channel_count, codec_id; + int loop_flag = 0, channel_count, codec_id, sample_rate; int aux_chunk_count; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + /* check extension, case insensitive */ if ( !check_extensions(streamFile, "scd") ) goto fail; - streamFile->get_name(streamFile,filename,sizeof(filename)); /* SEDB */ - if (read_32bitBE(0,streamFile) != 0x53454442) goto fail; + if (read_32bitBE(0x00,streamFile) != 0x53454442) goto fail; /* SSCF */ - if (read_32bitBE(4,streamFile) != 0x53534346) goto fail; + if (read_32bitBE(0x04,streamFile) != 0x53534346) goto fail; /** main header section **/ - if (read_32bitBE(8,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */ - read_32bitBE(8,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */ + 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 */ read_32bit = read_32bitBE; read_16bit = read_16bitBE; //size_offset = 0x14; - } else if (read_32bitLE(8,streamFile) == 3 || /* version 2/3 LE, as seen in FFXIV for PC (and others?) */ - read_32bitLE(8,streamFile) == 2) { + } else if (read_32bitLE(0x08,streamFile) == 3 || /* version 2/3 LE, as seen in FFXIV for PC (and others?) */ + read_32bitLE(0x08,streamFile) == 2) { read_32bit = read_32bitLE; read_16bit = read_16bitLE; //size_offset = 0x10; } else goto fail; - /* 0xc: probably 00=LE, 01=BE */ - /* 0xd: unk (always 0x04) */ + /* 0x0c: probably 0=LE, 1=BE */ + /* 0x0d: unk (always 0x04) */ tables_offset = read_16bit(0xe,streamFile); #if 0 @@ -97,14 +80,14 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile); /** stream header **/ - stream_size = read_32bit(meta_offset + 0x0, streamFile); - channel_count = read_32bit(meta_offset+4,streamFile); - /* 0x8 sample rate */ - codec_id = read_32bit(meta_offset+0xc,streamFile); + stream_size = read_32bit(meta_offset+0x00, streamFile); + channel_count = read_32bit(meta_offset+0x04,streamFile); + sample_rate = read_32bit(meta_offset+0x08,streamFile); + codec_id = read_32bit(meta_offset+0x0c,streamFile); - loop_start = read_32bit(meta_offset+0x10,streamFile); - loop_end = read_32bit(meta_offset+0x14,streamFile); - loop_flag = (loop_end > 0); + loop_start = read_32bit(meta_offset+0x10,streamFile); + loop_end = read_32bit(meta_offset+0x14,streamFile); + loop_flag = (loop_end > 0); post_meta_offset = meta_offset + 0x20; start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile); @@ -123,18 +106,14 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } - #ifdef VGM_USE_VORBIS /* special case using init_vgmstream_ogg_vorbis with callbacks */ - if (codec_id == 0x6) - { + if (codec_id == 0x06) { VGMSTREAM * result = NULL; uint32_t seek_table_size, vorb_header_size; uint8_t xor_version, xor_byte; - vgm_vorbis_info_t inf; + vgm_vorbis_info_t inf = {0}; - - memset(&inf, 0, sizeof(inf)); inf.loop_start = loop_start; inf.loop_end = loop_end; inf.loop_flag = loop_flag; @@ -205,13 +184,12 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { /* fill in the vital statistics */ vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bit(meta_offset+8,streamFile); + vgmstream->sample_rate = sample_rate; vgmstream->num_streams = headers_entries; vgmstream->meta_type = meta_SQEX_SCD; switch (codec_id) { - case 0x1: - /* PCM */ + case 0x01: /* PCM */ vgmstream->coding_type = coding_PCM16_int; vgmstream->layout_type = layout_none; vgmstream->num_samples = stream_size / 2 / channel_count; @@ -221,124 +199,111 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->loop_end_sample = loop_end / 2 / channel_count; } break; + + case 0x06: /* OGG [Final Fantasy XIII-2 (PS3), Final Fantasy XIV (PC)] */ + goto fail; /* handled above */ + #ifdef VGM_USE_MPEG - case 0x7: - /* MPEG */ - { - mpeg_codec_data *mpeg_data = NULL; - coding_t ct; + case 0x07: { /* MPEG [Final Fantasy XIII (PS3)] */ + mpeg_codec_data *mpeg_data = NULL; - /* Drakengard 3, some Kingdom Hearts */ - if (vgmstream->sample_rate == 47999) - vgmstream->sample_rate = 48000; - if (vgmstream->sample_rate == 44099) - vgmstream->sample_rate = 44100; + /* Drakengard 3, some Kingdom Hearts */ + if (vgmstream->sample_rate == 47999) + vgmstream->sample_rate = 48000; + if (vgmstream->sample_rate == 44099) + vgmstream->sample_rate = 44100; - mpeg_data = init_mpeg_codec_data(streamFile, start_offset, &ct, vgmstream->channels); - if (!mpeg_data) goto fail; - vgmstream->codec_data = mpeg_data; + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels); + if (!mpeg_data) goto fail; + vgmstream->codec_data = mpeg_data; + vgmstream->layout_type = layout_none; - vgmstream->coding_type = ct; - vgmstream->layout_type = layout_none; - vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data); - vgmstream->num_samples -= vgmstream->num_samples%576; - if (loop_flag) { - vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data); - vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576; - vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data); - vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576; - } - vgmstream->interleave_block_size = 0; + vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data); + vgmstream->num_samples -= vgmstream->num_samples%576; + if (loop_flag) { + vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data); + vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576; + vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data); + vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576; } + vgmstream->interleave_block_size = 0; break; + } #endif - case 0xC: - /* MS ADPCM */ + case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */ vgmstream->coding_type = coding_MSADPCM; vgmstream->layout_type = layout_none; - vgmstream->interleave_block_size = read_16bit(post_meta_offset+0xc,streamFile); - vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels); + vgmstream->interleave_block_size = read_16bit(post_meta_offset+0x0c,streamFile); + vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels); if (loop_flag) { vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels); vgmstream->loop_end_sample = msadpcm_bytes_to_samples(loop_end, vgmstream->interleave_block_size, vgmstream->channels); } break; - case 0xA: /* Dragon Quest X (Wii) */ - case 0x15: /* Dragon Quest X (Wii U) (no apparent differences except higher sample rate) */ - /* GC/Wii DSP ADPCM */ - { - STREAMFILE * file; - int i; - const off_t interleave_size = 0x800; - const off_t stride_size = interleave_size * channel_count; + case 0x0A: /* DSP ADPCM [Dragon Quest X (Wii)] */ + case 0x15: { /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */ + STREAMFILE * file; + int i; + const off_t interleave_size = 0x800; + const off_t stride_size = interleave_size * channel_count; + size_t total_size; + scd_int_codec_data * data = NULL; - size_t total_size; - scd_int_codec_data * data = NULL; - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_scd_int; - - /* a normal DSP header... */ - vgmstream->num_samples = read_32bitBE(start_offset+0,streamFile); - total_size = (read_32bitBE(start_offset+4,streamFile)+1)/2; - - if (loop_flag) { - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end+1; - } - - /* verify other channel headers */ - for (i = 1; i < channel_count; i++) { - if (read_32bitBE(start_offset+interleave_size*i+0,streamFile) != vgmstream->num_samples || - (read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size) { - goto fail; - } - - } - - /* the primary streamfile we'll be using */ - file = streamFile->open(streamFile,filename,stride_size); - if (!file) - goto fail; - - vgmstream->ch[0].streamfile = file; - - data = malloc(sizeof(scd_int_codec_data)); - data->substream_count = channel_count; - data->substreams = calloc(channel_count, sizeof(VGMSTREAM *)); - data->intfiles = calloc(channel_count, sizeof(STREAMFILE *)); - - vgmstream->codec_data = data; - - for (i=0;isubstreams[i] = init_vgmstream_ngc_dsp_std(intfile); - data->intfiles[i] = intfile; - if (!data->substreams[i]) - goto fail; - - /* TODO: only handles mono substreams, though that's all we have with DSP */ - /* save start things so we can restart for seeking/looping */ - /* copy the channels */ - memcpy(data->substreams[i]->start_ch,data->substreams[i]->ch,sizeof(VGMSTREAMCHANNEL)*1); - /* copy the whole VGMSTREAM */ - memcpy(data->substreams[i]->start_vgmstream,data->substreams[i],sizeof(VGMSTREAM)); - - } + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_scd_int; + /* a normal DSP header... */ + total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2; + vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end+1; } + + /* verify other channel headers */ + for (i = 1; i < channel_count; i++) { + if (read_32bitBE(start_offset+interleave_size*i+0,streamFile) != vgmstream->num_samples || + (read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size) { + goto fail; + } + } + + /* the primary streamfile we'll be using */ + file = streamFile->open(streamFile,filename,stride_size); + if (!file) goto fail; + + vgmstream->ch[0].streamfile = file; + + data = malloc(sizeof(scd_int_codec_data)); + data->substream_count = channel_count; + data->substreams = calloc(channel_count, sizeof(VGMSTREAM *)); + data->intfiles = calloc(channel_count, sizeof(STREAMFILE *)); + + vgmstream->codec_data = data; + + for (i=0;isubstreams[i] = init_vgmstream_ngc_dsp_std(intfile); + data->intfiles[i] = intfile; + if (!data->substreams[i]) goto fail; + + /* TODO: only handles mono substreams, though that's all we have with DSP */ + /* save start things so we can restart for seeking/looping */ + memcpy(data->substreams[i]->start_ch,data->substreams[i]->ch,sizeof(VGMSTREAMCHANNEL)*1); + memcpy(data->substreams[i]->start_vgmstream,data->substreams[i],sizeof(VGMSTREAM)); + } + break; + } + #ifdef VGM_USE_FFMPEG - case 0xB: - /* XMA2 */ /* Lightning Returns SFX, FFXIII (X360) */ - { + case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx] */ ffmpeg_codec_data *ffmpeg_data = NULL; uint8_t buf[200]; int32_t bytes; @@ -356,44 +321,42 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->num_samples = ffmpeg_data->totalSamples; vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; - } break; + } - case 0xE: - /* ATRAC3plus */ /* Lord of Arcana (PSP) */ - { - ffmpeg_codec_data *ffmpeg_data = NULL; + case 0x0E: { /* ATRAC3plus [Lord of Arcana (PSP)] */ + ffmpeg_codec_data *ffmpeg_data = NULL; - /* full RIFF header at start_offset/post_meta_offset (same) */ - ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size); - if (!ffmpeg_data) goto fail; - vgmstream->codec_data = ffmpeg_data; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; + /* full RIFF header at start_offset/post_meta_offset (same) */ + ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; - vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact samples */ - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; + vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact samples */ + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; - /* manually read skip_samples if FFmpeg didn't do it */ - if (ffmpeg_data->skipSamples <= 0) { - off_t chunk_offset; - size_t chunk_size, fact_skip_samples = 0; - if (!find_chunk_le(streamFile, 0x66616374,start_offset+0xc,0, &chunk_offset,&chunk_size)) /* find "fact" */ - goto fail; - if (chunk_size == 0x8) { - fact_skip_samples = read_32bitLE(chunk_offset+0x4, streamFile); - } else if (chunk_size == 0xc) { - fact_skip_samples = read_32bitLE(chunk_offset+0x8, streamFile); - } - ffmpeg_set_skip_samples(ffmpeg_data, fact_skip_samples); + /* manually read skip_samples if FFmpeg didn't do it */ + if (ffmpeg_data->skipSamples <= 0) { + off_t chunk_offset; + size_t chunk_size, fact_skip_samples = 0; + if (!find_chunk_le(streamFile, 0x66616374,start_offset+0xc,0, &chunk_offset,&chunk_size)) /* find "fact" */ + goto fail; + if (chunk_size == 0x8) { + fact_skip_samples = read_32bitLE(chunk_offset+0x4, streamFile); + } else if (chunk_size == 0xc) { + fact_skip_samples = read_32bitLE(chunk_offset+0x8, streamFile); } - /* SCD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */ - + ffmpeg_set_skip_samples(ffmpeg_data, fact_skip_samples); } - break; + /* SCD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */ + break; + } #endif + default: VGM_LOG("SCD: unknown codec_id 0x%x\n", codec_id); goto fail; @@ -410,131 +373,6 @@ fail: return NULL; } -static STREAMFILE *open_scdint_impl(SCDINTSTREAMFILE *streamfile,const char * const filename,size_t buffersize) -{ - SCDINTSTREAMFILE *newfile; - - if (strcmp(filename, streamfile->filename)) - return NULL; - - newfile = malloc(sizeof(SCDINTSTREAMFILE)); - if (!newfile) - return NULL; - - memcpy(newfile,streamfile,sizeof(SCDINTSTREAMFILE)); - return &newfile->sf; -} - -static void close_scdint(SCDINTSTREAMFILE *streamfile) -{ - free(streamfile); - return; -} - -static size_t get_size_scdint(SCDINTSTREAMFILE *streamfile) -{ - return streamfile->total_size; -} - -static size_t get_offset_scdint(SCDINTSTREAMFILE *streamfile) -{ - return streamfile->current_logical_offset; -} - -static void get_name_scdint(SCDINTSTREAMFILE *streamfile, char *buffer, size_t length) -{ - strncpy(buffer,streamfile->filename,length); - buffer[length-1]='\0'; -} - -static size_t read_scdint(SCDINTSTREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length) -{ - size_t sz = 0; - - while (length > 0) - { - off_t to_read; - off_t length_available; - off_t block_num; - off_t intrablock_offset; - off_t physical_offset; - - - block_num = offset / streamfile->interleave_block_size; - intrablock_offset = offset % streamfile->interleave_block_size; - streamfile->current_logical_offset = offset; - physical_offset = streamfile->start_physical_offset + block_num * streamfile->stride_size + intrablock_offset; - - length_available = - streamfile->interleave_block_size - intrablock_offset; - - if (length < length_available) - { - to_read = length; - } - else - { - to_read = length_available; - } - - if (to_read > 0) - { - size_t bytes_read; - - bytes_read = read_streamfile(dest, - physical_offset, - to_read, streamfile->real_file); - - sz += bytes_read; - - streamfile->current_logical_offset = offset + bytes_read; - - if (bytes_read != to_read) - { - /* an error which we will not attempt to handle here */ - return sz; - } - - dest += bytes_read; - offset += bytes_read; - length -= bytes_read; - } - } - - return sz; -} - -/* start_offset is for *this* interleaved stream */ -static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size) -{ - SCDINTSTREAMFILE * scd = NULL; - - /* _scdint funcs can't handle this case */ - if (start_offset + total_size > file->get_size(file)) - return NULL; - - scd = malloc(sizeof(SCDINTSTREAMFILE)); - if (!scd) - return NULL; - - scd->sf.read = (void*)read_scdint; - scd->sf.get_size = (void*)get_size_scdint; - scd->sf.get_offset = (void*)get_offset_scdint; - scd->sf.get_name = (void*)get_name_scdint; - scd->sf.get_realname = (void*)get_name_scdint; - scd->sf.open = (void*)open_scdint_impl; - scd->sf.close = (void*)close_scdint; - - scd->real_file = file; - scd->filename = filename; - scd->start_physical_offset = start_offset; - scd->current_logical_offset = 0; - scd->interleave_block_size = interleave_block_size; - scd->stride_size = stride_size; - scd->total_size = total_size; - - return &scd->sf; -} #ifdef VGM_USE_VORBIS static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h new file mode 100644 index 000000000..2d9f67c76 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h @@ -0,0 +1,134 @@ +#ifndef _SQEX_SCD_STREAMFILE_H_ +#define _SQEX_SCD_STREAMFILE_H_ +#include "../streamfile.h" + +/* special streamfile type to handle deinterleaving of complete files (based heavily on AIXSTREAMFILE */ + +typedef struct _SCDINTSTREAMFILE { + STREAMFILE sf; + STREAMFILE *real_file; + const char * filename; + off_t start_physical_offset; + off_t current_logical_offset; + off_t interleave_block_size; + off_t stride_size; + size_t total_size; +} SCDINTSTREAMFILE; + + +/*static*/ STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size); + + +static STREAMFILE *open_scdint_impl(SCDINTSTREAMFILE *streamfile,const char * const filename,size_t buffersize) { + SCDINTSTREAMFILE *newfile; + + if (strcmp(filename, streamfile->filename)) + return NULL; + + newfile = malloc(sizeof(SCDINTSTREAMFILE)); + if (!newfile) + return NULL; + + memcpy(newfile,streamfile,sizeof(SCDINTSTREAMFILE)); + return &newfile->sf; +} + +static void close_scdint(SCDINTSTREAMFILE *streamfile) { + free(streamfile); + return; +} + +static size_t get_size_scdint(SCDINTSTREAMFILE *streamfile) { + return streamfile->total_size; +} + +static size_t get_offset_scdint(SCDINTSTREAMFILE *streamfile) { + return streamfile->current_logical_offset; +} + +static void get_name_scdint(SCDINTSTREAMFILE *streamfile, char *buffer, size_t length) { + strncpy(buffer,streamfile->filename,length); + buffer[length-1]='\0'; +} + +static size_t read_scdint(SCDINTSTREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length) { + size_t sz = 0; + + while (length > 0) { + off_t to_read; + off_t length_available; + off_t block_num; + off_t intrablock_offset; + off_t physical_offset; + + + block_num = offset / streamfile->interleave_block_size; + intrablock_offset = offset % streamfile->interleave_block_size; + streamfile->current_logical_offset = offset; + physical_offset = streamfile->start_physical_offset + block_num * streamfile->stride_size + intrablock_offset; + + length_available = streamfile->interleave_block_size - intrablock_offset; + + if (length < length_available) { + to_read = length; + } + else { + to_read = length_available; + } + + if (to_read > 0) { + size_t bytes_read; + + bytes_read = read_streamfile(dest, + physical_offset, + to_read, streamfile->real_file); + + sz += bytes_read; + + streamfile->current_logical_offset = offset + bytes_read; + + if (bytes_read != to_read) { + return sz; /* an error which we will not attempt to handle here */ + } + + dest += bytes_read; + offset += bytes_read; + length -= bytes_read; + } + } + + return sz; +} + +/* start_offset is for *this* interleaved stream */ +/*static*/ STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size) { + SCDINTSTREAMFILE * scd = NULL; + + /* _scdint funcs can't handle this case */ + if (start_offset + total_size > file->get_size(file)) + return NULL; + + scd = malloc(sizeof(SCDINTSTREAMFILE)); + if (!scd) + return NULL; + + scd->sf.read = (void*)read_scdint; + scd->sf.get_size = (void*)get_size_scdint; + scd->sf.get_offset = (void*)get_offset_scdint; + scd->sf.get_name = (void*)get_name_scdint; + scd->sf.get_realname = (void*)get_name_scdint; + scd->sf.open = (void*)open_scdint_impl; + scd->sf.close = (void*)close_scdint; + + scd->real_file = file; + scd->filename = filename; + scd->start_physical_offset = start_offset; + scd->current_logical_offset = 0; + scd->interleave_block_size = interleave_block_size; + scd->stride_size = stride_size; + scd->total_size = total_size; + + return &scd->sf; +} + +#endif /* _SCD_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ss_stream.c b/Frameworks/vgmstream/vgmstream/src/meta/ss_stream.c deleted file mode 100644 index 5c29495df..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/ss_stream.c +++ /dev/null @@ -1,203 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* SS_STREAM - - SS_STREAM is format used by various UBI Soft Games - - 2008-11-15 - Fastelbja : First version ... - - - Some infos, sorry for messing up the meta (regards, manako) - -Splinter Cell - *.SS0; PC (except Music_*.SS0) -Splinter Cell: Pandora Tomorrow - *.SS0, *.LS0; PC -Splinter Cell: Chaos Theory - *.SS0, *.LS0; PC -Splinter Cell: Double Agent - *.SS0, *.LS0; PC - -UbiSoft Old Simple Stream (version 3) -UbiSoft Simple Stream (version 5) -UbiSoft Old Interleaved Stream (version 2) -UbiSoft Interleaved Stream (version 8 ) - -Note: if the version number is 3, then all values in this file are big-endian. If the version is 5, then all values are little-endian. - -Header: -byte {1} - Version number (3 or 5) -byte {3} - Unknown -byte {4} - Unknown -uint32 {4} - Unknown -uint16 {2} - Unknown -uint16 {2} - Number of extra uncompressed samples before the data (always 10) -int16 {2} - First left sample for decompression -byte {1} - First left index for decompression -byte {1} - Unknown -int16 {2} - First right sample for decompression -byte {1} - First right index for decompression -byte {1} - Unknown -byte {4} - Unknown - -Extra Uncompressed Samples: -if the sound is mono: -int16 {Number of extra uncompressed samples * 2} - Uncompressed samples - -if the sound is stereo: -int16 {Number of extra uncompressed samples * 4} - Uncompressed samples - -Data: -byte {?} - Compressed data - - - -And here is the format of the old interleaved streams: - -Code: -Little-endian - -uint32 {4} - Signature (2) -uint32 {4} - Number of Layers (always 3) -uint32 {4} - Total File Size -uint32 {4} - Unknown (always 20) -uint32 {4} - Unknown (always 1104) -uint32 {4} - Average Block Size (always 361) - -For Each Block: { - uint32 {4} - Block Index (begins at 1) - uint32 {4} - Unknown (always 20) - - For Each Layer (Chunk): { - uint32 {4} - Layer Chunk Size - } - - For Each Layer (Chunk): { - uint32 {Layer Chunk Size} - Chunk of an Encapsulated UbiSoft Old Simple Stream - } -} - - -And the new interleaved streams: - -Code: -Little-endian - -uint16 {2} - Signature (8) -uint16 {2} - Unknown -uint32 {4} - Unknown -uint32 {4} - Number of Layers -uint32 {4} - Number of Blocks -uint32 {4} - Number of Bytes after This to the Headers -uint32 {4} - The Sum of (Number of Layers * 4) Plus the Header Lengths -uint32 {4} - Average Sum of Chunk Data Lengths - -For Each Layer: { - uint32 {4} - Layer Header Size -} - -For Each Layer: { - uint32 {Layer Header Size} - Header of an Encapsulated Stream (PCM, UbiSoft Simple Stream, Ogg Vorbis) -} - -For Each Block: { - uint32 {4} - Signature (3) - uint32 {4} - Number of bytes from the start of this block to the next block, 0 if no more blocks - - For Each Layer (Chunk): { - uint32 {4} - Layer Chunk Size - } - - For Each Layer (Chunk): { - uint32 {Layer Chunk Size} - Chunk of an Encapsulated Stream (PCM, UbiSoft Simple Stream, Ogg Vorbis) - } -} - - -*/ - -VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int loop_flag=0; - int channels; - int channel_count; - off_t start_offset; - int i; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("ss3",filename_extension(filename)) && - strcasecmp("ss7",filename_extension(filename))) goto fail; - - loop_flag = 0; - //freq_flag = read_8bit(0x08,streamFile); - - if (read_8bit(0x0C,streamFile) == 0) { - channels = 1; - } else { - channels = read_8bit(0x0C,streamFile)*2; - } - - channel_count = channels; - - - /* 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 = 48000; - - -#if 0 - if (!strcasecmp("ss3",filename_extension(filename))) { - vgmstream->sample_rate = 32000; - } else if (!strcasecmp("ss7",filename_extension(filename))) { - vgmstream->sample_rate = 48000; - } -#endif - - start_offset = (read_8bit(0x07,streamFile)+5); - -#if 0 - if (channel_count == 1){ - start_offset = 0x3C; - } else if (channel_count == 2) { - start_offset = 0x44; - } -#endif - - if(channel_count==1) - vgmstream->coding_type = coding_IMA; - else - vgmstream->coding_type = coding_EACS_IMA; - - vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile)-start_offset)* 2 / vgmstream->channels); - vgmstream->layout_type = layout_none; - - vgmstream->meta_type = meta_XBOX_WAVM; - vgmstream->get_high_nibble=0; - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].offset = start_offset; - } else if (channel_count == 2) { - vgmstream->ch[i].offset = start_offset; - } - - vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - vgmstream->ch[i].adpcm_history1_32=(int32_t)read_16bitLE(0x10+i*4,streamFile); - vgmstream->ch[i].adpcm_step_index =(int)read_8bit(0x12+i*4,streamFile); - if (!vgmstream->ch[i].streamfile) goto fail; - } - } - - 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/ta_aac.c b/Frameworks/vgmstream/vgmstream/src/meta/ta_aac.c index 6d4958bca..136ef057f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ta_aac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ta_aac.c @@ -8,93 +8,93 @@ VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int loop_flag, channel_count; - size_t sampleRate, numSamples, startSample, dataSize, blockSize, blockCount; // A mess + size_t sampleRate, numSamples, startSample, dataSize, blockSize, blockCount; // A mess /* check extension, case insensitive */ - /* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */ + /* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */ if ( !check_extensions(streamFile,"aac,laac,ace")) goto fail; if (read_32bitBE(0x00,streamFile) != 0x41414320) /* "AAC " */ goto fail; - /* Ok, let's check what's behind door number 1 */ - if (read_32bitBE(0x1000, streamFile) == 0x41534320) /* "ASC " */ - { - loop_flag = read_32bitBE(0x1118, streamFile); + /* Ok, let's check what's behind door number 1 */ + if (read_32bitBE(0x1000, streamFile) == 0x41534320) /* "ASC " */ + { + loop_flag = read_32bitBE(0x1118, streamFile); - /*Funky Channel Count Checking */ - if (read_32bitBE(0x1184, streamFile) == 0x7374726D) - channel_count = 6; - else if (read_32bitBE(0x1154, streamFile) == 0x7374726D) - channel_count = 4; - else - channel_count = read_8bit(0x1134, streamFile); + /*Funky Channel Count Checking */ + if (read_32bitBE(0x1184, streamFile) == 0x7374726D) + channel_count = 6; + else if (read_32bitBE(0x1154, streamFile) == 0x7374726D) + channel_count = 4; + else + channel_count = read_8bit(0x1134, streamFile); - sampleRate = read_32bitBE(0x10F4, streamFile); - numSamples = read_32bitBE(0x10FC, streamFile); - startSample = read_32bitBE(0x10F8, streamFile); - dataSize = read_32bitBE(0x10F0, streamFile); - blockSize = read_32bitBE(0x1100, streamFile); - blockCount = read_32bitBE(0x110C, streamFile); - } - else if (read_32bitBE(0x1000, streamFile) == 0x57415645) /* "WAVE" */ - { - loop_flag = read_32bitBE(0x1048, streamFile); + sampleRate = read_32bitBE(0x10F4, streamFile); + numSamples = read_32bitBE(0x10FC, streamFile); + startSample = read_32bitBE(0x10F8, streamFile); + dataSize = read_32bitBE(0x10F0, streamFile); + blockSize = read_32bitBE(0x1100, streamFile); + blockCount = read_32bitBE(0x110C, streamFile); + } + else if (read_32bitBE(0x1000, streamFile) == 0x57415645) /* "WAVE" */ + { + loop_flag = read_32bitBE(0x1048, streamFile); - /*Funky Channel Count Checking */ - if (read_32bitBE(0x10B0, streamFile) == 0x7374726D) - channel_count = 6; - else if (read_32bitBE(0x1080, streamFile) == 0x7374726D) - channel_count = 4; - else - channel_count = read_8bit(0x1060, streamFile); + /*Funky Channel Count Checking */ + if (read_32bitBE(0x10B0, streamFile) == 0x7374726D) + channel_count = 6; + else if (read_32bitBE(0x1080, streamFile) == 0x7374726D) + channel_count = 4; + else + channel_count = read_8bit(0x1060, streamFile); - sampleRate = read_32bitBE(0x1024, streamFile); - numSamples = read_32bitBE(0x102C, streamFile); - startSample = read_32bitBE(0x1028, streamFile); - dataSize = read_32bitBE(0x1020, streamFile); - blockSize = read_32bitBE(0x1030, streamFile); - blockCount = read_32bitBE(0x103C, streamFile); - } - else if (read_32bitBE(0x1000, streamFile) == 0x00000000) /* some like to be special */ - { - loop_flag = read_32bitBE(0x6048, streamFile); + sampleRate = read_32bitBE(0x1024, streamFile); + numSamples = read_32bitBE(0x102C, streamFile); + startSample = read_32bitBE(0x1028, streamFile); + dataSize = read_32bitBE(0x1020, streamFile); + blockSize = read_32bitBE(0x1030, streamFile); + blockCount = read_32bitBE(0x103C, streamFile); + } + else if (read_32bitBE(0x1000, streamFile) == 0x00000000) /* some like to be special */ + { + loop_flag = read_32bitBE(0x6048, streamFile); - /*Funky Channel Count Checking */ - if (read_32bitBE(0x60B0, streamFile) == 0x7374726D) - channel_count = 6; - else if (read_32bitBE(0x6080, streamFile) == 0x7374726D) - channel_count = 4; - else - channel_count = read_8bit(0x6060, streamFile); + /*Funky Channel Count Checking */ + if (read_32bitBE(0x60B0, streamFile) == 0x7374726D) + channel_count = 6; + else if (read_32bitBE(0x6080, streamFile) == 0x7374726D) + channel_count = 4; + else + channel_count = read_8bit(0x6060, streamFile); - sampleRate = read_32bitBE(0x6024, streamFile); - numSamples = read_32bitBE(0x602C, streamFile); - startSample = read_32bitBE(0x6028, streamFile); - dataSize = read_32bitBE(0x6020, streamFile); - blockSize = read_32bitBE(0x6030, streamFile); - blockCount = read_32bitBE(0x603C, streamFile); - } - else - goto fail; //cuz I don't know if there are other variants + sampleRate = read_32bitBE(0x6024, streamFile); + numSamples = read_32bitBE(0x602C, streamFile); + startSample = read_32bitBE(0x6028, streamFile); + dataSize = read_32bitBE(0x6020, streamFile); + blockSize = read_32bitBE(0x6030, streamFile); + blockCount = read_32bitBE(0x603C, streamFile); + } + else + goto fail; //cuz I don't know if there are other variants /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - if (read_32bitBE(0x1000, streamFile) == 0x00000000) - start_offset = 0x7000; - else - start_offset = 0x2000; + if (read_32bitBE(0x1000, streamFile) == 0x00000000) + start_offset = 0x7000; + else + start_offset = 0x2000; vgmstream->sample_rate = sampleRate; vgmstream->channels = channel_count; vgmstream->num_samples = numSamples; - if (loop_flag) { - vgmstream->loop_start_sample = startSample; - vgmstream->loop_end_sample = vgmstream->num_samples; - } + if (loop_flag) { + vgmstream->loop_start_sample = startSample; + vgmstream->loop_end_sample = vgmstream->num_samples; + } vgmstream->meta_type = meta_TA_AAC_X360; #ifdef VGM_USE_FFMPEG @@ -103,9 +103,9 @@ VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile) { uint8_t buf[100]; size_t bytes, datasize, block_size, block_count; - block_count = blockCount; - block_size = blockSize; - datasize = dataSize; + block_count = blockCount; + block_size = blockSize; + datasize = dataSize; bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); if (bytes <= 0) goto fail; @@ -132,79 +132,79 @@ fail: /* PlayStation 3 Variants (Star Ocean International, Resonance of Fate) */ VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - uint32_t data_size, loop_start, loop_end, codec_id; + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + uint32_t data_size, loop_start, loop_end, codec_id; - /* check extension, case insensitive */ - /* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */ - if (!check_extensions(streamFile, "aac,laac,ace")) - goto fail; + /* check extension, case insensitive */ + /* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */ + if (!check_extensions(streamFile, "aac,laac,ace")) + goto fail; - if (read_32bitBE(0x00, streamFile) != 0x41414320) /* "AAC " */ - goto fail; + if (read_32bitBE(0x00, streamFile) != 0x41414320) /* "AAC " */ + goto fail; - /* Haven't Found a codec flag yet. Let's just use this for now */ - if (read_32bitBE(0x10000, streamFile) != 0x41534320) /* "ASC " */ - goto fail; + /* Haven't Found a codec flag yet. Let's just use this for now */ + if (read_32bitBE(0x10000, streamFile) != 0x41534320) /* "ASC " */ + goto fail; - if (read_32bitBE(0x10104, streamFile) != 0xFFFFFFFF) - loop_flag = 1; - else - loop_flag = 0; + if (read_32bitBE(0x10104, streamFile) != 0xFFFFFFFF) + loop_flag = 1; + else + loop_flag = 0; - channel_count = read_32bitBE(0x100F4, streamFile); - codec_id = read_32bitBE(0x100F0, streamFile); + channel_count = read_32bitBE(0x100F4, streamFile); + codec_id = read_32bitBE(0x100F0, streamFile); - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; - /* Useless header, let's play the guessing game */ - start_offset = 0x10110; - vgmstream->sample_rate = read_32bitBE(0x100FC, streamFile); - vgmstream->channels = channel_count; - vgmstream->meta_type = meta_TA_AAC_PS3; - data_size = read_32bitBE(0x100F8, streamFile); - loop_start = read_32bitBE(0x10104, streamFile); - loop_end = read_32bitBE(0x10108, streamFile); + /* Useless header, let's play the guessing game */ + start_offset = 0x10110; + vgmstream->sample_rate = read_32bitBE(0x100FC, streamFile); + vgmstream->channels = channel_count; + vgmstream->meta_type = meta_TA_AAC_PS3; + data_size = read_32bitBE(0x100F8, streamFile); + loop_start = read_32bitBE(0x10104, streamFile); + loop_end = read_32bitBE(0x10108, streamFile); #ifdef VGM_USE_FFMPEG - { - ffmpeg_codec_data *ffmpeg_data = NULL; - uint8_t buf[100]; - int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo, max_samples; - block_size = (codec_id == 4 ? 0x60 : (codec_id == 5 ? 0x98 : 0xC0)) * vgmstream->channels; - max_samples = (data_size / block_size) * samples_size; - encoder_delay = 0x0; - joint_stereo = 0; + { + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[100]; + int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo, max_samples; + block_size = (codec_id == 4 ? 0x60 : (codec_id == 5 ? 0x98 : 0xC0)) * vgmstream->channels; + max_samples = (data_size / block_size) * samples_size; + encoder_delay = 0x0; + joint_stereo = 0; /* make a fake riff so FFmpeg can parse the ATRAC3 */ - bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); - if (bytes <= 0) goto fail; + bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); + if (bytes <= 0) goto fail; - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, data_size); - if (!ffmpeg_data) goto fail; - vgmstream->codec_data = ffmpeg_data; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - vgmstream->num_samples = max_samples; + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, data_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = max_samples; - if (loop_flag) { - vgmstream->loop_start_sample = (loop_start / block_size) * samples_size; - vgmstream->loop_end_sample = (loop_end / block_size) * samples_size; - } + if (loop_flag) { + vgmstream->loop_start_sample = (loop_start / block_size) * samples_size; + vgmstream->loop_end_sample = (loop_end / block_size) * samples_size; + } - } + } #endif - /* open the file for reading */ - if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) - goto fail; - return vgmstream; + /* open the file for reading */ + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; fail: - close_vgmstream(vgmstream); - return NULL; + close_vgmstream(vgmstream); + return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/thp.c b/Frameworks/vgmstream/vgmstream/src/meta/thp.c index b4b9d2407..2a9c95b9d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/thp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/thp.c @@ -7,74 +7,74 @@ VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; + VGMSTREAM * vgmstream = NULL; + + char filename[PATH_LIMIT]; + off_t start_offset; - char filename[PATH_LIMIT]; - off_t start_offset; - - uint32_t maxAudioSize=0; + uint32_t maxAudioSize=0; - uint32_t numComponents; - off_t componentTypeOffset; - off_t componentDataOffset; - - char thpVersion; + uint32_t numComponents; + off_t componentTypeOffset; + off_t componentDataOffset; - int loop_flag; - int channel_count=-1; - int i; + char thpVersion; + + int loop_flag; + int channel_count=-1; + int i; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("thp",filename_extension(filename)) && - strcasecmp("dsp",filename_extension(filename))) goto fail; + strcasecmp("dsp",filename_extension(filename))) goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x54485000) goto fail; - maxAudioSize = read_32bitBE(0x0C,streamFile); - thpVersion = read_8bit(0x06,streamFile); + maxAudioSize = read_32bitBE(0x0C,streamFile); + thpVersion = read_8bit(0x06,streamFile); - if(maxAudioSize==0) // no sound - goto fail; + if(maxAudioSize==0) // no sound + goto fail; loop_flag = 0; // allways unloop - /* fill in the vital statistics */ - if(thpVersion==0x10) { - start_offset = read_32bitBE(0x24,streamFile); - /* No idea what's up with this */ - if (start_offset == 0) - start_offset = read_32bitBE(0x28,streamFile); - } else - start_offset = read_32bitBE(0x28,streamFile); + /* fill in the vital statistics */ + if(thpVersion==0x10) { + start_offset = read_32bitBE(0x24,streamFile); + /* No idea what's up with this */ + if (start_offset == 0) + start_offset = read_32bitBE(0x28,streamFile); + } else + start_offset = read_32bitBE(0x28,streamFile); - // Get info from the first block - componentTypeOffset = read_32bitBE(0x20,streamFile); - numComponents = read_32bitBE(componentTypeOffset ,streamFile); - componentDataOffset=componentTypeOffset+0x14; - componentTypeOffset+=4; + // Get info from the first block + componentTypeOffset = read_32bitBE(0x20,streamFile); + numComponents = read_32bitBE(componentTypeOffset ,streamFile); + componentDataOffset=componentTypeOffset+0x14; + componentTypeOffset+=4; - for(i=0;ichannels=channel_count; - vgmstream->sample_rate=read_32bitBE(componentDataOffset+4,streamFile); - vgmstream->num_samples=read_32bitBE(componentDataOffset+8,streamFile); - break; - } else { - if(thpVersion==0x10) - componentDataOffset+=0x0c; - else - componentDataOffset+=0x08; - } - } + vgmstream->channels=channel_count; + vgmstream->sample_rate=read_32bitBE(componentDataOffset+4,streamFile); + vgmstream->num_samples=read_32bitBE(componentDataOffset+8,streamFile); + break; + } else { + if(thpVersion==0x10) + componentDataOffset+=0x0c; + else + componentDataOffset+=0x08; + } + } /* open the file for reading */ { @@ -87,10 +87,10 @@ VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile) { } } - vgmstream->thpNextFrameSize=read_32bitBE(0x18,streamFile); - thp_block_update(start_offset,vgmstream); + vgmstream->full_block_size = read_32bitBE(0x18,streamFile); /* block size of current block, changes every time */ + thp_block_update(start_offset,vgmstream); - vgmstream->coding_type = coding_NGC_DSP; + vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_thp_blocked; vgmstream->meta_type = meta_THP; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/tun.c b/Frameworks/vgmstream/vgmstream/src/meta/tun.c index 533ed0aff..cf270679a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/tun.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/tun.c @@ -1,58 +1,43 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* TUN (from LEGO Racers (PC)) */ +/* ALP - from LEGO Racers (PC) */ VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; off_t start_offset; - int channel_count; - int loop_flag; + int loop_flag, channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("tun",filename_extension(filename))) goto fail; + /* check extension */ + if ( !check_extensions(streamFile,"tun") ) + goto fail; /* check header */ if (read_32bitBE(0x00,streamFile) != 0x414C5020) /* "ALP " */ goto fail; - channel_count = 2; - loop_flag = 0; + channel_count = 2; /* probably at 0x0F */ + loop_flag = 0; + start_offset = 0x10; + /* also "ADPCM" at 0x08 */ - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x10; vgmstream->channels = channel_count; vgmstream->sample_rate = 22050; - vgmstream->coding_type = coding_DVI_IMA; - vgmstream->num_samples = (get_streamfile_size(streamFile)) - 0x10; + vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(streamFile) - 0x10, channel_count); + + vgmstream->coding_type = coding_DVI_IMA_int; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 1; + vgmstream->interleave_block_size = 0x01; vgmstream->meta_type = meta_TUN; /* 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; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - + 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); return NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index 1432ca9b4..7d6dd602a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -3,7 +3,7 @@ #include "../layout/layout.h" #include "../util.h" -#define TXTH_LINE_MAX 0x2000 +#define TXT_LINE_MAX 0x2000 /* known TXTH types */ typedef enum { @@ -30,11 +30,12 @@ typedef enum { XMA1 = 20, /* raw XMA1 */ XMA2 = 21, /* raw XMA2 */ FFMPEG = 22, /* any headered FFmpeg format */ + AC3 = 23, /* AC3/SPDIF */ } txth_type; typedef struct { txth_type codec; - txth_type codec_mode; + uint32_t codec_mode; uint32_t interleave; uint32_t id_value; @@ -60,11 +61,12 @@ typedef struct { uint32_t coef_offset; uint32_t coef_spacing; - uint32_t coef_mode; uint32_t coef_big_endian; + uint32_t coef_mode; } txth_header; +static STREAMFILE * open_txth(STREAMFILE * streamFile); static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth); static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth, const char * key, const char * val); static int parse_num(STREAMFILE * streamFile, const char * val, uint32_t * out_value); @@ -76,44 +78,16 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes); VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; STREAMFILE * streamText = NULL; - txth_header txth; + txth_header txth = {0}; coding_t coding; int i, j; /* no need for ID or ext checks -- if a .TXTH exists all is good - * (player still needs to accept the ext, so at worst rename to .vgmstream) */ - { - char filename[PATH_LIMIT]; - char fileext[PATH_LIMIT]; - - /* try "(path/)(name.ext).txth" */ - if (!get_streamfile_name(streamFile,filename,PATH_LIMIT)) goto fail; - strcat(filename, ".txth"); - streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (streamText) goto found; - - /* try "(path/)(.ext).txth" */ - if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail; - if (!get_streamfile_ext(streamFile,fileext,PATH_LIMIT)) goto fail; - strcat(filename,"."); - strcat(filename, fileext); - strcat(filename, ".txth"); - streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (streamText) goto found; - - /* try "(path/).txth" */ - if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail; - strcat(filename, ".txth"); - streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (streamText) goto found; - - /* not found */ - goto fail; - } -found: + * (player still needs to accept the streamfile's ext, so at worst rename to .vgmstream) */ + streamText = open_txth(streamFile); + if (!streamText) goto fail; /* process the text file */ - memset(&txth,0,sizeof(txth_header)); if (!parse_txth(streamFile, streamText, &txth)) goto fail; @@ -145,6 +119,7 @@ found: case ATRAC3PLUS: case XMA1: case XMA2: + case AC3: case FFMPEG: coding = coding_FFmpeg; break; #endif default: @@ -244,7 +219,8 @@ found: vgmstream->interleave_block_size = txth.interleave; } else if (txth.channels > 1 && txth.codec_mode == 1) { if (!txth.interleave) goto fail; - vgmstream->layout_type = layout_interleave_byte; + coding = coding_NGC_DSP_subint; + vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = txth.interleave; } else if (txth.channels == 1 || txth.codec_mode == 2) { vgmstream->layout_type = layout_none; @@ -261,7 +237,8 @@ found: for (j=0;j<16;j++) { vgmstream->ch[i].adpcm_coef[j] = read_16bit(txth.coef_offset + i*txth.coef_spacing + j*2,streamFile); } - } else { + } + else { goto fail; //IDK what is this /* for (j=0;j<8;j++) { @@ -285,7 +262,7 @@ found: case coding_FFmpeg: { ffmpeg_codec_data *ffmpeg_data = NULL; - if (txth.codec == FFMPEG) { + if (txth.codec == FFMPEG || txth.codec == AC3) { /* default FFmpeg */ ffmpeg_data = init_ffmpeg_offset(streamFile, txth.start_offset,txth.data_size); if ( !ffmpeg_data ) goto fail; @@ -390,47 +367,63 @@ fail: return NULL; } + +static STREAMFILE * open_txth(STREAMFILE * streamFile) { + char filename[PATH_LIMIT]; + char fileext[PATH_LIMIT]; + STREAMFILE * streamText; + + /* try "(path/)(name.ext).txth" */ + if (!get_streamfile_name(streamFile,filename,PATH_LIMIT)) goto fail; + strcat(filename, ".txth"); + streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (streamText) return streamText; + + /* try "(path/)(.ext).txth" */ + if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail; + if (!get_streamfile_ext(streamFile,fileext,PATH_LIMIT)) goto fail; + strcat(filename,"."); + strcat(filename, fileext); + strcat(filename, ".txth"); + streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (streamText) return streamText; + + /* try "(path/).txth" */ + if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail; + strcat(filename, ".txth"); + streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (streamText) return streamText; + +fail: + /* not found */ + return 0; +} + /* Simple text parser of "key = value" lines. * The code is meh and error handling not exactly the best. */ static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth) { - off_t off = 0; + off_t txt_offset = 0x00; off_t file_size = get_streamfile_size(streamText); txth->data_size = get_streamfile_size(streamFile); /* for later use */ /* skip BOM if needed */ if (read_16bitLE(0x00, streamText) == 0xFFFE || read_16bitLE(0x00, streamText) == 0xFEFF) - off = 0x02; + txt_offset = 0x02; /* read lines */ - while (off < file_size) { - char line[TXTH_LINE_MAX]; - char key[TXTH_LINE_MAX]; - char val[TXTH_LINE_MAX]; /* at least as big as a line to avoid overflows (I hope) */ - int ok; - off_t line_start = off, line_end = 0; - line[0] = key[0] = val[0] = 0; - - /* find line end */ - while (line_end == 0 && off - line_start < TXTH_LINE_MAX) { - char c = (char)read_8bit(off, streamText); - if (c == '\n') - line_end = off; - else if (off >= file_size) - line_end = off-1; + while (txt_offset < file_size) { + char line[TXT_LINE_MAX] = {0}; + char key[TXT_LINE_MAX] = {0}, val[TXT_LINE_MAX] = {0}; /* at least as big as a line to avoid overflows (I hope) */ + int ok, bytes_read, line_done; - off++; - } + bytes_read = get_streamfile_text_line(TXT_LINE_MAX,line, txt_offset,streamText, &line_done); + if (!line_done) goto fail; - if (line_end == 0) - goto fail; /* bad file / line too long */ + txt_offset += bytes_read; /* get key/val (ignores lead/trail spaces, stops at space/comment/separator) */ - read_streamfile((uint8_t*)line,line_start,line_end, streamText); - line[line_end - line_start + 1] = '\0'; ok = sscanf(line, " %[^ \t#=] = %[^ \t#\r\n] ", key,val); - //VGM_LOG("TXTH: ok=%i, key=\"%s\", val=\"%s\" from 0x%lx to 0x%lx\n", ok, key, val, line_start, line_end); - if (ok != 2) /* ignore line if no key=val (comment or garbage) */ continue; @@ -472,13 +465,20 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h else if (0==strcmp(val,"XMA1")) txth->codec = XMA1; else if (0==strcmp(val,"XMA2")) txth->codec = XMA2; else if (0==strcmp(val,"FFMPEG")) txth->codec = FFMPEG; + else if (0==strcmp(val,"AC3")) txth->codec = AC3; else goto fail; } else if (0==strcmp(key,"codec_mode")) { if (!parse_num(streamFile,val, &txth->codec_mode)) goto fail; } else if (0==strcmp(key,"interleave")) { - if (!parse_num(streamFile,val, &txth->interleave)) goto fail; + 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; + } } else if (0==strcmp(key,"id_value")) { if (!parse_num(streamFile,val, &txth->id_value)) goto fail; @@ -663,6 +663,10 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) { case XMA2: return bytes; /* preserve */ + case AC3: + if (!txth->interleave) return 0; + return bytes / txth->interleave * 256 * txth->channels; + /* untested */ case IMA: case DVI_IMA: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c index 5c3304f8b..118998f1c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_raki.c @@ -70,10 +70,11 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { switch(((uint64_t)platform << 32) | type) { case 0x57696E2070636D20: /* "Win pcm " */ + case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4)*/ /* chunks: "data" */ - vgmstream->coding_type = little_endian ? coding_PCM16LE : coding_PCM16BE; + vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = block_align; + vgmstream->interleave_block_size = block_align; /* usually 0x04 */ vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, bits_per_sample); break; @@ -88,7 +89,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { break; case 0x5769692061647063: /* "Wii adpc" */ - case 0x4361666561647063: /* "Cafeadpc" (WiiU) */ + case 0x4361666561647063: /* "Cafeadpc" (Cafe = WiiU) */ /* chunks: "datS" (stereo), "datL" (mono or full interleave), "datR" (full interleave), "data" equivalents */ vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c new file mode 100644 index 000000000..27495f354 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -0,0 +1,889 @@ +#include "meta.h" +#include "../coding/coding.h" + + +typedef enum { UBI_ADPCM, RAW_PCM, RAW_PSX, RAW_DSP, RAW_XBOX, FMT_VAG, FMT_AT3, FMT_OGG } ubi_sb_codec; +typedef struct { + int big_endian; + int total_streams; + int is_external; + int autodetect_external; + ubi_sb_codec codec; + + /* main/fixed info */ + uint32_t version; + size_t section1_num; + size_t section2_num; + size_t section3_num; + size_t extra_size; + int flag1; + int flag2; + + /* stream info config (format varies slightly per game) */ + size_t section1_entry_size; + size_t section2_entry_size; + size_t section3_entry_size; + off_t external_flag_offset; + off_t num_samples_offset; + off_t sample_rate_offset; + off_t channels_offset; + off_t stream_type_offset; + off_t stream_name_offset; + off_t extra_name_offset; + size_t stream_name_size; + size_t stream_id_offset; + int has_short_channels; + int has_internal_names; + int has_extra_name_flag; + int has_rotating_ids; + + /* derived */ + size_t main_size; + size_t section1_size; + size_t section2_size; + size_t section3_size; + + /* stream info */ + uint32_t header_id; + uint32_t header_type; + size_t stream_size; + off_t extra_offset; + off_t stream_offset; + uint32_t stream_id; + + int stream_samples; /* usually only for external resources */ + int sample_rate; + int channels; + uint32_t stream_type; + char stream_name[255]; + + +} ubi_sb_header; + +static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile); +static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile); + + +/* .SBx - banks from Ubisoft's sound engine ("DARE" / "UbiSound Driver") games in ~2000-2008 */ +VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE *streamData = NULL; + off_t start_offset; + int loop_flag = 0; + ubi_sb_header sb = {0}; + + /* check extension (number represents the platform, see later) */ + if ( !check_extensions(streamFile,"sb0,sb1,sb2,sb3,sb4,sb5,sb6,sb7") ) + goto fail; + + + /* .sb0 (sound bank) is a small multisong format (loaded in memory?) that contains SFX data + * but can also reference .ss0/ls0 (sound stream) external files for longer streams. + * A companion .sp0 (sound project) describes files and if it uses BANKs (.sb0) or MAPs (.sm0). */ + + /* main parse */ + if ( !parse_sb_header(&sb, streamFile) ) + goto fail; + + + /* open external stream if needed */ + if (sb.autodetect_external) { /* works most of the time but could give false positives */ + VGM_LOG("UBI SB: autodetecting external stream '%s'\n", sb.stream_name); + + streamData = open_stream_name(streamFile,sb.stream_name); + if (!streamData) { + streamData = streamFile; /* assume internal */ + if (sb.stream_size > get_streamfile_size(streamData)) { + VGM_LOG("UBI SB: expected external stream\n"); + goto fail; + } + } else { + sb.is_external = 1; + } + } + else if (sb.is_external) { + streamData = open_stream_name(streamFile,sb.stream_name); + if (!streamData) { + VGM_LOG("UBI SB: external stream '%s' not found\n", sb.stream_name); + goto fail; + } + } + else { + streamData = streamFile; + } + + /* final offset */ + if (sb.is_external) { + start_offset = sb.stream_offset; + } else { + start_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_size + sb.section3_size; + start_offset += sb.stream_offset; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(sb.channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sb.sample_rate; + vgmstream->num_streams = sb.total_streams; + vgmstream->meta_type = meta_UBI_SB; + + + switch(sb.codec) { + case UBI_ADPCM: { + vgmstream->coding_type = coding_UBI_IMA; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = ubi_ima_bytes_to_samples(sb.stream_size, sb.channels, streamData, start_offset); + break; + } + + case RAW_PCM: + vgmstream->coding_type = coding_PCM16LE; /* always LE even on Wii */ + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + vgmstream->num_samples = pcm_bytes_to_samples(sb.stream_size, sb.channels, 16); + break; + + case RAW_PSX: + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = sb.stream_size / sb.channels; + vgmstream->num_samples = ps_bytes_to_samples(sb.stream_size, sb.channels) ; + break; + + case RAW_XBOX: + vgmstream->coding_type = coding_XBOX; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = ms_ima_bytes_to_samples(sb.stream_size, 0x24*sb.channels,sb.channels); + break; + + case RAW_DSP: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = sb.stream_size / sb.channels; + vgmstream->num_samples = dsp_bytes_to_samples(sb.stream_size, sb.channels); + + { + off_t coefs_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_offset; + coefs_offset += 0x10; /* entry size is 0x40 (first/last 0x10 = unknown), per channel */ + + dsp_read_coefs_be(vgmstream,streamFile,coefs_offset, 0x40); + } + break; + + case FMT_VAG: + /* skip VAG header (some sb4 use VAG and others raw PSX) */ + if (read_32bitBE(start_offset, streamData) == 0x56414770) { /* "VAGp" */ + start_offset += 0x30; + sb.stream_size -= 0x30; + } + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = sb.stream_size / sb.channels; + vgmstream->num_samples = ps_bytes_to_samples(sb.stream_size, sb.channels); + + break; + +#ifdef VGM_USE_FFMPEG + case FMT_AT3: { + ffmpeg_codec_data *ffmpeg_data; + + /* skip weird value (3, 4) in Brothers in Arms: D-Day (PSP) */ + if (read_32bitBE(start_offset+0x04,streamData) == 0x52494646) { + start_offset += 0x04; + sb.stream_size -= 0x04; + } + + ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb.stream_size); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + if (sb.stream_samples == 0) /* sometimes not known */ + sb.stream_samples = ffmpeg_data->totalSamples; + vgmstream->num_samples = sb.stream_samples; + if (sb.stream_samples != ffmpeg_data->totalSamples) { + VGM_LOG("UBI SB: header samples differ (%i vs %i)\n", sb.stream_samples, (size_t)ffmpeg_data->totalSamples); + goto fail; + } + + /* manually read skip_samples if FFmpeg didn't do it */ + if (ffmpeg_data->skipSamples <= 0) { + off_t chunk_offset; + size_t chunk_size, fact_skip_samples = 0; + if (!find_chunk_le(streamData, 0x66616374,start_offset+0xc,0, &chunk_offset,&chunk_size)) /* find "fact" */ + goto fail; + if (chunk_size == 0x8) { + fact_skip_samples = read_32bitLE(chunk_offset+0x4, streamData); + } else if (chunk_size == 0xc) { + fact_skip_samples = read_32bitLE(chunk_offset+0x8, streamData); + } + ffmpeg_set_skip_samples(ffmpeg_data, fact_skip_samples); + } + break; + } + + case FMT_OGG: { + ffmpeg_codec_data *ffmpeg_data; + + ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb.stream_size); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = sb.stream_samples; /* ffmpeg_data->totalSamples */ + VGM_ASSERT(sb.stream_samples != ffmpeg_data->totalSamples, "UBI SB: header samples differ\n"); + break; + } + +#endif + default: + VGM_LOG("UBI SB: unknown codec\n"); + goto fail; + } + + if (sb.has_internal_names || sb.is_external) { + strcpy(vgmstream->stream_name, sb.stream_name); + } + + + /* open the file for reading (can be an external stream, different from the current .sb0) */ + if ( !vgmstream_open_stream(vgmstream, streamData, start_offset) ) + goto fail; + + if (sb.is_external && streamData) close_streamfile(streamData); + return vgmstream; + +fail: + if (sb.is_external && streamData) close_streamfile(streamData); + close_vgmstream(vgmstream); + return NULL; + +} + + +static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + int i, ok, current_type = -1, current_id = -1; + int target_stream = streamFile->stream_index; + + if (target_stream == 0) target_stream = 1; + + sb->big_endian = check_extensions(streamFile, "sb3,sb6,sb7"); /* GC, PS3, Wii */ + if (sb->big_endian) { + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + /* file layout is: base header, section1, section2, extra section, section3, data (all except base header can be null) */ + + sb->version = read_32bit(0x00, streamFile); /* 16b+16b major/minor version */ + sb->section1_num = read_32bit(0x04, streamFile); /* group headers? */ + sb->section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */ + sb->section3_num = read_32bit(0x0c, streamFile); /* internal streams table */ + sb->extra_size = read_32bit(0x10, streamFile); /* extra table, unknown (config for non-audio types) except with DSP = coefs */ + sb->flag1 = read_32bit(0x14, streamFile); /* unknown, usually -1 but can be others (0/1/2/etc) */ + sb->flag2 = read_32bit(0x18, streamFile); /* unknown, usually -1 but can be others */ + + ok = config_sb_header_version(sb, streamFile); + if (!ok) { + VGM_LOG("UBI SB: unknown SB version+platform\n"); + goto fail; + } + + sb->main_size = 0x1c; + sb->section1_size = sb->section1_entry_size * sb->section1_num; + sb->section2_size = sb->section2_entry_size * sb->section2_num; + sb->section3_size = sb->section3_entry_size * sb->section3_num; + + /* find target stream info in section2 */ + for (i = 0; i < sb->section2_num; i++) { + off_t offset = sb->main_size + sb->section1_size + sb->section2_entry_size*i; + + /* ignore non-audio entry (other types seem to have config data) */ + if (read_32bit(offset + 0x04, streamFile) != 0x01) + continue; + + /* weird case when there is no internal substream ID and just seem to rotate every time type changes, joy */ + if (sb->has_rotating_ids) { /* assumes certain configs can't happen in this case */ + int current_is_external = 0; + int type = read_32bit(offset + sb->stream_type_offset, streamFile); + + if (current_type == -1) + current_type = type; + if (current_id == -1) /* use first ID in section3 */ + current_id = read_32bit(sb->main_size + sb->section1_size + sb->section2_size + sb->extra_size + 0x00, streamFile); + + if (sb->external_flag_offset) { + current_is_external = read_32bit(offset + sb->external_flag_offset, streamFile); + } else if (sb->has_extra_name_flag && read_32bit(offset + sb->extra_name_offset, streamFile) != 0xFFFFFFFF) { + current_is_external = 1; /* -1 in extra_name means internal */ + } + + + if (!current_is_external) { + if (current_type != type) { + current_type = type; + current_id++; /* rotate */ + if (current_id >= sb->section3_num) + current_id = 0; /* reset */ + } + + } + } + + /* update streams (total_stream also doubles as current) */ + sb->total_streams++; + if (sb->total_streams != target_stream) + continue; + //;VGM_LOG("target at offset=%lx (size=%x)\n", offset, sb->section2_entry_size); + + sb->header_id = read_32bit(offset + 0x00, streamFile); /* 16b+16b group+sound id */ + sb->header_type = read_32bit(offset + 0x04, streamFile); + sb->stream_size = read_32bit(offset + 0x08, streamFile); + sb->extra_offset = read_32bit(offset + 0x0c, streamFile); /* within the extra section */ + sb->stream_offset = read_32bit(offset + 0x10, streamFile); /* within the data section */ + sb->channels = (sb->has_short_channels) ? + (uint16_t)read_16bit(offset + sb->channels_offset, streamFile) : + (uint32_t)read_32bit(offset + sb->channels_offset, streamFile); + sb->sample_rate = read_32bit(offset + sb->sample_rate_offset, streamFile); + sb->stream_type = read_32bit(offset + sb->stream_type_offset, streamFile); + + if (sb->num_samples_offset) + sb->stream_samples = read_32bit(offset + sb->num_samples_offset, streamFile); + + if (sb-> has_rotating_ids) { + sb->stream_id = current_id; + } else if (sb->stream_id_offset) { + sb->stream_id = read_32bit(offset + sb->stream_id_offset, streamFile); + } + + /* external stream name can be found in the header (first versions) or the extra table (later versions) */ + if (sb->stream_name_offset) { + read_string(sb->stream_name, sb->stream_name_size, offset + sb->stream_name_offset, streamFile); + } else { + sb->stream_name_offset = read_32bit(offset + sb->extra_name_offset, streamFile); + read_string(sb->stream_name, sb->stream_name_size, sb->main_size + sb->section1_size + sb->section2_size + sb->stream_name_offset, streamFile); + } + + /* not always set and must be derived */ + if (sb->external_flag_offset) { + sb->is_external = read_32bit(offset + sb->external_flag_offset, streamFile); + } else if (sb->has_extra_name_flag && read_32bit(offset + sb->extra_name_offset, streamFile) != 0xFFFFFFFF) { + sb->is_external = 1; /* -1 in extra_name means internal */ + } else if (sb->section3_num == 0) { + sb->is_external = 1; + } else { + sb->autodetect_external = 1; + + if (sb->stream_name[0] == '\0') + sb->autodetect_external = 0; /* no name */ + if (sb->extra_size > 0 && sb->stream_name_offset > sb->extra_size) + sb->autodetect_external = 0; /* name outside extra table == is internal */ + } + } + if (sb->total_streams == 0) { + VGM_LOG("UBI SB: no streams\n"); + goto fail; + } + if (target_stream < 0 || target_stream > sb->total_streams || sb->total_streams < 1) { + VGM_LOG("UBI SB: wrong target stream (target=%i, total=%i)\n", target_stream, sb->total_streams); + goto fail; + } + + if (!(sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) { + VGM_LOG("UBI SB: unexpected number of internal streams %i\n", sb->section3_num); + goto fail; + } + + + /* happens in some versions */ + if (sb->stream_type > 0xFF) { + VGM_LOG("UBI SB: garbage in stream_type\n"); + sb->stream_type = 0; + } + + /* guess codec */ + switch(sb->stream_type) { + case 0x00: /* platform default (rarely external) */ + if ( check_extensions(streamFile, "sb0")) { + sb->codec = RAW_PCM; + } else if (check_extensions(streamFile, "sb1,sb5")) { + sb->codec = RAW_PSX; + } else if (check_extensions(streamFile, "sb2")) { + sb->codec = RAW_XBOX; + } else if (check_extensions(streamFile, "sb3,sb7")) { + sb->codec = RAW_DSP; + } else if (check_extensions(streamFile, "sb4")) { + sb->codec = FMT_VAG; + } else { + VGM_LOG("UBI SB: unknown internal format\n"); + goto fail; + } + break; + + case 0x01: /* PCM (Wii, rarely used) */ + sb->codec = RAW_PCM; + break; + + case 0x03: /* Ubi ADPCM (main external stream codec, has subtypes) */ + sb->codec = UBI_ADPCM; + break; + + case 0x04: /* Ogg (later PC games) */ + sb->codec = FMT_OGG; + break; + + case 0x05: /* AT3 (PSP, PS3) */ + sb->codec = FMT_AT3; + break; + + default: + VGM_LOG("UBI SB: unknown stream_type %x\n", sb->stream_type); + goto fail; + } + + /* uncommon but possible */ + //VGM_ASSERT(sb->is_external && sb->section3_num != 0, "UBI SS: mixed external and internal streams\n"); + + /* seems that can be safely ignored */ + //VGM_ASSERT(sb->is_external && sb->stream_id_offset && sb->stream_id > 0, "UBI SB: unexpected external stream with stream id\n"); + + /* section 3: substreams within the file, adjust stream offset (rarely used but table is always present) */ + if (!sb->is_external && (sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) { + for (i = 0; i < sb->section3_num; i++) { + off_t offset = sb->main_size + sb->section1_size + sb->section2_size + sb->extra_size + sb->section3_entry_size * i; + + /* table has unordered ids+size, so if our id doesn't match current data offset must be beyond */ + if (read_32bit(offset + 0x00, streamFile) == sb->stream_id) + break; + sb->stream_offset += read_32bit(offset + 0x04, streamFile); + } + } + + return 1; +fail: + return 0; +} + + +static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) { + /* meh... */ + int is_sb0 = check_extensions(streamFile, "sb0"); /* PC */ + int is_sb1 = check_extensions(streamFile, "sb1"); /* PS2 */ + int is_sb2 = check_extensions(streamFile, "sb2"); /* Xbox */ + int is_sb3 = check_extensions(streamFile, "sb3"); /* GC */ + int is_sb4 = check_extensions(streamFile, "sb4"); /* PSP, X360? */ + int is_sb5 = check_extensions(streamFile, "sb5"); /* PSP, 3DS? */ + //int is_sb6 = check_extensions(streamFile, "sb6"); /* PS3? */ + int is_sb7 = check_extensions(streamFile, "sb7"); /* Wii */ + int is_biadd_psp = 0; + + + /* The format varies with almost every game + platform (some kind of class serialization?), + * support is done case-by-case as offsets move slightly. Basic layout: + * - fixed part (0x00..0x14) + * - garbage, flags + * - external stream number of samples / internal garbage + * - external stream size (also in the common part) / internal garbage + * - garbage + * - external original sample rate / internal garbage + * - sample rate, pcm bits?, channels + * - stream type and external filename (internal filename too on some platforms) + * - end flags/garbage + * Garbage looks like uninitialized variables (may be null, contain part of strings, etc). + * Later version don't have filename per header but in the extra section. + */ + + + /* common */ + sb->section3_entry_size = 0x08; + sb->stream_name_size = 0x24; /* maybe 0x28 or 0x20 for some but ok enough (null terminated) */ + + /* Prince of Persia: Sands of Time (2003)(PC) */ + if ((sb->version == 0x000A0002 && is_sb0) || /* (not sure if exists, just in case) */ + (sb->version == 0x000A0004 && is_sb0)) { /* main game */ + sb->section1_entry_size = 0x64; + sb->section2_entry_size = 0x80; + + sb->external_flag_offset = 0x24; /* maybe 0x28 */ + sb->num_samples_offset = 0x30; + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4a; + sb->stream_type_offset = 0x4c; + sb->stream_name_offset = 0x50; + + sb->has_short_channels = 1; + sb->has_internal_names = 1; + return 1; + } + + /* Prince of Persia: Sands of Time (2003)(PS2) */ + if ((sb->version == 0x000A0002 && is_sb1) || /* Prince of Persia 1 port */ + (sb->version == 0x000A0004 && is_sb1)) { /* main game */ + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x6c; + + sb->external_flag_offset = 0; /* no apparent flag */ + sb->channels_offset = 0x20; + sb->sample_rate_offset = 0x24; + sb->num_samples_offset = 0x30; + sb->stream_name_offset = 0x40; + sb->stream_type_offset = 0x68; + + return 1; + } + + /* Prince of Persia: Sands of Time (2003)(Xbox) */ + if ((sb->version == 0x000A0002 && is_sb2) || /* Prince of Persia 1 port */ + (sb->version == 0x000A0004 && is_sb2)) { /* main game */ + sb->section1_entry_size = 0x64; + sb->section2_entry_size = 0x78; + + sb->external_flag_offset = 0x24; /* maybe 0x28 */ + sb->num_samples_offset = 0x30; + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4a; + sb->stream_type_offset = 0x4c; /* may contain garbage */ + sb->stream_name_offset = 0x50; + + sb->has_short_channels = 1; + sb->has_internal_names = 1; + return 1; + } + + /* Tom Clancy's Rainbow Six 3 (2003)(PS2) */ + if (sb->version == 0x000A0007 && is_sb1) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x6c; + + sb->external_flag_offset = 0; /* no apparent flag */ + sb->channels_offset = 0x20; + sb->sample_rate_offset = 0x24; + sb->num_samples_offset = 0x30; + sb->stream_name_offset = 0x40; + sb->stream_type_offset = 0x68; + + return 1; + } + + /* Prince of Persia: Sands of Time (2003)(GC) */ + if ((sb->version == 0x000A0002 && is_sb3) || /* Prince of Persia 1 port */ + (sb->version == 0x000A0004 && is_sb3)) { /* main game */ + sb->section1_entry_size = 0x64; + sb->section2_entry_size = 0x74; + + sb->external_flag_offset = 0x20; /* maybe 0x24 */ + sb->num_samples_offset = 0x2c; + sb->sample_rate_offset = 0x40; + sb->channels_offset = 0x46; + sb->stream_type_offset = 0x48; + sb->stream_name_offset = 0x4c; + + sb->has_short_channels = 1; + return 1; + } + + /* Myst IV Demo (2004)(PC) (final game is different) */ + if (sb->version == 0x00100000 && is_sb0) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0xa4; + + sb->external_flag_offset = 0x24; + sb->num_samples_offset = 0x34; + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4c; + sb->stream_type_offset = 0x50; + sb->stream_name_offset = 0x54; + + sb->has_internal_names = 1; + return 1; + } + + /* Prince of Persia: Warrior Within (2004)(PC) */ + if (sb->version == 0x00120009 && is_sb0) { + sb->section1_entry_size = 0x6c; + sb->section2_entry_size = 0x84; + + sb->external_flag_offset = 0x24; + sb->num_samples_offset = 0x30; + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4c; + sb->stream_type_offset = 0x50; + sb->stream_name_offset = 0x54; + + sb->has_internal_names = 1; + return 1; + } + + /* Prince of Persia: Warrior Within (2004)(PS2) */ + if (sb->version == 0x00120009 && is_sb1) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x6c; + + sb->external_flag_offset = 0; /* no apparent flag */ + sb->channels_offset = 0x20; + sb->sample_rate_offset = 0x24; + sb->num_samples_offset = 0x30; + sb->stream_name_offset = 0x40; + sb->stream_type_offset = 0x68; + + return 1; + } + + /* Prince of Persia: Warrior Within (2004)(Xbox) */ + if (sb->version == 0x00120009 && is_sb2) { + sb->section1_entry_size = 0x6c; + sb->section2_entry_size = 0x90; + + sb->external_flag_offset = 0x24; + sb->num_samples_offset = 0x44; + sb->sample_rate_offset = 0x58; + sb->channels_offset = 0x60; + sb->stream_type_offset = 0x64; /* may contain garbage */ + sb->stream_name_offset = 0x68; + + sb->has_internal_names = 1; + return 1; + } + + /* Prince of Persia: Warrior Within (2004)(GC) */ + if (sb->version == 0x00120009 && is_sb3) { + sb->section1_entry_size = 0x6c; + sb->section2_entry_size = 0x78; + + sb->external_flag_offset = 0x20; + sb->num_samples_offset = 0x2c; + sb->sample_rate_offset = 0x40; + sb->channels_offset = 0x48; + sb->stream_type_offset = 0x4c; + sb->stream_name_offset = 0x50; + + return 1; + } + + /* two games with same id; use project file as identifier */ + if (sb->version == 0x0012000C && is_sb4) { + STREAMFILE * streamTest = open_stream_name(streamFile, "BIAAUDIO.SP4"); + if (streamTest) { + is_biadd_psp = 1; + close_streamfile(streamTest); + } + } + + /* Prince of Persia: Revelations (2005)(PSP) */ + if (sb->version == 0x0012000C && is_sb4 && !is_biadd_psp) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x84; + + sb->external_flag_offset = 0x24; + sb->num_samples_offset = 0x30; + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4c; + sb->stream_type_offset = 0x50; + sb->stream_name_offset = 0x54; + + sb->has_internal_names = 1; + return 1; + } + + /* Brothers in Arms - D-Day (2006)(PSP) */ + if (sb->version == 0x0012000C && is_sb4 && is_biadd_psp) { + sb->section1_entry_size = 0x80; + sb->section2_entry_size = 0x94; + + sb->stream_id_offset = 0x0; //todo 0x1C or 0x20? table seems problematic + sb->external_flag_offset = 0x24; + sb->num_samples_offset = 0; /* variable? */ + sb->sample_rate_offset = 0x44; + sb->channels_offset = 0x4c; + sb->stream_type_offset = 0x50; + sb->stream_name_offset = 0x54; + + sb->has_internal_names = 1; + return 1; + } + + /* Prince of Persia: The Two Thrones (2005)(PC) */ + if (sb->version == 0x00150000 && is_sb0) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x78; + + sb->external_flag_offset = 0x2c; + sb->stream_id_offset = 0x34; + sb->num_samples_offset = 0x40; + sb->sample_rate_offset = 0x54; + sb->channels_offset = 0x5c; + sb->stream_type_offset = 0x60; + sb->extra_name_offset = 0x64; + + sb->has_extra_name_flag = 1; + return 1; + } + + /* Prince of Persia: The Two Thrones (2005)(PS2) */ + if (sb->version == 0x00150000 && is_sb1) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x5c; + + sb->external_flag_offset = 0; + sb->channels_offset = 0x2c; + sb->sample_rate_offset = 0x30; + sb->num_samples_offset = 0x3c; + sb->extra_name_offset = 0x4c; + sb->stream_type_offset = 0x50; + + sb->has_extra_name_flag = 1; + return 1; + } + + /* Prince of Persia: The Two Thrones (2005)(Xbox) */ + if (sb->version == 0x00150000 && is_sb2) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x58; + + sb->external_flag_offset = 0; + sb->num_samples_offset = 0x28; + sb->stream_id_offset = 0; + sb->sample_rate_offset = 0x3c; + sb->channels_offset = 0x44; + sb->stream_type_offset = 0x48; + sb->extra_name_offset = 0x4c; + + sb->has_extra_name_flag = 1; + sb->has_rotating_ids = 1; + return 1; + } + + /* Prince of Persia: The Two Thrones (2005)(GC) */ + if (sb->version == 0x00150000 && is_sb3) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x6c; + + sb->external_flag_offset = 0x28; /* maybe 0x2c */ + sb->num_samples_offset = 0x3c; + sb->sample_rate_offset = 0x50; + sb->channels_offset = 0x58; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x60; + + return 1; + } + + /* Prince of Persia: Rival Swords (2007)(PSP) */ + if (sb->version == 0x00180005 && is_sb5) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x54; + + sb->external_flag_offset = 0; + sb->channels_offset = 0x28; + sb->sample_rate_offset = 0x2c; + //sb->num_samples_offset = 0x34 or 0x3c /* varies */ + sb->extra_name_offset = 0x44; + sb->stream_type_offset = 0x48; + + sb->has_extra_name_flag = 1; + return 1; + } + +#if 0 + /* Rainbow Six Vegas (2007)(PSP) */ + if (sb->version == 0x00180006 && is_sb5) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x54; + + sb->external_flag_offset = 0; + sb->channels_offset = 0x28; + sb->sample_rate_offset = 0x2c; + //sb->num_samples_offset = 0x34 or 0x3c /* varies */ + sb->extra_name_offset = 0x44; + sb->stream_type_offset = 0x48; + + sb->has_extra_name_flag = 1; + sb->has_rotating_ids = 1; + return 1; + } + + /* todo Rainbow Six Vegas changes: + * some streams use type 0x06 instead of 0x01, known values: + * 0x0c: header offset in extra table? + * 0x2c: stream size + * 0x30: stream offset + * most other fields are fixed, comparing different files + * header is in the extra table, after the stream name (repeated?) + * (0x04: sample rate, 0x0c: channels, etc) + * stream data may be newer Ubi ADPCM (see DecUbiSnd) + */ +#endif + + /* Red Steel (2006)(Wii) */ + if (sb->version == 0x00180006 && is_sb7) { /* same as 0x00150000 */ + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x6c; + + sb->external_flag_offset = 0x28; /* maybe 0x2c */ + sb->num_samples_offset = 0x3c; + sb->sample_rate_offset = 0x50; + sb->channels_offset = 0x58; + sb->stream_type_offset = 0x5c; + sb->extra_name_offset = 0x60; + + return 1; + } + + /* Prince of Persia: Rival Swords (2007)(Wii) */ + if (sb->version == 0x00190003 && is_sb7) { + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x70; + + sb->external_flag_offset = 0x28; /* maybe 0x2c */ + sb->channels_offset = 0x3c; + sb->sample_rate_offset = 0x40; + sb->num_samples_offset = 0x48; + sb->extra_name_offset = 0x58; + sb->stream_type_offset = 0x5c; + + return 1; + } + + /* TMNT (2007)(PS2) */ + if (sb->version == 0x00190002 && is_sb1) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x5c; + + sb->external_flag_offset = 0; + sb->channels_offset = 0x28; + sb->sample_rate_offset = 0x2c; + //sb->num_samples_offset = 0x34 or 0x3c /* varies */ + sb->extra_name_offset = 0x44; + sb->stream_type_offset = 0x48; + + sb->has_extra_name_flag = 1; + return 1; + } + + /* TMNT (2007)(GC) */ + if (sb->version == 0x00190002 && is_sb3) { /* same as 0x00190003 */ + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x6c; + + 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; + + return 1; + } + + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vawx.c b/Frameworks/vgmstream/vgmstream/src/meta/vawx.c index befdaef21..a7d3347b2 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vawx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vawx.c @@ -1,4 +1,5 @@ #include "meta.h" +#include "../layout/layout.h" #include "../coding/coding.h" @@ -37,12 +38,11 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { switch(type) { case 2: /* VAG */ vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; + vgmstream->layout_type = channel_count == 6 ? layout_blocked_vawx : layout_interleave ; vgmstream->interleave_block_size = 0x10; vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile); - /* todo 6ch has 0x8000 blocks and must skip last 0x20 each block (or, skip 0x20 every 0x1550*6 */ break; @@ -110,6 +110,9 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) goto fail; + if (vgmstream->layout_type == layout_blocked_vawx) + block_update_vawx(start_offset,vgmstream); + return vgmstream; fail: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vsf.c b/Frameworks/vgmstream/vgmstream/src/meta/vsf.c index 002ad070b..36047ecef 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vsf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vsf.c @@ -66,67 +66,3 @@ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; } - -/* VSF with SMSS header (from Tiny Toon Adventures: Defenders of the Universe */ -VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("vsf",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x534D5353) /* "SMSS" */ - goto fail; - - - loop_flag = read_32bitLE(0x18,streamFile); - channel_count = read_32bitLE(0x0c,streamFile); - - /* 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_PSX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*2)*28/16/channel_count; - vgmstream->loop_end_sample = (read_32bitLE(0x1c,streamFile)*2)*28/16/channel_count; - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile); - vgmstream->meta_type = meta_PS2_VSF_TTA; - - /* 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; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - 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/vsf_tta.c b/Frameworks/vgmstream/vgmstream/src/meta/vsf_tta.c new file mode 100644 index 000000000..03ba72fff --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/vsf_tta.c @@ -0,0 +1,66 @@ +#include "meta.h" + + +/* VSF with SMSS header (from Tiny Toon Adventures: Defenders of the Universe) */ +VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vsf",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x534D5353) /* "SMSS" */ + goto fail; + + + loop_flag = read_32bitLE(0x18,streamFile); + channel_count = read_32bitLE(0x0c,streamFile); + + /* 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_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*2)*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x1c,streamFile)*2)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile); + vgmstream->meta_type = meta_PS2_VSF_TTA; + + /* 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; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + 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/vxn.c b/Frameworks/vgmstream/vgmstream/src/meta/vxn.c new file mode 100644 index 000000000..238d3e24f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/vxn.c @@ -0,0 +1,109 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* VXN - from Gameloft mobile games */ +VGMSTREAM * init_vgmstream_vxn(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + int loop_flag = 0, channel_count, codec, sample_rate, block_align, bits, num_samples; + off_t start_offset, stream_offset, chunk_offset, first_offset = 0x00; + size_t stream_size; + int total_streams, target_stream = streamFile->stream_index; + + /* check extensions */ + if (!check_extensions(streamFile,"vxn")) + goto fail; + + /* check header/version chunk (RIFF-like format with many custom chunks) */ + if (read_32bitBE(0x00,streamFile) != 0x566F784E) /* "VoxN" */ + goto fail; + if (read_32bitLE(0x10,streamFile) != get_streamfile_size(streamFile) ) + goto fail; + + if (!find_chunk_le(streamFile, 0x41666D74,first_offset,0, &chunk_offset,NULL)) /* "Afmt" */ + goto fail; + codec = (uint16_t)read_16bitLE(chunk_offset+0x00, streamFile); + channel_count = (uint16_t)read_16bitLE(chunk_offset+0x02, streamFile); + sample_rate = read_32bitLE(chunk_offset+0x04, streamFile); + block_align = (uint16_t)read_16bitLE(chunk_offset+0x08, streamFile); + bits = (uint16_t)read_16bitLE(chunk_offset+0x0a, streamFile); + + /* files are divided into segment subsongs, often a leadout and loop in that order + * (the "Plst" and "Rule" chunks may have order info) */ + if (!find_chunk_le(streamFile, 0x5365676D,first_offset,0, &chunk_offset,NULL)) /* "Segm" */ + goto fail; + total_streams = read_32bitLE(chunk_offset+0x00, streamFile); + if (target_stream == 0) target_stream = 1; + if (target_stream < 0 || target_stream > total_streams || total_streams < 1) goto fail; + + stream_offset = read_32bitLE(chunk_offset+0x04 + (target_stream-1)*0x18 + 0x00, streamFile); + stream_size = read_32bitLE(chunk_offset+0x04 + (target_stream-1)*0x18 + 0x04, streamFile); + num_samples = read_32bitLE(chunk_offset+0x04 + (target_stream-1)*0x18 + 0x08, streamFile); + + if (!find_chunk_le(streamFile, 0x44617461,first_offset,0, &chunk_offset,NULL)) /* "Data" */ + goto fail; + start_offset = chunk_offset + stream_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->num_streams = total_streams; + + vgmstream->meta_type = meta_VXN; + + switch (codec) { + case 0x0001: /* PCM */ + if (bits != 16) goto fail; + + vgmstream->coding_type = coding_PCM16LE; + vgmstream->interleave_block_size = block_align; + vgmstream->layout_type = layout_interleave; + break; + + case 0x0002: /* MSADPCM (ex. Asphalt 7) */ + if (bits != 4) goto fail; + + vgmstream->coding_type = coding_MSADPCM; + vgmstream->interleave_block_size = block_align; + vgmstream->layout_type = layout_none; + break; + + case 0x0011: /* MS-IMA (ex. Asphalt 6) */ + if (bits != 16) goto fail; + + vgmstream->coding_type = coding_MS_IMA; + vgmstream->interleave_block_size = block_align; + vgmstream->layout_type = layout_none; + break; + +#ifdef VGM_USE_FFMPEG + case 0x0800: { /* Musepack (ex. Asphalt Xtreme) */ + ffmpeg_codec_data * ffmpeg_data = NULL; + if (bits != 0xFFFF) goto fail; + + ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } +#endif + + default: + VGM_LOG("VXN: unknown codec 0x%02x\n", codec); + goto fail; + } + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wpd.c b/Frameworks/vgmstream/vgmstream/src/meta/wpd.c index 3bb37a2d4..21d81ceec 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wpd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wpd.c @@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_wpd(STREAMFILE *streamFile) { char filename[PATH_LIMIT]; off_t start_offset; int channel_count; - int loop_flag; + int loop_flag; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); @@ -17,8 +17,8 @@ VGMSTREAM * init_vgmstream_wpd(STREAMFILE *streamFile) { if (read_32bitBE(0x00,streamFile) != 0x20445057) /* " DPW" */ goto fail; - channel_count = read_32bitLE(0x4,streamFile); - loop_flag = 0; + channel_count = read_32bitLE(0x4,streamFile); + loop_flag = 0; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ws_aud.c b/Frameworks/vgmstream/vgmstream/src/meta/ws_aud.c index 01effa480..cd13606c4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ws_aud.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ws_aud.c @@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE *streamFile) { if (bytes_per_sample != 1) goto fail; break; case 99: /* IMA ADPCM */ - coding_type = coding_IMA; + coding_type = coding_IMA_int; break; default: goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c index ace0ca29b..b871da8ab 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c @@ -128,8 +128,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { } /* other Wwise specific: */ - //"JUNK": optional padding so that raw data starts in an offset multiple of 0x10 (0-size JUNK exists too) - //"akd ": unknown (IMA/PCM; "audiokinetic data"?) + //"JUNK": optional padding for usually aligment (0-size JUNK exists too) + //"akd ": seem to store extra info for Wwise editor (wave peaks/loudness/HDR envelope?) } /* format to codec */ @@ -158,7 +158,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { ww.codec = DSP; } - /* Some Wwise files (ex. Oddworld PSV, Bayonetta 2 WiiU sfx) are truncated mirrors of another file. + /* Some Wwise files (ex. Oddworld PSV, Bayonetta 2 WiiU, often in BGM.bnk) are truncated mirrors of another file. * They come in RAM banks, probably to play the beginning while the rest of the real stream loads. * We'll add basic support to avoid complaints of this or that .wem not playing */ if (ww.data_size > ww.file_size) { @@ -560,50 +560,50 @@ fail: 0x00 (4): num_samples 0x04 (4): skip samples? 0x08 (4): ? (small if loop, 0 otherwise) -0x0c (4): loop offset after seek table+setup (offset after setup if file doesn't loop) +0x0c (4): data start offset after seek table+setup, or loop start when "smpl" is present 0x10 (4): ? (small, 0..~0x400) 0x14 (4): approximate data size without seek table? (almost setup+packets) 0x18 (4): setup_offset within data (0 = no seek table) 0x1c (4): audio_offset within data -0x20 (4): biggest packet size (not including header)? -0x24 (4): ? (mid, 0~0x5000) -0x28 (4): ? (mid, 0~0x5000) -0x2c (4): parent bank/event id? (shared by several .wem a game, but not all need to share it) +0x20 (2): biggest packet size (not including header)? +0x22 (2): ? (small, N..~0x100) uLastGranuleExtra? +0x24 (4): ? (mid, 0~0x5000) dwDecodeAllocSize? +0x28 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize? +0x2c (4): parent bank/event id? uHashCodebook? (shared by several .wem a game, but not all need to share it) 0x30 (1): blocksize_1_exp (small) 0x31 (1): blocksize_0_exp (large) 0x32 (2): empty "vorb" size 0x28 / 0x2a 0x00 (4): num_samples -0x04 (4): loop offset after seek table+setup (offset after setup if file doesn't loop) -0x08 (4): data size without seek table (setup+packets) +0x04 (4): data start offset after seek table+setup, or loop start when "smpl" is present +0x08 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present 0x0c (2): ? (small, 0..~0x400) 0x10 (4): setup_offset within data (0 = no seek table) 0x14 (4): audio_offset within data -0x18 (2): ? (small, 0..~0x400) -0x1a (2): ? (small, N..~0x100) -0x1c (4): ? (mid, 0~0x5000) -0x20 (4): ? (mid, 0~0x5000) -0x24 (4): parent bank/event id? (shared by several .wem a game, but not all need to share it) -0x28 (1): blocksize_1_exp (small) [removed when size is 0x28] -0x29 (1): blocksize_0_exp (large) [removed when size is 0x28] - +0x18 (2): biggest packet size (not including header)? +0x1a (2): ? (small, N..~0x100) uLastGranuleExtra? +0x1c (4): ? (mid, 0~0x5000) dwDecodeAllocSize? +0x20 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize? +0x24 (4): parent bank/event id? uHashCodebook? (shared by several .wem a game, but not all need to share it) +0x28 (1): blocksize_1_exp (small) [removed when size is 0x28] +0x29 (1): blocksize_0_exp (large) [removed when size is 0x28] - new format: "fmt" size 0x42, extra size 0x30 0x12 (2): flag? (00,10,18): not related to seek table, codebook type, chunk count, looping, etc 0x14 (4): channel config 0x18 (4): num_samples -0x1c (4): loop offset after seek table+setup (offset after setup if file doesn't loop) -0x20 (4): data size without seek table (setup+packets) +0x1c (4): data start offset after seek table+setup, or loop start when "smpl" is present +0x20 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present 0x24 (2): ?1 (small, 0..~0x400) 0x26 (2): ?2 (small, N..~0x100): not related to seek table, codebook type, chunk count, looping, packet size, samples, etc 0x28 (4): setup offset within data (0 = no seek table) 0x2c (4): audio offset within data 0x30 (2): biggest packet size (not including header) -0x32 (2): ?4 (small, 0..~0x100): may be same than ?2 (something related to the avg bitrate?) -0x34 (4): bitrate config? (mid, 0~0x5000) -0x38 (4): bitrate config? (mid, 0~0x5000) (2 byte with max/min?) +0x32 (2): (small, 0..~0x100) uLastGranuleExtra? +0x34 (4): ? (mid, 0~0x5000) dwDecodeAllocSize? +0x38 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize? 0x40 (1): blocksize_1_exp (small) 0x41 (1): blocksize_0_exp (large) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/x360_tra.c b/Frameworks/vgmstream/vgmstream/src/meta/x360_tra.c index 44bb321e0..b94189113 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/x360_tra.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/x360_tra.c @@ -36,7 +36,7 @@ VGMSTREAM * init_vgmstream_x360_tra(STREAMFILE *streamFile) { vgmstream->channels = 2; vgmstream->sample_rate = 24000; - vgmstream->coding_type = coding_DVI_IMA; + vgmstream->coding_type = coding_DVI_IMA_int; vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) - ((get_streamfile_size(streamFile)/0x204)*4)); vgmstream->layout_type = layout_tra_blocked; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c index 83c44fe64..403f0d98d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -25,7 +25,7 @@ static const int wma_block_align_index[17] = { }; -typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3 } xact_codec; +typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3, OGG } xact_codec; typedef struct { int little_endian; int version; @@ -124,8 +124,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { /* for Techland's XWB with no data */ if (xwb.base_offset == 0) goto fail; - /* some BlazBlue Centralfiction songs have padding after data size */ - if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile)) goto fail; /* read base entry (WAVEBANKDATA) */ off = xwb.base_offset; @@ -168,8 +166,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { xwb.loop_start = (uint32_t)read_32bit(off+0x0c, streamFile); xwb.loop_end = (uint32_t)read_32bit(off+0x10, streamFile);//length - - xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start); } else { uint32_t entry_info = (uint32_t)read_32bit(off+0x00, streamFile); @@ -190,9 +186,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { xwb.loop_start_sample = (uint32_t)read_32bit(off+0x10, streamFile); xwb.loop_end_sample = (uint32_t)read_32bit(off+0x14, streamFile) + xwb.loop_start_sample; } - - xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start) - && !(xwb.entry_flags & WAVEBANKENTRY_FLAGS_IGNORELOOP); } @@ -231,14 +224,17 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { case 1: xwb.codec = XBOX_ADPCM; break; default: goto fail; } - } else if (xwb.version <= XACT1_1_MAX) { + } + else if (xwb.version <= XACT1_1_MAX) { switch(xwb.tag){ case 0: xwb.codec = PCM; break; case 1: xwb.codec = XBOX_ADPCM; break; case 2: xwb.codec = WMA; break; + case 3: xwb.codec = OGG; break; /* extension */ default: goto fail; } - } else if (xwb.version <= XACT2_2_MAX) { + } + else if (xwb.version <= XACT2_2_MAX) { switch(xwb.tag) { case 0: xwb.codec = PCM; break; /* Table Tennis (v34): XMA1, Prey (v38): XMA2, v35/36/37: ? */ @@ -246,7 +242,8 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { case 2: xwb.codec = MS_ADPCM; break; default: goto fail; } - } else { + } + else { switch(xwb.tag) { case 0: xwb.codec = PCM; break; case 1: xwb.codec = XMA2; break; @@ -267,6 +264,26 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { xwb.num_samples = atrac3_bytes_to_samples(xwb.stream_size, xwb.block_align * xwb.channels); } + /* Oddworld: Stranger's Wrath iOS/Android format hijack, with changed meanings */ + if (xwb.codec == OGG) { + xwb.num_samples = xwb.stream_size / (2 * xwb.channels); /* uncompressed bytes */ + xwb.stream_size = xwb.loop_end; + xwb.loop_start = 0; + xwb.loop_end = 0; + } + + + /* test loop after the above fixes */ + xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start) + && !(xwb.entry_flags & WAVEBANKENTRY_FLAGS_IGNORELOOP); + + if (xwb.codec != OGG) { + /* for Oddworld OGG the data_size value is size of uncompressed bytes instead */ + /* some BlazBlue Centralfiction songs have padding after data size (maybe wrong rip?) */ + if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile)) + goto fail; + } + /* fix samples */ if (xwb.version <= XACT2_2_MAX && xwb.codec == PCM) { @@ -403,6 +420,10 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; + + /* no wma_bytes_to_samples, this should be ok */ + if (!vgmstream->num_samples) + vgmstream->num_samples = ffmpeg_data->totalSamples; break; } @@ -431,7 +452,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { break; } - case ATRAC3: { /* Techland extension */ + case ATRAC3: { /* Techland PS3 extension */ uint8_t buf[200]; int bytes; @@ -448,6 +469,15 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { vgmstream->layout_type = layout_none; break; } + + case OGG: { /* Oddworld: Strangers Wrath iOS/Android extension */ + vgmstream->codec_data = init_ffmpeg_offset(streamFile, xwb.stream_offset, xwb.stream_size); + if ( !vgmstream->codec_data ) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } + #endif default: @@ -511,7 +541,7 @@ typedef struct { /* try to find the stream name in a companion XSB file, a comically complex cue format. */ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_header * xwb, STREAMFILE *streamXwb) { - STREAMFILE *streamFile; + STREAMFILE *streamFile = NULL; int i,j, start_sound, cfg__start_sound = 0, cfg__selected_wavebank = 0; int xsb_version; off_t off, suboff, name_offset = 0; @@ -546,7 +576,7 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head /* read main header (SoundBankHeader) */ xsb_version = read_16bit(0x04, streamFile); if ((xwb->version <= XACT1_1_MAX && xsb_version > XSB_XACT1_MAX) || (xwb->version <= XACT2_2_MAX && xsb_version > XSB_XACT2_MAX)) { - VGM_LOG("XSB: xsb and xwb are from different XACT versions (xsb v%i vs xwb v%i)", xsb_version, xwb->version); + VGM_LOG("XSB: xsb and xwb are from different XACT versions (xsb v%i vs xwb v%i)\n", xsb_version, xwb->version); goto fail; } @@ -585,10 +615,10 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head } VGM_ASSERT(xsb.xsb_sounds_count < xwb->streams, - "XSB: number of streams in xsb lower than xwb (xsb %i vs xwb %i)", xsb.xsb_sounds_count, xwb->streams); + "XSB: number of streams in xsb lower than xwb (xsb %i vs xwb %i)\n", xsb.xsb_sounds_count, xwb->streams); VGM_ASSERT(xsb.xsb_simple_sounds_count + xsb.xsb_complex_sounds_count != xsb.xsb_sounds_count, - "XSB: number of xsb sounds doesn't match simple + complex sounds (simple %i, complex %i, total %i)", xsb.xsb_simple_sounds_count, xsb.xsb_complex_sounds_count, xsb.xsb_sounds_count); + "XSB: number of xsb sounds doesn't match simple + complex sounds (simple %i, complex %i, total %i)\n", xsb.xsb_simple_sounds_count, xsb.xsb_complex_sounds_count, xsb.xsb_sounds_count); /* init stuff */ @@ -614,7 +644,7 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head size = 0x14; if (flag != 0x01) { - VGM_LOG("XSB: xsb flag 0x%x at offset 0x%08lx not implemented", flag, off); + VGM_LOG("XSB: xsb flag 0x%x at offset 0x%08lx not implemented\n", flag, off); goto fail; } @@ -643,7 +673,7 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head suboff = size - 0x08; } } else { - VGM_LOG("XSB: xsb flag 0x%x at offset 0x%08lx not implemented", flag, off); + VGM_LOG("XSB: xsb flag 0x%x at offset 0x%08lx not implemented\n", flag, off); goto fail; } } @@ -654,7 +684,7 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head } if (s->wavebank+1 > xsb.xsb_wavebanks_count) { - VGM_LOG("XSB: unknown xsb wavebank id %i at offset 0x%lx", s->wavebank, off); + VGM_LOG("XSB: unknown xsb wavebank id %i at offset 0x%lx\n", s->wavebank, off); goto fail; } @@ -724,7 +754,7 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head if (w->sound_count == xwb->streams) { if (!cfg__selected_wavebank) { - VGM_LOG("XSB: multiple xsb wavebanks with the same number of sounds, use -w to specify one of the wavebanks"); + VGM_LOG("XSB: multiple xsb wavebanks with the same number of sounds, use -w to specify one of the wavebanks\n"); goto fail; } @@ -739,17 +769,17 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head } if (!cfg__selected_wavebank) { - VGM_LOG("XSB: multiple xsb wavebanks but autodetect didn't work"); + VGM_LOG("XSB: multiple xsb wavebanks but autodetect didn't work\n"); goto fail; } if (xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count == 0) { - VGM_LOG("XSB: xsb selected wavebank %i has no sounds", cfg__selected_wavebank); + VGM_LOG("XSB: xsb selected wavebank %i has no sounds\n", cfg__selected_wavebank); goto fail; } if (cfg__start_sound) { if (xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count - (cfg__start_sound-1) < xwb->streams) { - VGM_LOG("XSB: starting sound too high (max in selected wavebank is %i)", xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count - xwb->streams + 1); + VGM_LOG("XSB: starting sound too high (max in selected wavebank is %i)\n", xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count - xwb->streams + 1); goto fail; } @@ -789,5 +819,6 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head fail: free(xsb.xsb_sounds); free(xsb.xsb_wavebanks); + if (streamFile) close_streamfile(streamFile); return; } diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.c b/Frameworks/vgmstream/vgmstream/src/streamfile.c index 32ef75fc3..97e549927 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.c +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.c @@ -22,9 +22,6 @@ typedef struct { uint8_t * buffer; /* data buffer */ size_t buffersize; /* max buffer size */ size_t filesize; /* cached file size (max offset) */ -#ifdef VGM_DEBUG_OUTPUT - int error_notified; -#endif #ifdef PROFILE_STREAMFILE size_t bytes_read; int error_count; @@ -67,13 +64,7 @@ static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOST /* request outside file: ignore to avoid seek/read */ if (offset > streamfile->filesize) { streamfile->offset = streamfile->filesize; - -#ifdef VGM_DEBUG_OUTPUT - if (!streamfile->error_notified) { - VGM_LOG("ERROR: reading over filesize 0x%x @ 0x%lx + 0x%x (buggy meta?)\n", streamfile->filesize, offset, length); - streamfile->error_notified = 1; - } -#endif + VGM_LOG_ONCE("ERROR: reading over filesize 0x%x @ 0x%lx + 0x%x (buggy meta?)\n", streamfile->filesize, offset, length); #if STREAMFILE_IGNORE_EOF memset(dest,0,length); /* dest is already shifted */ @@ -143,13 +134,7 @@ static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offse /* request outside file: ignore to avoid seek/read in read_the_rest() */ if (offset > streamfile->filesize) { streamfile->offset = streamfile->filesize; - -#ifdef VGM_DEBUG_OUTPUT - if (!streamfile->error_notified) { - VGM_LOG("ERROR: offset over filesize 0x%x @ 0x%lx + 0x%x (buggy meta?)\n", streamfile->filesize, offset, length); - streamfile->error_notified = 1; - } -#endif + VGM_LOG_ONCE("ERROR: offset over filesize 0x%x @ 0x%lx + 0x%x (buggy meta?)\n", streamfile->filesize, offset, length); #if STREAMFILE_IGNORE_EOF memset(dest,0,length); @@ -169,7 +154,7 @@ static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offse /* request outside buffer: new fread */ { size_t length_read = read_the_rest(dest,offset,length,streamfile); -#if PROFILE_STREAMFILE +#ifdef PROFILE_STREAMFILE if (length_read < length) streamfile->error_count++; #endif @@ -298,63 +283,59 @@ STREAMFILE * open_stdio_streamfile_by_file(FILE * file, const char * filename) { /* **************************************************** */ -/* Read a line into dst. The source files are MS-DOS style, - * separated (not terminated) by CRLF. Return 1 if the full line was - * retrieved (if it could fit in dst), 0 otherwise. In any case the result - * will be properly terminated. The CRLF will be removed if there is one. - * Return the number of bytes read (including CRLF line ending). Note that - * this is not the length of the string, and could be larger than the buffer. - * *line_done_ptr is set to 1 if the complete line was read into dst, - * otherwise it is set to 0. line_done_ptr can be NULL if you aren't - * interested in this info. +/* Read a line into dst. The source files are lines separated by CRLF (Windows) / LF (Unux) / CR (Mac). + * The line will be null-terminated and CR/LF removed if found. + * + * Returns the number of bytes read (including CR/LF), note that this is not the string length. + * line_done_ptr is set to 1 if the complete line was read into dst; NULL can be passed to ignore. */ -size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, - STREAMFILE * infile, int *line_done_ptr) -{ +size_t get_streamfile_text_line(int dst_length, char * dst, off_t offset, STREAMFILE * streamfile, int *line_done_ptr) { int i; - off_t file_length = get_streamfile_size(infile); - /* how many bytes over those put in the buffer were read */ - int extra_bytes = 0; + off_t file_length = get_streamfile_size(streamfile); + int extra_bytes = 0; /* how many bytes over those put in the buffer were read */ if (line_done_ptr) *line_done_ptr = 0; - for (i=0;iopen(streamFile,filename_ext,STREAMFILE_DEFAULT_BUFFER_SIZE); } +/* Opens an stream using the passed name (in the same folder) */ +STREAMFILE * open_stream_name(STREAMFILE *streamFile, const char * name) { + char foldername[PATH_LIMIT]; + char filename[PATH_LIMIT]; + const char *path; + + streamFile->get_name(streamFile,foldername,sizeof(foldername)); + + path = strrchr(foldername,DIR_SEPARATOR); + if (path!=NULL) path = path+1; + + if (path) { + strcpy(filename, foldername); + filename[path-foldername] = '\0'; + strcat(filename, name); + } else { + strcpy(filename, name); + } + + return streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); +} + /** * open file containing decryption keys and copy to buffer * tries combinations of keynames based on the original filename diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.h b/Frameworks/vgmstream/vgmstream/src/streamfile.h index 22b94742b..0398b5ae0 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.h @@ -156,9 +156,10 @@ static inline int8_t read_8bit(off_t offset, STREAMFILE * streamfile) { /* various STREAMFILE helpers functions */ -size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, STREAMFILE * infile, int *line_done_ptr); +size_t get_streamfile_text_line(int dst_length, char * dst, off_t offset, STREAMFILE * streamfile, int *line_done_ptr); STREAMFILE * open_stream_ext(STREAMFILE *streamFile, const char * ext); +STREAMFILE * open_stream_name(STREAMFILE *streamFile, const char * ext); int read_string(char * buf, size_t bufsize, off_t offset, STREAMFILE *streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/util.c b/Frameworks/vgmstream/vgmstream/src/util.c index 51136173e..badb2c97d 100644 --- a/Frameworks/vgmstream/vgmstream/src/util.c +++ b/Frameworks/vgmstream/vgmstream/src/util.c @@ -2,10 +2,6 @@ #include "util.h" #include "streamtypes.h" -int check_sample_rate(int32_t sr) { - return !(sr<300 || sr>96000); -} - const char * filename_extension(const char * filename) { const char * ext; @@ -18,6 +14,8 @@ const char * filename_extension(const char * filename) { return ext; } +/* unused */ +/* void interleave_channel(sample * outbuffer, sample * inbuffer, int32_t sample_count, int channel_count, int channel_number) { int32_t insample,outsample; @@ -30,6 +28,7 @@ void interleave_channel(sample * outbuffer, sample * inbuffer, int32_t sample_co outbuffer[outsample]=inbuffer[insample]; } } +*/ /* failed attempt at interleave in place */ /* diff --git a/Frameworks/vgmstream/vgmstream/src/util.h b/Frameworks/vgmstream/vgmstream/src/util.h index 0062e6ac3..a2c5765f7 100644 --- a/Frameworks/vgmstream/vgmstream/src/util.h +++ b/Frameworks/vgmstream/vgmstream/src/util.h @@ -61,35 +61,35 @@ static inline int get_low_nibble_signed(uint8_t n) { return nibble_to_int[n&0xf]; } -/* return true for a good sample rate */ -int check_sample_rate(int32_t sr); +static inline int clamp16(int32_t val) { + if (val>32767) return 32767; + if (val<-32768) return -32768; + return val; +} /* return a file's extension (a pointer to the first character of the - * extension in the original filename or the ending null byte if no extension - */ + * extension in the original filename or the ending null byte if no extension */ const char * filename_extension(const char * filename); -static inline int clamp16(int32_t val) { - if (val>32767) return 32767; - if (val<-32768) return -32768; - return val; -} - void swap_samples_le(sample *buf, int count); void concatn(int length, char * dst, const char * src); /* Simple stdout logging for debugging and regression testing purposes. - * Needs C99 variadic macros. */ + * Needs C99 variadic macros, uses do..while to force ; as statement */ #ifdef VGM_DEBUG_OUTPUT /* equivalent to printf when condition is true */ #define VGM_ASSERT(condition, ...) \ do { if (condition) printf(__VA_ARGS__); } while (0) +#define VGM_ASSERT_ONCE(condition, ...) \ + do { static int written; if (!written) { if (condition) printf(__VA_ARGS__); written = 1; } } while (0) /* equivalent to printf */ #define VGM_LOG(...) \ do { printf(__VA_ARGS__); } while (0) +#define VGM_LOG_ONCE(...) \ + do { static int written; if (!written) { printf(__VA_ARGS__); written = 1; } } while (0) /* prints file/line/func */ #define VGM_LOGF() \ do { printf("%s:%i '%s'\n", __FILE__, __LINE__, __func__); } while (0) @@ -111,10 +111,12 @@ void concatn(int length, char * dst, const char * src); #define VGM_ASSERT(condition, ...) /* nothing */ #define VGM_LOG(...) /* nothing */ +#define VGM_LOG_ONCE(...) /* nothing */ #define VGM_LOGF() /* nothing */ #define VGM_LOGT() /* nothing */ #define VGM_LOGB(buf, buf_size, bytes_per_line) /* nothing */ + #endif/*VGM_DEBUG_OUTPUT*/ #endif diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 0c8715821..b5bb594e7 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -5,22 +5,16 @@ #include #include #include -#include "formats.h" #include "vgmstream.h" #include "meta/meta.h" #include "layout/layout.h" #include "coding/coding.h" -/* See if there is a second file which may be the second channel, given - * already opened mono opened_stream which was opened from filename. - * If a suitable file is found, open it and change opened_stream to a stereo stream. */ -static void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile); +static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *streamFile, VGMSTREAM* (*init_vgmstream_function)(STREAMFILE*)); -/* - * List of functions that will recognize files. - */ -VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { +/* List of functions that will recognize files */ +VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_adx, init_vgmstream_brstm, init_vgmstream_bfwav, @@ -38,7 +32,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ngc_dsp_std, init_vgmstream_ngc_mdsp_std, init_vgmstream_ngc_dsp_csmp, - init_vgmstream_Cstr, + init_vgmstream_cstr, init_vgmstream_gcsw, init_vgmstream_ps2_ads, init_vgmstream_ps2_npsf, @@ -91,7 +85,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_rifx, init_vgmstream_pos, init_vgmstream_nwa, - init_vgmstream_eacs, + init_vgmstream_ea_1snh, init_vgmstream_xss, init_vgmstream_sl3, init_vgmstream_hgc1, @@ -114,16 +108,16 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ikm, init_vgmstream_sfs, init_vgmstream_bg00, - init_vgmstream_dvi, - init_vgmstream_kcey, + init_vgmstream_sat_dvi, + init_vgmstream_dc_kcey, init_vgmstream_ps2_rstm, init_vgmstream_acm, init_vgmstream_mus_acm, init_vgmstream_ps2_kces, init_vgmstream_ps2_dxh, init_vgmstream_ps2_psh, - init_vgmstream_pcm_scd, - init_vgmstream_pcm_ps2, + init_vgmstream_scd_pcm, + init_vgmstream_ps2_pcm, init_vgmstream_ps2_rkv, init_vgmstream_ps2_psw, init_vgmstream_ps2_vas, @@ -139,7 +133,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_dc_str, init_vgmstream_dc_str_v2, init_vgmstream_xbox_matx, - init_vgmstream_de2, + init_vgmstream_dec, init_vgmstream_vs, init_vgmstream_dc_str, init_vgmstream_dc_str_v2, @@ -153,7 +147,6 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_kraw, init_vgmstream_ps2_omu, init_vgmstream_ps2_xa2, - //init_vgmstream_idsp, init_vgmstream_idsp2, init_vgmstream_idsp3, init_vgmstream_idsp4, @@ -202,7 +195,6 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_wii_smp, init_vgmstream_emff_ps2, init_vgmstream_emff_ngc, - init_vgmstream_ss_stream, init_vgmstream_thp, init_vgmstream_wii_sts, init_vgmstream_ps2_p2bt, @@ -259,9 +251,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_ster, init_vgmstream_ps2_wb, init_vgmstream_bnsf, -#ifdef VGM_USE_G7221 init_vgmstream_s14_sss, -#endif init_vgmstream_ps2_gcm, init_vgmstream_ps2_smpl, init_vgmstream_ps2_msa, @@ -288,7 +278,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_dsp_bdsp, init_vgmstream_ps2_vms, init_vgmstream_xau, - init_vgmstream_gh3_bar, + init_vgmstream_bar, init_vgmstream_ffw, init_vgmstream_dsp_dspw, init_vgmstream_ps2_jstm, @@ -371,6 +361,16 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_awc, init_vgmstream_nsw_opus, init_vgmstream_pc_al2, + init_vgmstream_pc_ast, + init_vgmstream_naac, + init_vgmstream_ubi_sb, + init_vgmstream_ezw, + init_vgmstream_vxn, + init_vgmstream_ea_snr_sns, + init_vgmstream_ea_sps, + init_vgmstream_ngc_vid1, + init_vgmstream_flx, + init_vgmstream_mogg, init_vgmstream_txth, /* should go at the end (lower priority) */ #ifdef VGM_USE_FFMPEG @@ -380,87 +380,87 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { /* internal version with all parameters */ -static VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) { +static VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile) { int i, fcns_size; if (!streamFile) return NULL; - fcns_size = (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0])); + fcns_size = (sizeof(init_vgmstream_functions)/sizeof(init_vgmstream_functions[0])); /* try a series of formats, see which works */ for (i=0; i < fcns_size; i++) { /* call init function and see if valid VGMSTREAM was returned */ - VGMSTREAM * vgmstream = (init_vgmstream_fcns[i])(streamFile); - if (vgmstream) { - /* these are little hacky checks */ + VGMSTREAM * vgmstream = (init_vgmstream_functions[i])(streamFile); + if (!vgmstream) + continue; - /* fail if there is nothing to play (without this check vgmstream can generate empty files) */ - if (vgmstream->num_samples <= 0) { - VGM_LOG("VGMSTREAM: wrong num_samples (ns=%i / 0x%08x)\n", vgmstream->num_samples, vgmstream->num_samples); - close_vgmstream(vgmstream); - continue; - } + /* fail if there is nothing to play (without this check vgmstream can generate empty files) */ + if (vgmstream->num_samples <= 0) { + VGM_LOG("VGMSTREAM: wrong num_samples (ns=%i / 0x%08x)\n", vgmstream->num_samples, vgmstream->num_samples); + close_vgmstream(vgmstream); + continue; + } - /* everything should have a reasonable sample rate (a verification of the metadata) */ - if (!check_sample_rate(vgmstream->sample_rate)) { - VGM_LOG("VGMSTREAM: wrong sample rate (sr=%i)\n", vgmstream->sample_rate); - close_vgmstream(vgmstream); - continue; - } + /* everything should have a reasonable sample rate (300 is Wwise min) */ + if (vgmstream->sample_rate < 300 || vgmstream->sample_rate > 96000) { + VGM_LOG("VGMSTREAM: wrong sample rate (sr=%i)\n", vgmstream->sample_rate); + close_vgmstream(vgmstream); + continue; + } - /* Sanify loops! */ - if (vgmstream->loop_flag) { - if ((vgmstream->loop_end_sample <= vgmstream->loop_start_sample) - || (vgmstream->loop_end_sample > vgmstream->num_samples) - || (vgmstream->loop_start_sample < 0) ) { - vgmstream->loop_flag = 0; - VGM_LOG("VGMSTREAM: wrong loops ignored (lss=%i, lse=%i, ns=%i)\n", vgmstream->loop_start_sample, vgmstream->loop_end_sample, vgmstream->num_samples); - } + /* Sanify loops! */ + if (vgmstream->loop_flag) { + if ((vgmstream->loop_end_sample <= vgmstream->loop_start_sample) + || (vgmstream->loop_end_sample > vgmstream->num_samples) + || (vgmstream->loop_start_sample < 0) ) { + vgmstream->loop_flag = 0; + VGM_LOG("VGMSTREAM: wrong loops ignored (lss=%i, lse=%i, ns=%i)\n", vgmstream->loop_start_sample, vgmstream->loop_end_sample, vgmstream->num_samples); } + } + + /* test if candidate for dual stereo */ + if (vgmstream->channels == 1 && ( + (vgmstream->meta_type == meta_DSP_STD) || + (vgmstream->meta_type == meta_PS2_VAGp) || + (vgmstream->meta_type == meta_GENH) || + (vgmstream->meta_type == meta_TXTH) || + (vgmstream->meta_type == meta_KRAW) || + (vgmstream->meta_type == meta_PS2_MIB) || + (vgmstream->meta_type == meta_NGC_LPS) || + (vgmstream->meta_type == meta_DSP_YGO) || + (vgmstream->meta_type == meta_DSP_AGSC) || + (vgmstream->meta_type == meta_PS2_SMPL) || + (vgmstream->meta_type == meta_NGCA) || + (vgmstream->meta_type == meta_NUB_VAG) || + (vgmstream->meta_type == meta_SPT_SPD) || + (vgmstream->meta_type == meta_EB_SFX) || + (vgmstream->meta_type == meta_CWAV) + )) { + try_dual_file_stereo(vgmstream, streamFile, init_vgmstream_functions[i]); + } - /* dual file stereo */ - if (do_dfs && ( - (vgmstream->meta_type == meta_DSP_STD) || - (vgmstream->meta_type == meta_PS2_VAGp) || - (vgmstream->meta_type == meta_GENH) || - (vgmstream->meta_type == meta_KRAW) || - (vgmstream->meta_type == meta_PS2_MIB) || - (vgmstream->meta_type == meta_NGC_LPS) || - (vgmstream->meta_type == meta_DSP_YGO) || - (vgmstream->meta_type == meta_DSP_AGSC) || - (vgmstream->meta_type == meta_PS2_SMPL) || - (vgmstream->meta_type == meta_NGCA) || - (vgmstream->meta_type == meta_NUB_VAG) || - (vgmstream->meta_type == meta_SPT_SPD) || - (vgmstream->meta_type == meta_EB_SFX) || - (vgmstream->meta_type == meta_CWAV) - ) && vgmstream->channels == 1) { - try_dual_file_stereo(vgmstream, streamFile); - } #ifdef VGM_USE_FFMPEG - /* check FFmpeg streams here, for lack of a better place */ - if (vgmstream->coding_type == coding_FFmpeg) { - ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; - if (data->streamCount && !vgmstream->num_streams) { - vgmstream->num_streams = data->streamCount; - } + /* check FFmpeg streams here, for lack of a better place */ + if (vgmstream->coding_type == coding_FFmpeg) { + ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; + if (data->streamCount && !vgmstream->num_streams) { + vgmstream->num_streams = data->streamCount; } + } #endif - /* save info */ - vgmstream->stream_index = streamFile->stream_index; + /* save info */ + vgmstream->stream_index = streamFile->stream_index; - /* save start things so we can restart for seeking */ - /* copy the channels */ - memcpy(vgmstream->start_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels); - /* copy the whole VGMSTREAM */ - memcpy(vgmstream->start_vgmstream,vgmstream,sizeof(VGMSTREAM)); + /* save start things so we can restart for seeking */ + memcpy(vgmstream->start_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels); + memcpy(vgmstream->start_vgmstream,vgmstream,sizeof(VGMSTREAM)); - return vgmstream; - } + return vgmstream; } + /* not supported */ return NULL; } @@ -476,7 +476,7 @@ VGMSTREAM * init_vgmstream(const char * const filename) { } VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile) { - return init_vgmstream_internal(streamFile,1); + return init_vgmstream_internal(streamFile); } /* Reset a VGMSTREAM to its state at the start of playback. @@ -507,6 +507,10 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { reset_hca(vgmstream); } + if (vgmstream->coding_type==coding_EA_MT) { + reset_ea_mt(vgmstream); + } + #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) if (vgmstream->coding_type==coding_MP4_AAC) { reset_mp4_aac(vgmstream); @@ -558,28 +562,6 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { } } - if (vgmstream->layout_type==layout_aix) { - aix_codec_data *data = vgmstream->codec_data; - int i; - - data->current_segment = 0; - for (i=0;isegment_count*data->stream_count;i++) - { - reset_vgmstream(data->adxs[i]); - } - } - - if (vgmstream->layout_type==layout_aax) { - aax_codec_data *data = vgmstream->codec_data; - int i; - - data->current_segment = 0; - for (i=0;isegment_count;i++) - { - reset_vgmstream(data->adxs[i]); - } - } - if ( vgmstream->coding_type == coding_NWA0 || vgmstream->coding_type == coding_NWA1 || @@ -592,19 +574,38 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { reset_nwa(data->nwa); } + + if (vgmstream->layout_type==layout_aix) { + aix_codec_data *data = vgmstream->codec_data; + int i; + + data->current_segment = 0; + for (i=0;isegment_count*data->stream_count;i++) { + reset_vgmstream(data->adxs[i]); + } + } + + if (vgmstream->layout_type==layout_aax) { + aax_codec_data *data = vgmstream->codec_data; + int i; + + data->current_segment = 0; + for (i=0;isegment_count;i++) { + reset_vgmstream(data->adxs[i]); + } + } + if (vgmstream->layout_type==layout_scd_int) { scd_int_codec_data *data = vgmstream->codec_data; int i; - for (i=0;isubstream_count;i++) - { + for (i=0;isubstream_count;i++) { reset_vgmstream(data->substreams[i]); } } - } -/* simply allocate memory for the VGMSTREAM and its channels */ +/* Allocate memory and setup a VGMSTREAM */ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) { VGMSTREAM * vgmstream; VGMSTREAM * start_vgmstream; @@ -667,7 +668,6 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) { } void close_vgmstream(VGMSTREAM * vgmstream) { - int i,j; if (!vgmstream) return; @@ -687,7 +687,12 @@ void close_vgmstream(VGMSTREAM * vgmstream) { free_hca(vgmstream->codec_data); vgmstream->codec_data = NULL; } - + + if (vgmstream->coding_type==coding_EA_MT) { + free_ea_mt(vgmstream->codec_data); + vgmstream->codec_data = NULL; + } + #ifdef VGM_USE_FFMPEG if (vgmstream->coding_type==coding_FFmpeg) { free_ffmpeg(vgmstream->codec_data); @@ -757,53 +762,6 @@ void close_vgmstream(VGMSTREAM * vgmstream) { } } - if (vgmstream->layout_type==layout_aix) { - aix_codec_data *data = (aix_codec_data *) vgmstream->codec_data; - - if (data) { - if (data->adxs) { - int i; - for (i=0;isegment_count*data->stream_count;i++) { - - /* note that the AIX close_streamfile won't do anything but - * deallocate itself, there is only one open file and that - * is in vgmstream->ch[0].streamfile */ - close_vgmstream(data->adxs[i]); - } - free(data->adxs); - } - if (data->sample_counts) { - free(data->sample_counts); - } - - free(data); - } - vgmstream->codec_data = NULL; - } - if (vgmstream->layout_type==layout_aax) { - aax_codec_data *data = (aax_codec_data *) vgmstream->codec_data; - - if (data) { - if (data->adxs) { - int i; - for (i=0;isegment_count;i++) { - - /* note that the AAX close_streamfile won't do anything but - * deallocate itself, there is only one open file and that - * is in vgmstream->ch[0].streamfile */ - close_vgmstream(data->adxs[i]); - } - free(data->adxs); - } - if (data->sample_counts) { - free(data->sample_counts); - } - - free(data); - } - vgmstream->codec_data = NULL; - } - if ( vgmstream->coding_type == coding_NWA0 || vgmstream->coding_type == coding_NWA1 || @@ -819,6 +777,51 @@ void close_vgmstream(VGMSTREAM * vgmstream) { vgmstream->codec_data = NULL; } + + if (vgmstream->layout_type==layout_aix) { + aix_codec_data *data = (aix_codec_data *) vgmstream->codec_data; + + if (data) { + if (data->adxs) { + int i; + for (i=0;isegment_count*data->stream_count;i++) { + /* note that the close_streamfile won't do anything but deallocate itself, + * there is only one open file in vgmstream->ch[0].streamfile */ + close_vgmstream(data->adxs[i]); + } + free(data->adxs); + } + if (data->sample_counts) { + free(data->sample_counts); + } + + free(data); + } + vgmstream->codec_data = NULL; + } + + if (vgmstream->layout_type==layout_aax) { + aax_codec_data *data = (aax_codec_data *) vgmstream->codec_data; + + if (data) { + if (data->adxs) { + int i; + for (i=0;isegment_count;i++) { + /* note that the close_streamfile won't do anything but deallocate itself, + * there is only one open file in vgmstream->ch[0].streamfile */ + close_vgmstream(data->adxs[i]); + } + free(data->adxs); + } + if (data->sample_counts) { + free(data->sample_counts); + } + + free(data); + } + vgmstream->codec_data = NULL; + } + if (vgmstream->layout_type==layout_scd_int) { scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data; @@ -826,10 +829,8 @@ void close_vgmstream(VGMSTREAM * vgmstream) { if (data->substreams) { int i; for (i=0;isubstream_count;i++) { - - /* note that the scd_int close_streamfile won't do anything - * but deallocate itself, there is only one open file and - * that is in vgmstream->ch[0].streamfile */ + /* note that the close_streamfile won't do anything but deallocate itself, + * there is only one open file in vgmstream->ch[0].streamfile */ close_vgmstream(data->substreams[i]); if(data->intfiles[i]) close_streamfile(data->intfiles[i]); } @@ -842,20 +843,25 @@ void close_vgmstream(VGMSTREAM * vgmstream) { vgmstream->codec_data = NULL; } + /* now that the special cases have had their chance, clean up the standard items */ - for (i=0;ichannels;i++) { - if (vgmstream->ch[i].streamfile) { - close_streamfile(vgmstream->ch[i].streamfile); - /* Multiple channels might have the same streamfile. Find the others - * that are the same as this and clear them so they won't be closed - * again. */ - for (j=0;jchannels;j++) { - if (i!=j && vgmstream->ch[j].streamfile == - vgmstream->ch[i].streamfile) { - vgmstream->ch[j].streamfile = NULL; + { + int i,j; + + for (i=0;ichannels;i++) { + if (vgmstream->ch[i].streamfile) { + close_streamfile(vgmstream->ch[i].streamfile); + /* Multiple channels might have the same streamfile. Find the others + * that are the same as this and clear them so they won't be closed + * again. */ + for (j=0;jchannels;j++) { + if (i!=j && vgmstream->ch[j].streamfile == + vgmstream->ch[i].streamfile) { + vgmstream->ch[j].streamfile = NULL; + } } + vgmstream->ch[i].streamfile = NULL; } - vgmstream->ch[i].streamfile = NULL; } } @@ -892,7 +898,22 @@ int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double } } -/* decode data into sample buffer */ +void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample) { + if (!vgmstream) return; + + /* this requires a bit more messing with the VGMSTREAM than I'm comfortable with... */ + if (loop_flag && !vgmstream->loop_flag && !vgmstream->loop_ch) { + vgmstream->loop_ch = calloc(vgmstream->channels,sizeof(VGMSTREAMCHANNEL)); + /* loop_ch will be populated when decoded samples reach loop start */ + } + vgmstream->loop_flag = loop_flag; + if (loop_flag) { + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + } +} + +/* Decode data into sample buffer */ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { switch (vgmstream->layout_type) { case layout_interleave: @@ -912,14 +933,14 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_ast_blocked: case layout_halpst_blocked: case layout_xa_blocked: - case layout_ea_blocked: - case layout_eacs_blocked: + case layout_blocked_ea_schl: + case layout_blocked_ea_1snh: case layout_caf_blocked: case layout_wsi_blocked: case layout_str_snds_blocked: case layout_ws_aud_blocked: case layout_matx_blocked: - case layout_de2_blocked: + case layout_blocked_dec: case layout_vs_blocked: case layout_emff_ps2_blocked: case layout_emff_ngc_blocked: @@ -927,7 +948,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_xvas_blocked: case layout_thp_blocked: case layout_filp_blocked: - case layout_ivaud_blocked: + case layout_blocked_ivaud: case layout_psx_mgav_blocked: case layout_ps2_adm_blocked: case layout_dsp_bdsp_blocked: @@ -936,14 +957,12 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_ps2_strlr_blocked: case layout_rws_blocked: case layout_hwas_blocked: - case layout_ea_sns_blocked: + case layout_blocked_ea_sns: case layout_blocked_awc: case layout_blocked_vgs: + case layout_blocked_vawx: render_vgmstream_blocked(buffer,sample_count,vgmstream); break; - case layout_interleave_byte: - render_vgmstream_interleave_byte(buffer,sample_count,vgmstream); - break; case layout_acm: case layout_mus_acm: render_vgmstream_mus_acm(buffer,sample_count,vgmstream); @@ -957,10 +976,12 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_scd_int: render_vgmstream_scd_int(buffer,sample_count,vgmstream); break; + default: + break; } } -/* get the size in samples of a single frame (1 or N channels), for interleaved/blocked layouts */ +/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { switch (vgmstream->coding_type) { case coding_CRI_ADX: @@ -972,6 +993,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_L5_555: return 32; case coding_NGC_DSP: + case coding_NGC_DSP_subint: return 14; case coding_PCM16LE: case coding_PCM16LE_XOR_int: @@ -1015,14 +1037,15 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_NGC_DTK: return 28; case coding_G721: - case coding_DVI_IMA: - case coding_EACS_IMA: - case coding_SNDS_IMA: case coding_IMA: + case coding_DVI_IMA: + case coding_SNDS_IMA: case coding_OTNS_IMA: + case coding_UBI_IMA: return 1; case coding_IMA_int: case coding_DVI_IMA_int: + case coding_3DS_IMA: case coding_AICA: return 2; case coding_NGC_AFC: @@ -1042,9 +1065,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_EA_XA: case coding_EA_XA_int: case coding_EA_XA_V2: - return 28; - case coding_MAXIS_XA: - return 14*vgmstream->channels; + case coding_MAXIS_XA: + return 28; case coding_EA_XAS: return 128; case coding_WS: @@ -1090,11 +1112,13 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_LSF: return 54; case coding_MTAF: - return 0x80*2; + return 128*2; case coding_MTA2: - return 0x80*2; + return 128*2; case coding_MC3: return 10; + case coding_EA_MT: + return 432; case coding_CRI_HCA: return clHCA_samplesPerBlock; #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) @@ -1110,16 +1134,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { } } -int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) { - switch (vgmstream->coding_type) { - case coding_NDS_IMA: - return (vgmstream->interleave_smallblock_size-4)*2; - default: - return get_vgmstream_samples_per_frame(vgmstream); - } -} - -/* get the data size of a single frame (1 or N channels), for interleaved/blocked layouts */ +/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { switch (vgmstream->coding_type) { case coding_CRI_ADX: @@ -1131,7 +1146,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_L5_555: return 18; case coding_NGC_DSP: - return 8; + return 0x08; + case coding_NGC_DSP_subint: + return 0x08 * vgmstream->channels; case coding_PCM16LE: case coding_PCM16LE_XOR_int: case coding_PCM16BE: @@ -1171,14 +1188,12 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return 0x14; case coding_NGC_DTK: return 32; - case coding_EACS_IMA: - return 1; - case coding_DVI_IMA: - case coding_IMA: 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_PSX: @@ -1202,15 +1217,19 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_MAXIS_XA: return 0x0F*vgmstream->channels; case coding_EA_XA_V2: - return 1; /* the frame is variant in size (ADPCM frames of 0x0F or PCM frames) */ + return 0; /* variable (ADPCM frames of 0x0f or PCM frames of 0x3d) */ case coding_EA_XAS: return 0x4c*vgmstream->channels; 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; + return 1; case coding_APPLE_IMA4: return 34; case coding_LSF: @@ -1234,12 +1253,23 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_MTA2: return 0x90; case coding_MC3: - return 4; + return 0x04; + case coding_EA_MT: + return 0; /* variable (frames of bit counts or PCM frames) */ default: return 0; } } +/* In NDS IMA the frame size is the block size, so the last one is short */ +int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) { + switch (vgmstream->coding_type) { + case coding_NDS_IMA: + return (vgmstream->interleave_smallblock_size-4)*2; + default: + return get_vgmstream_samples_per_frame(vgmstream); + } +} int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) { switch (vgmstream->coding_type) { case coding_NDS_IMA: @@ -1249,20 +1279,8 @@ int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) { } } -void decode_vgmstream_mem(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer, uint8_t * data, int channel) { - - switch (vgmstream->coding_type) { - case coding_NGC_DSP: - decode_ngc_dsp_mem(&vgmstream->ch[channel], - buffer+samples_written*vgmstream->channels+channel, - vgmstream->channels,vgmstream->samples_into_block, - samples_to_do, data); - break; - default: - break; - } -} - +/* Decode samples into the buffer. Assume that we have written samples_written into the + * buffer already, and we have samples_to_do consecutive samples ahead of us. */ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer) { int chan; @@ -1311,6 +1329,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + case coding_NGC_DSP_subint: + for (chan=0;chanchannels;chan++) { + decode_ngc_dsp_subint(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do, + chan, vgmstream->interleave_block_size); + } + break; case coding_PCM16LE: for (chan=0;chanchannels;chan++) { decode_pcm16LE(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, @@ -1421,7 +1447,7 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to break; case coding_XBOX_int: for (chan=0;chanchannels;chan++) { - decode_xbox_ima_int(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + decode_xbox_ima_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, samples_to_do,chan); } @@ -1606,25 +1632,23 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + case coding_IMA: + case coding_IMA_int: case coding_DVI_IMA: case coding_DVI_IMA_int: for (chan=0;chanchannels;chan++) { - decode_dvi_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + int is_stereo = (vgmstream->channels > 1 && vgmstream->coding_type == coding_IMA) + || (vgmstream->channels > 1 && vgmstream->coding_type == coding_DVI_IMA); + int is_high_first = vgmstream->coding_type == coding_DVI_IMA || vgmstream->coding_type == coding_DVI_IMA_int; + + decode_standard_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, - samples_to_do); + samples_to_do, chan, is_stereo, is_high_first); } break; - case coding_EACS_IMA: + case coding_3DS_IMA: for (chan=0;chanchannels;chan++) { - decode_eacs_ima(vgmstream,buffer+samples_written*vgmstream->channels+chan, - vgmstream->channels,vgmstream->samples_into_block, - samples_to_do,chan); - } - break; - case coding_IMA: - case coding_IMA_int: - for (chan=0;chanchannels;chan++) { - decode_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + decode_3ds_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, samples_to_do); } @@ -1678,6 +1702,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + case coding_UBI_IMA: + for (chan=0;chanchannels;chan++) { + decode_ubi_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; case coding_WS: for (chan=0;chanchannels;chan++) { @@ -1821,9 +1852,19 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to chan); } break; + case coding_EA_MT: + for (chan=0;chanchannels;chan++) { + decode_ea_mt(vgmstream, buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels, vgmstream->samples_into_block, samples_to_do, + chan); + } + break; + default: + break; } } +/* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM * vgmstream) { int samples_to_do; int samples_left_this_block; @@ -1855,7 +1896,7 @@ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMST return samples_to_do; } -/* loop if end sample is reached, and return 1 if we did loop */ +/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */ int vgmstream_do_loop(VGMSTREAM * vgmstream) { /*if (!vgmstream->loop_flag) return 0;*/ @@ -1875,7 +1916,6 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { if (vgmstream->meta_type == meta_DSP_STD || vgmstream->meta_type == meta_DSP_RS03 || vgmstream->meta_type == meta_DSP_CSTR || - vgmstream->meta_type == meta_NDS_STRM_FFTA2 || /* clicks in some files otherwise */ vgmstream->coding_type == coding_PSX || vgmstream->coding_type == coding_PSX_bmdx || vgmstream->coding_type == coding_PSX_badflags) { @@ -1895,6 +1935,10 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { loop_hca(vgmstream); } + if (vgmstream->coding_type==coding_EA_MT) { + seek_ea_mt(vgmstream, vgmstream->loop_start_sample); + } + #ifdef VGM_USE_VORBIS if (vgmstream->coding_type==coding_ogg_vorbis) { seek_ogg_vorbis(vgmstream, vgmstream->loop_sample); @@ -1949,6 +1993,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { vgmstream->current_sample = vgmstream->loop_sample; vgmstream->samples_into_block = vgmstream->loop_samples_into_block; vgmstream->current_block_size = vgmstream->loop_block_size; + vgmstream->current_block_samples = vgmstream->loop_block_samples; vgmstream->current_block_offset = vgmstream->loop_block_offset; vgmstream->next_block_offset = vgmstream->loop_next_block_offset; @@ -1964,6 +2009,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { vgmstream->loop_sample = vgmstream->current_sample; vgmstream->loop_samples_into_block = vgmstream->samples_into_block; vgmstream->loop_block_size = vgmstream->current_block_size; + vgmstream->loop_block_samples = vgmstream->current_block_samples; vgmstream->loop_block_offset = vgmstream->current_block_offset; vgmstream->loop_next_block_offset = vgmstream->next_block_offset; vgmstream->hit_loop = 1; @@ -1972,7 +2018,8 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { return 0; /* not looped */ } -/* build a descriptive string */ +/* Write a description of the stream into array pointed by desc, which must be length bytes long. + * Will always be null-terminated if length > 0 */ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { #define TEMPSIZE 256 char temp[TEMPSIZE]; @@ -2057,8 +2104,7 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { concatn(length,desc,temp); if (vgmstream->layout_type == layout_interleave - || vgmstream->layout_type == layout_interleave_shortblock - || vgmstream->layout_type == layout_interleave_byte) { + || vgmstream->layout_type == layout_interleave_shortblock) { snprintf(temp,TEMPSIZE, "interleave: %#x bytes\n", (int32_t)vgmstream->interleave_block_size); @@ -2125,104 +2171,108 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { } } -/* filename search pairs for dual file stereo */ -const char * const dfs_pairs[][2] = { - {"L","R"}, - {"l","r"}, - {"_0","_1"}, - {"left","right"}, - {"Left","Right"}, -}; -#define DFS_PAIR_COUNT (sizeof(dfs_pairs)/sizeof(dfs_pairs[0])) -static void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile) { - char filename[PATH_LIMIT]; - char filename2[PATH_LIMIT]; +/* See if there is a second file which may be the second channel, given an already opened mono vgmstream. + * If a suitable file is found, open it and change opened_vgmstream to a stereo vgmstream. */ +static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *streamFile, VGMSTREAM*(*init_vgmstream_function)(STREAMFILE *)) { + /* filename search pairs for dual file stereo */ + static const char * const dfs_pairs[][2] = { + {"L","R"}, + {"l","r"}, + {"left","right"}, + {"Left","Right"}, + {".V0",".V1"}, + {"_0","_1"}, //unneeded? + }; + char new_filename[PATH_LIMIT]; char * ext; - int dfs_name= -1; /*-1=no stereo, 0=opened_stream is left, 1=opened_stream is right */ - VGMSTREAM * new_stream = NULL; - STREAMFILE *dual_stream = NULL; - int i,j; + int dfs_pair = -1; /* -1=no stereo, 0=opened_vgmstream is left, 1=opened_vgmstream is right */ + VGMSTREAM *new_vgmstream = NULL; + STREAMFILE *dual_streamFile = NULL; + int i,j, dfs_pair_count; - if (opened_stream->channels != 1) return; - - streamFile->get_name(streamFile,filename,sizeof(filename)); + if (opened_vgmstream->channels != 1) + return; /* vgmstream's layout stuff currently assumes a single file */ // fastelbja : no need ... this one works ok with dual file - //if (opened_stream->layout != layout_none) return; + //if (opened_vgmstream->layout != layout_none) return; + //todo force layout_none if layout_interleave? - /* we need at least a base and a name ending to replace */ - if (strlen(filename)<2) return; + streamFile->get_name(streamFile,new_filename,sizeof(new_filename)); + if (strlen(new_filename)<2) return; /* we need at least a base and a name ending to replace */ + + ext = (char *)filename_extension(new_filename); + if (ext-new_filename >= 1 && ext[-1]=='.') ext--; /* including "." */ - strcpy(filename2,filename); + /* find pair from base name and modify new_filename with the opposite */ + dfs_pair_count = (sizeof(dfs_pairs)/sizeof(dfs_pairs[0])); + for (i = 0; dfs_pair == -1 && i< dfs_pair_count; i++) { + for (j=0; dfs_pair==-1 && j<2; j++) { + const char * this_suffix = dfs_pairs[i][j]; + size_t this_suffix_len = strlen(dfs_pairs[i][j]); + const char * other_suffix = dfs_pairs[i][j^1]; + size_t other_suffix_len = strlen(dfs_pairs[i][j^1]); - /* look relative to the extension; */ - ext = (char *)filename_extension(filename2); - - /* we treat the . as part of the extension */ - if (ext-filename2 >= 1 && ext[-1]=='.') ext--; - - for (i=0; dfs_name==-1 && iopen(streamFile,filename2,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!dual_stream) goto fail; + /* try to init other channel (new_filename now has the opposite name) */ + dual_streamFile = streamFile->open(streamFile,new_filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!dual_streamFile) goto fail; - new_stream = init_vgmstream_internal(dual_stream, - 0 /* don't do dual file on this, to prevent recursion */ - ); - close_streamfile(dual_stream); + new_vgmstream = init_vgmstream_function(dual_streamFile); /* use the init that just worked, no other should work */ + close_streamfile(dual_streamFile); /* see if we were able to open the file, and if everything matched nicely */ - if (new_stream && - new_stream->channels == 1 && - /* we have seen legitimate pairs where these are off by one... */ - /* but leaving it commented out until I can find those and recheck */ - /* abs(new_stream->num_samples-opened_stream->num_samples <= 1) && */ - new_stream->num_samples == opened_stream->num_samples && - new_stream->sample_rate == opened_stream->sample_rate && - new_stream->meta_type == opened_stream->meta_type && - new_stream->coding_type == opened_stream->coding_type && - new_stream->layout_type == opened_stream->layout_type && - new_stream->loop_flag == opened_stream->loop_flag && - /* check these even if there is no loop, because they should then - * be zero in both */ - new_stream->loop_start_sample == opened_stream->loop_start_sample && - new_stream->loop_end_sample == opened_stream->loop_end_sample && + if (!(new_vgmstream && + new_vgmstream->channels == 1 && + /* we have seen legitimate pairs where these are off by one... + * but leaving it commented out until I can find those and recheck */ + /* abs(new_vgmstream->num_samples-opened_vgmstream->num_samples <= 1) && */ + new_vgmstream->num_samples == opened_vgmstream->num_samples && + new_vgmstream->sample_rate == opened_vgmstream->sample_rate && + new_vgmstream->meta_type == opened_vgmstream->meta_type && + new_vgmstream->coding_type == opened_vgmstream->coding_type && + new_vgmstream->layout_type == opened_vgmstream->layout_type && /* check even if the layout doesn't use them, because it is - * difficult to determine when it does, and they should be zero - * otherwise, anyway */ - new_stream->interleave_block_size == opened_stream->interleave_block_size && - new_stream->interleave_smallblock_size == opened_stream->interleave_smallblock_size) { - /* We seem to have a usable, matching file. Merge in the second channel. */ + * difficult to determine when it does, and they should be zero otherwise, anyway */ + new_vgmstream->interleave_block_size == opened_vgmstream->interleave_block_size && + new_vgmstream->interleave_smallblock_size == opened_vgmstream->interleave_smallblock_size)) { + goto fail; + } + + /* check these even if there is no loop, because they should then be zero in both + * Homura PS2 right channel doesn't have loop points so it's ignored */ + if (new_vgmstream->meta_type != meta_PS2_SMPL && + !(new_vgmstream->loop_flag == opened_vgmstream->loop_flag && + new_vgmstream->loop_start_sample== opened_vgmstream->loop_start_sample && + new_vgmstream->loop_end_sample == opened_vgmstream->loop_end_sample)) { + goto fail; + } + + /* We seem to have a usable, matching file. Merge in the second channel. */ + { VGMSTREAMCHANNEL * new_chans; VGMSTREAMCHANNEL * new_loop_chans = NULL; VGMSTREAMCHANNEL * new_start_chans = NULL; @@ -2231,18 +2281,17 @@ static void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFi new_chans = calloc(2,sizeof(VGMSTREAMCHANNEL)); if (!new_chans) goto fail; - memcpy(&new_chans[dfs_name],&opened_stream->ch[0],sizeof(VGMSTREAMCHANNEL)); - memcpy(&new_chans[dfs_name^1],&new_stream->ch[0],sizeof(VGMSTREAMCHANNEL)); + memcpy(&new_chans[dfs_pair],&opened_vgmstream->ch[0],sizeof(VGMSTREAMCHANNEL)); + memcpy(&new_chans[dfs_pair^1],&new_vgmstream->ch[0],sizeof(VGMSTREAMCHANNEL)); - /* loop and start will be initialized later, we just need to - * allocate them here */ + /* loop and start will be initialized later, we just need to allocate them here */ new_start_chans = calloc(2,sizeof(VGMSTREAMCHANNEL)); if (!new_start_chans) { free(new_chans); goto fail; } - if (opened_stream->loop_ch) { + if (opened_vgmstream->loop_ch) { new_loop_chans = calloc(2,sizeof(VGMSTREAMCHANNEL)); if (!new_loop_chans) { free(new_chans); @@ -2253,93 +2302,72 @@ static void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFi /* remove the existing structures */ /* not using close_vgmstream as that would close the file */ - free(opened_stream->ch); - free(new_stream->ch); + free(opened_vgmstream->ch); + free(new_vgmstream->ch); - free(opened_stream->start_ch); - free(new_stream->start_ch); + free(opened_vgmstream->start_ch); + free(new_vgmstream->start_ch); - if (opened_stream->loop_ch) { - free(opened_stream->loop_ch); - free(new_stream->loop_ch); + if (opened_vgmstream->loop_ch) { + free(opened_vgmstream->loop_ch); + free(new_vgmstream->loop_ch); } /* fill in the new structures */ - opened_stream->ch = new_chans; - opened_stream->start_ch = new_start_chans; - opened_stream->loop_ch = new_loop_chans; + opened_vgmstream->ch = new_chans; + opened_vgmstream->start_ch = new_start_chans; + opened_vgmstream->loop_ch = new_loop_chans; /* stereo! */ - opened_stream->channels = 2; + opened_vgmstream->channels = 2; /* discard the second VGMSTREAM */ - free(new_stream); + free(new_vgmstream); } + fail: return; } -static int get_vgmstream_channel_count(VGMSTREAM * vgmstream) +/* average bitrate helper */ +static int get_vgmstream_average_bitrate_channel_count(VGMSTREAM * vgmstream) { + //AAX, AIX, ACM? + if (vgmstream->layout_type==layout_scd_int) { scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data; - if (data) { - return data->substream_count; - } - else { - return 0; - } + return (data) ? data->substream_count : 0; } #ifdef VGM_USE_VORBIS if (vgmstream->coding_type==coding_ogg_vorbis) { ogg_vorbis_codec_data *data = (ogg_vorbis_codec_data *) vgmstream->codec_data; - - if (data) { - return 1; - } - else { - return 0; - } + return (data) ? 1 : 0; } #endif if (vgmstream->coding_type==coding_CRI_HCA) { hca_codec_data *data = (hca_codec_data *) vgmstream->codec_data; - - if (data) { - return 1; - } - else { - return 0; - } + return (data) ? 1 : 0; } #ifdef VGM_USE_FFMPEG if (vgmstream->coding_type==coding_FFmpeg) { ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; - - if (data) { - return 1; - } - else { - return 0; - } + return (data) ? 1 : 0; } #endif #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) if (vgmstream->coding_type==coding_MP4_AAC) { mp4_aac_codec_data *data = (mp4_aac_codec_data *) vgmstream->codec_data; - if (data) { - return 1; - } - else { - return 0; - } + return (data) ? 1 : 0; } #endif return vgmstream->channels; } -static STREAMFILE * get_vgmstream_streamfile(VGMSTREAM * vgmstream, int channel) +/* average bitrate helper */ +static STREAMFILE * get_vgmstream_average_bitrate_channel_streamfile(VGMSTREAM * vgmstream, int channel) { + //AAX, AIX, ACM? + if (vgmstream->layout_type==layout_scd_int) { scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data; return data->intfiles[channel]; @@ -2347,19 +2375,16 @@ static STREAMFILE * get_vgmstream_streamfile(VGMSTREAM * vgmstream, int channel) #ifdef VGM_USE_VORBIS if (vgmstream->coding_type==coding_ogg_vorbis) { ogg_vorbis_codec_data *data = (ogg_vorbis_codec_data *) vgmstream->codec_data; - return data->ov_streamfile.streamfile; } #endif if (vgmstream->coding_type==coding_CRI_HCA) { hca_codec_data *data = (hca_codec_data *) vgmstream->codec_data; - return data->streamfile; } #ifdef VGM_USE_FFMPEG if (vgmstream->coding_type==coding_FFmpeg) { ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; - return data->streamfile; } #endif @@ -2372,42 +2397,41 @@ static STREAMFILE * get_vgmstream_streamfile(VGMSTREAM * vgmstream, int channel) return vgmstream->ch[channel].streamfile; } -static int get_vgmstream_channel_average_bitrate(STREAMFILE * streamfile, int sample_rate, int length_samples) -{ +static int get_vgmstream_average_bitrate_from_streamfile(STREAMFILE * streamfile, int sample_rate, int length_samples) { + // todo: not correct in subsongs or formats which only use part of the data return (int)((int64_t)get_streamfile_size(streamfile) * 8 * sample_rate / length_samples); } -int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) -{ +/* Return the average bitrate in bps of all unique files contained within this stream. */ +int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) { char path_current[PATH_LIMIT]; char path_compare[PATH_LIMIT]; - + unsigned int i, j; int bitrate = 0; int sample_rate = vgmstream->sample_rate; int length_samples = vgmstream->num_samples; - int channels = get_vgmstream_channel_count(vgmstream); + int channels = get_vgmstream_average_bitrate_channel_count(vgmstream); STREAMFILE * streamFile; if (!sample_rate || !channels || !length_samples) return 0; - + if (channels >= 1) { - streamFile = get_vgmstream_streamfile(vgmstream, 0); + streamFile = get_vgmstream_average_bitrate_channel_streamfile(vgmstream, 0); if (streamFile) { - bitrate += get_vgmstream_channel_average_bitrate(streamFile, sample_rate, length_samples); + bitrate += get_vgmstream_average_bitrate_from_streamfile(streamFile, sample_rate, length_samples); } } - for (i = 1; i < channels; ++i) - { - streamFile = get_vgmstream_streamfile(vgmstream, i); + /* Compares files by absolute paths, so bitrate doesn't multiply when the same STREAMFILE is reopened per channel */ + for (i = 1; i < channels; ++i) { + streamFile = get_vgmstream_average_bitrate_channel_streamfile(vgmstream, i); if (!streamFile) continue; streamFile->get_name(streamFile, path_current, sizeof(path_current)); - for (j = 0; j < i; ++j) - { - STREAMFILE * compareFile = get_vgmstream_streamfile(vgmstream, j); + for (j = 0; j < i; ++j) { + STREAMFILE * compareFile = get_vgmstream_average_bitrate_channel_streamfile(vgmstream, j); if (!compareFile) continue; streamFile->get_name(compareFile, path_compare, sizeof(path_compare)); @@ -2415,9 +2439,9 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) break; } if (j == i) - bitrate += get_vgmstream_channel_average_bitrate(streamFile, sample_rate, length_samples); + bitrate += get_vgmstream_average_bitrate_from_streamfile(streamFile, sample_rate, length_samples); } - + return bitrate; } @@ -2436,8 +2460,10 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s int use_same_offset_per_channel = 0; - /* stream/offsets not needed, scd manages itself */ - if (vgmstream->layout_type == layout_scd_int) + /* stream/offsets not needed, manages themselves */ + if (vgmstream->layout_type == layout_aix || + vgmstream->layout_type == layout_aax || + vgmstream->layout_type == layout_scd_int) return 1; #ifdef VGM_USE_FFMPEG @@ -2485,6 +2511,11 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s } } + /* EA-MT decoder is a bit finicky and needs this when channel offsets change */ + if (vgmstream->coding_type == coding_EA_MT) { + flush_ea_mt(vgmstream); + } + return 1; fail: diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 0f30d0151..9d6e29894 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -79,20 +79,19 @@ enum { STREAM_NAME_SIZE = 255 }; /* reasonable max */ #include "nwa_decoder.h" #endif - /* The encoding type specifies the format the sound data itself takes */ typedef enum { /* PCM */ coding_PCM16LE, /* little endian 16-bit PCM */ - coding_PCM16LE_XOR_int, /* little endian 16-bit PCM with sample-level xor */ + coding_PCM16LE_XOR_int, /* little endian 16-bit PCM with sample-level xor (for blocks) */ coding_PCM16BE, /* big endian 16-bit PCM */ - coding_PCM16_int, /* 16-bit PCM with sample-level interleave */ + coding_PCM16_int, /* 16-bit PCM with sample-level interleave (for blocks) */ coding_PCM8, /* 8-bit PCM */ - coding_PCM8_int, /* 8-Bit PCM with sample-level interleave */ + coding_PCM8_int, /* 8-Bit PCM with sample-level interleave (for blocks) */ coding_PCM8_U, /* 8-bit PCM, unsigned (0x80 = 0) */ - coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0) with sample-level interleave */ - coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave */ + coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0) with sample-level interleave (for blocks) */ + coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave (for blocks) */ coding_ULAW, /* 8-bit u-Law (non-linear PCM) */ coding_ALAW, /* 8-bit a-Law (non-linear PCM) */ @@ -107,6 +106,7 @@ typedef enum { coding_CRI_ADX_enc_9, /* CRI ADX, type 9 encryption (PSO2) */ coding_NGC_DSP, /* Nintendo DSP ADPCM */ + coding_NGC_DSP_subint, /* Nintendo DSP ADPCM with frame subinterframe */ coding_NGC_DTK, /* Nintendo DTK ADPCM (hardware disc), also called TRK or ADP */ coding_NGC_AFC, /* Nintendo AFC ADPCM */ @@ -125,25 +125,26 @@ typedef enum { coding_MAXIS_XA, /* Maxis EA-XA ADPCM */ coding_EA_XAS, /* Electronic Arts EA-XAS ADPCM */ + coding_IMA, /* IMA ADPCM (stereo or mono, low nibble first) */ + coding_IMA_int, /* IMA ADPCM (mono/interleave, low nibble first) */ + coding_DVI_IMA, /* DVI IMA ADPCM (stereo or mono, high nibble first) */ + 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_IMA, /* IMA ADPCM (low nibble first) */ - coding_IMA_int, /* IMA ADPCM (interleaved) */ - coding_DVI_IMA, /* DVI IMA ADPCM (high nibble first), aka ADP4 */ - coding_DVI_IMA_int, /* DVI IMA ADPCM (Interleaved) */ coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ - coding_EACS_IMA, /* Electronic Arts IMA ADPCM */ - coding_MS_IMA, /* Microsoft IMA ADPCM */ + coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */ coding_RAD_IMA, /* Radical IMA ADPCM */ coding_RAD_IMA_mono, /* Radical IMA ADPCM, mono (for interleave) */ coding_APPLE_IMA4, /* Apple Quicktime IMA4 */ - coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */ coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */ coding_OTNS_IMA, /* Omikron The Nomad Soul IMA ADPCM */ coding_FSB_IMA, /* FMOD's FSB multichannel IMA ADPCM */ coding_WWISE_IMA, /* Audiokinetic Wwise IMA ADPCM */ coding_REF_IMA, /* Reflections IMA ADPCM */ coding_AWC_IMA, /* Rockstar AWC IMA ADPCM */ + coding_UBI_IMA, /* Ubisoft IMA ADPCM */ coding_MSADPCM, /* Microsoft ADPCM */ coding_WS, /* Westwood Studios VBR ADPCM */ @@ -161,9 +162,7 @@ typedef enum { coding_SDX2_int, /* SDX2 2:1 Squareroot-Delta-Exact compression with sample-level interleave */ coding_CBD2, /* CBD2 2:1 Cuberoot-Delta-Exact compression DPCM */ coding_CBD2_int, /* CBD2 2:1 Cuberoot-Delta-Exact compression, with sample-level interleave */ - coding_ACM, /* InterPlay ACM */ - coding_NWA0, /* Visual Art's NWA (compressed at various levels) */ coding_NWA1, coding_NWA2, @@ -171,6 +170,8 @@ typedef enum { coding_NWA4, coding_NWA5, + coding_EA_MT, /* Electronic Arts MicroTalk (linear-predictive speech codec) */ + coding_CRI_HCA, /* CRI High Compression Audio (MDCT-based) */ #ifdef VGM_USE_VORBIS @@ -216,20 +217,19 @@ typedef enum { /* interleave */ layout_interleave, /* equal interleave throughout the stream */ layout_interleave_shortblock, /* interleave with a short last block */ - layout_interleave_byte, /* full byte interleave */ /* headered blocks */ layout_ast_blocked, layout_halpst_blocked, layout_xa_blocked, - layout_ea_blocked, - layout_eacs_blocked, + layout_blocked_ea_schl, + layout_blocked_ea_1snh, layout_caf_blocked, layout_wsi_blocked, layout_str_snds_blocked, layout_ws_aud_blocked, layout_matx_blocked, - layout_de2_blocked, + layout_blocked_dec, layout_xvas_blocked, layout_vs_blocked, layout_emff_ps2_blocked, @@ -241,15 +241,16 @@ typedef enum { layout_ps2_adm_blocked, layout_dsp_bdsp_blocked, layout_mxch_blocked, - layout_ivaud_blocked, /* GTA IV .ivaud blocks */ + layout_blocked_ivaud, /* GTA IV .ivaud blocks */ layout_tra_blocked, /* DefJam Rapstar .tra blocks */ layout_ps2_iab_blocked, layout_ps2_strlr_blocked, layout_rws_blocked, layout_hwas_blocked, - layout_ea_sns_blocked, /* newest Electronic Arts blocks, found in SNS/SNU/SPS/etc formats */ + layout_blocked_ea_sns, /* newest Electronic Arts blocks, found in SNS/SNU/SPS/etc formats */ layout_blocked_awc, /* Rockstar AWC */ - layout_blocked_vgs, /* Guitar Hero II */ + layout_blocked_vgs, /* Guitar Hero II (PS2) */ + layout_blocked_vawx, /* No More Heroes 6ch (PS3) */ /* otherwise odd */ layout_acm, /* libacm layout */ @@ -291,7 +292,7 @@ typedef enum { /* Nintendo */ meta_STRM, /* Nintendo STRM */ - meta_RSTM, /* Nintendo RSTM (similar to STRM) */ + meta_RSTM, /* Nintendo RSTM (Revolution Stream, similar to STRM) */ meta_AFC, /* AFC */ meta_AST, /* AST */ meta_RWSD, /* single-stream RWSD */ @@ -316,7 +317,6 @@ typedef enum { meta_UTF_DSP, /* CRI ADPCM_WII, like AAX with DSP */ meta_NGC_ADPDTK, /* NGC DTK/ADP (.adp/dkt DTK) [no header_id] */ - meta_kRAW, /* almost headerless PCM */ meta_RSF, /* Retro Studios RSF (Metroid Prime .rsf) [no header_id] */ meta_HALPST, /* HAL Labs HALPST */ meta_GCSW, /* GCSW (PCM) */ @@ -325,7 +325,7 @@ typedef enum { meta_HIS, /* Her Ineractive .his */ meta_BNSF, /* Bandai Namco Sound Format */ - meta_PSX_XA, /* CD-ROM XA with RIFF header */ + meta_PSX_XA, /* CD-ROM XA */ meta_PS2_SShd, /* .ADS with SShd header */ meta_PS2_NPSF, /* Namco Production Sound File */ meta_PS2_RXWS, /* Sony games (Genji, Okage Shadow King, Arc The Lad Twilight of Spirits) */ @@ -377,8 +377,8 @@ typedef enum { meta_PS2_KCES, /* Dance Dance Revolution */ meta_PS2_DXH, /* Tokobot Plus - Myteries of the Karakuri */ meta_PS2_PSH, /* Dawn of Mana - Seiken Densetsu 4 */ - meta_PCM_SCD, /* Lunar - Eternal Blue */ - meta_PCM_PS2, /* Konami: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses */ + meta_SCD_PCM, /* Lunar - Eternal Blue */ + meta_PS2_PCM, /* Konami KCEJ East: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses, 7 Blades */ meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 */ meta_PS2_PSW, /* Rayman Raving Rabbids */ meta_PS2_VAS, /* Pro Baseball Spirits 5 */ @@ -468,9 +468,7 @@ typedef enum { meta_EA_SCHL, /* Electronic Arts SCHl with variable header */ meta_EA_SCHL_fixed, /* Electronic Arts SCHl with fixed header */ meta_EA_BNK, /* Electronic Arts BNK */ - meta_EACS_PC, /* Electronic Arts EACS PC */ - meta_EACS_PSX, /* Electronic Arts EACS PSX */ - meta_EACS_SAT, /* Electronic Arts EACS SATURN */ + meta_EA_1SNH, /* Electronic Arts 1SNh/EACS */ meta_RAW, /* RAW PCM file */ @@ -482,7 +480,7 @@ typedef enum { meta_WS_AUD, /* Westwood Studios .aud */ meta_WS_AUD_old, /* Westwood Studios .aud, old style */ meta_RIFF_WAVE, /* RIFF, for WAVs */ - meta_RIFF_WAVE_POS, /* .wav + .pos for looping */ + meta_RIFF_WAVE_POS, /* .wav + .pos for looping (Ys Complete PC) */ meta_RIFF_WAVE_labl, /* RIFF w/ loop Markers in LIST-adtl-labl */ meta_RIFF_WAVE_smpl, /* RIFF w/ loop data in smpl chunk */ meta_RIFF_WAVE_MWV, /* .mwv RIFF w/ loop data in ctrl chunk pflt */ @@ -491,15 +489,15 @@ typedef enum { meta_RIFX_WAVE_smpl, /* RIFX w/ loop data in smpl chunk */ meta_XNB, /* XNA Game Studio 4.0 */ meta_PC_MXST, /* Lego Island MxSt */ - meta_PC_SOB_SAB, /* Worms 4 Mayhem SOB+SAB file */ + meta_SAB, /* Worms 4 Mayhem SAB+SOB file */ meta_NWA, /* Visual Art's NWA */ meta_NWA_NWAINFOINI, /* Visual Art's NWA w/ NWAINFO.INI for looping */ meta_NWA_GAMEEXEINI, /* Visual Art's NWA w/ Gameexe.ini for looping */ - meta_DVI, /* DVI Interleaved */ - meta_KCEY, /* KCEYCOMP */ + meta_SAT_DVI, /* Konami KCE Nagoya DVI (SAT games) */ + meta_DC_KCEY, /* Konami KCE Yokohama KCEYCOMP (DC games) */ meta_ACM, /* InterPlay ACM header */ meta_MUS_ACM, /* MUS playlist of InterPlay ACM files */ - meta_DE2, /* Falcom (Gurumin) .de2 */ + meta_DEC, /* Falcom PC games (Xanadu Next, Gurumin) */ meta_VS, /* Men in Black .vs */ meta_FFXI_BGW, /* FFXI (PC) BGW */ meta_FFXI_SPW, /* FFXI (PC) SPW */ @@ -602,8 +600,8 @@ typedef enum { meta_PS2_2PFS, // Konami: Mahoromatic: Moetto - KiraKira Maid-San, GANTZ (PS2) meta_PS2_VBK, // Disney's Stitch - Experiment 626 meta_OTM, // Otomedius (Arcade) - meta_CSTM, // Nintendo 3DS CSTM - meta_FSTM, // Nintendo Wii U FSTM + meta_CSTM, // Nintendo 3DS CSTM (Century Stream) + meta_FSTM, // Nintendo Wii U FSTM (caFe? Stream) meta_3DS_IDSP, // Nintendo 3DS/Wii U IDSP meta_KT_WIIBGM, // Koei Tecmo WiiBGM meta_MCA, /* Capcom MCA "MADP" */ @@ -638,6 +636,16 @@ typedef enum { meta_AWC, /* Rockstar AWC (GTA5, RDR) */ meta_NSW_OPUS, /* Lego City Undercover (Switch) */ meta_PC_AL2, /* Conquest of Elysium 3 (PC) */ + meta_PC_AST, /* Dead Rising (PC) */ + meta_NAAC, /* Namco AAC (3DS) */ + meta_UBI_SB, /* Ubisoft banks */ + meta_EZW, /* EZ2DJ (Arcade) EZWAV */ + meta_VXN, /* Gameloft mobile games */ + meta_EA_SNR_SNS, /* Electronic Arts SNR+SNS (Burnout Paradise) */ + meta_EA_SPS, /* Electronic Arts SPS (Burnout Crash) */ + meta_NGC_VID1, /* Neversoft .ogg (Gun GC) */ + meta_PC_FLX, /* Ultima IX PC */ + meta_MOGG, /* Harmonix Music Systems MOGG Vorbis */ #ifdef VGM_USE_VORBIS meta_OGG_VORBIS, /* Ogg Vorbis */ @@ -721,46 +729,42 @@ typedef struct { layout_t layout_type; /* type of layout for data */ meta_t meta_type; /* how we know the metadata */ - /* streams (info only) */ - int num_streams; /* for multi-stream formats (0=not set/one, 1=one stream) */ - int stream_index; /* current stream */ - char stream_name[STREAM_NAME_SIZE]; /* name of the current stream, if the file stores it and it's filled */ + /* subsongs */ + int num_streams; /* for multi-stream formats (0=not set/one stream, 1=one stream) */ + int stream_index; /* selected stream (also 1-based) */ + char stream_name[STREAM_NAME_SIZE]; /* name of the current stream (info), if the file stores it and it's filled */ /* looping */ - int loop_flag; /* is this stream looped? */ - int32_t loop_start_sample; /* first sample of the loop (included in the loop) */ - int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */ + int loop_flag; /* is this stream looped? */ + int32_t loop_start_sample; /* first sample of the loop (included in the loop) */ + int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */ - /* channels */ - VGMSTREAMCHANNEL * ch; /* pointer to array of channels */ + /* layouts/block */ + size_t interleave_block_size; /* interleave, or block/frame size (depending on the codec) */ + size_t interleave_smallblock_size; /* smaller interleave for last block */ - /* channel copies */ + /* channel state */ + VGMSTREAMCHANNEL * ch; /* pointer to array of channels */ VGMSTREAMCHANNEL * start_ch; /* copies of channel status as they were at the beginning of the stream */ VGMSTREAMCHANNEL * loop_ch; /* copies of channel status as they were at the loop point */ - /* layout-specific */ + /* layout/block state */ + size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */ int32_t current_sample; /* number of samples we've passed */ int32_t samples_into_block; /* number of samples into the current block */ - /* interleave */ - size_t interleave_block_size; /* interleave for this file */ - size_t interleave_smallblock_size; /* smaller interleave for last block */ - /* headered blocks */ off_t current_block_offset; /* start of this block (offset of block header) */ size_t current_block_size; /* size in usable bytes of the block we're in now (used to calculate num_samples per block) */ size_t current_block_samples; /* size in samples of the block we're in now (used over current_block_size if possible) */ - size_t full_block_size; /* size including padding and other unusable data */ off_t next_block_offset; /* offset of header of the next block */ - int block_count; /* count of "semi" block in total block */ - - - /* loop layout (saved values) */ + /* layout/block loop state */ int32_t loop_sample; /* saved from current_sample, should be loop_start_sample... */ int32_t loop_samples_into_block;/* saved from samples_into_block */ off_t loop_block_offset; /* saved from current_block_offset */ size_t loop_block_size; /* saved from current_block_size */ + size_t loop_block_samples; /* saved from current_block_samples */ off_t loop_next_block_offset; /* saved from next_block_offset */ - /* loop internals */ + /* loop state */ int hit_loop; /* have we seen the loop yet? */ /* counters for "loop + play end of the stream instead of fading" (not used/needed otherwise) */ int loop_count; /* number of complete loops (1=looped once) */ @@ -772,17 +776,11 @@ typedef struct { uint8_t xa_channel; /* XA ADPCM: selected channel */ int32_t xa_sector_length; /* XA ADPCM: XA block */ - uint8_t xa_headerless; /* XA ADPCM: headerless XA block */ - - int8_t get_high_nibble; /* ADPCM: which nibble (XA, IMA, EA) */ - - uint8_t ea_big_endian; /* EA ADPCM stuff */ - uint8_t ea_platform; + uint8_t xa_headerless; /* XA ADPCM: headerless XA */ + int8_t xa_get_high_nibble; /* XA ADPCM: mono/stereo nibble selection (XA state could be simplified) */ int32_t ws_output_size; /* WS ADPCM: output bytes for this block */ - int32_t thpNextFrameSize; /* THP */ - void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream (for AAX/AIX/SCD) */ /* Data the codec needs for the whole stream. This is for codecs too @@ -818,11 +816,12 @@ typedef struct { /* custom Vorbis modes */ typedef enum { - VORBIS_FSB, /* simplified/external setup packets, custom packet headers */ - VORBIS_WWISE, /* many variations (custom setup, headers and data) */ - VORBIS_OGL, /* custom packet headers */ - VORBIS_SK /* "OggS" replaced by "SK" */ - //VORBIS_LYN /* two interleaved Ogg (including setup, duplicated) */ + VORBIS_FSB, /* FMOD FSB: simplified/external setup packets, custom packet headers */ + VORBIS_WWISE, /* Wwise WEM: many variations (custom setup, headers and data) */ + VORBIS_OGL, /* Shin'en OGL: custom packet headers */ + VORBIS_SK, /* Silicon Knights AUD: "OggS" replaced by "SK" */ + VORBIS_VID1, /* Neversoft VID1: custom packet blocks/headers */ + //VORBIS_LYN /* Ubisoft LyN: two interleaved Ogg (including setup, duplicated) */ } vorbis_custom_t; /* config for Wwise Vorbis (3 types for flexibility though not all combinations exist) */ @@ -873,6 +872,9 @@ typedef struct { uint8_t prev_blockflag; /* blockflag in the last decoded packet */ /* Ogg-style Vorbis: packet within a page */ int current_packet; + /* reference for page/blocks */ + off_t block_offset; + size_t block_size; } vorbis_custom_codec_data; #endif @@ -887,9 +889,10 @@ typedef enum { MPEG_FSB, /* N streams of 1 data-frame+padding (=interleave) */ MPEG_P3D, /* N streams of fixed interleave (not frame-aligned) */ MPEG_EA, /* 1 stream (maybe N streams in absolute offsets?) */ - MPEG_EAL31, /* EALayer3 v1, custom frames with v1 header */ - MPEG_EAL32P, /* EALayer3 v2 "P" (PCM?), custom frames with v2 header */ - MPEG_EAL32S, /* EALayer3 v2 "S" (Spike?), custom frames with v2 header */ + MPEG_EAL31, /* EALayer3 v1 (SCHl), custom frames with v1 header */ + MPEG_EAL31b, /* EALayer3 v1 (SNS), custom frames with v1 header + minor changes */ + MPEG_EAL32P, /* EALayer3 v2 "PCM", custom frames with v2 header + bigger PCM blocks? */ + MPEG_EAL32S, /* EALayer3 v2 "Spike", custom frames with v2 header + smaller PCM blocks? */ MPEG_LYN, /* N streams of fixed interleave */ MPEG_AWC /* N streams in block layout (music) or absolute offsets (sfx) */ } mpeg_custom_t; @@ -911,6 +914,12 @@ typedef struct { /* represents a single MPEG stream */ typedef struct { + /* per stream as sometimes mpg123 must be fed in passes if data is big enough (ex. EALayer3 multichannel) */ + uint8_t *buffer; /* raw data buffer */ + size_t buffer_size; + size_t bytes_in_buffer; + int buffer_full; /* raw buffer has been filled */ + int buffer_used; /* raw buffer has been fed to the decoder */ mpg123_handle *m; /* MPEG decoder */ uint8_t *output_buffer; /* decoded samples from this stream (in bytes for mpg123) */ @@ -922,16 +931,18 @@ typedef struct { size_t current_size_target; /* max data, until something happens */ size_t decode_to_discard; /* discard from this stream only (for EALayer3 or AWC) */ + } mpeg_custom_stream; typedef struct { - uint8_t *buffer; /* internal raw data buffer */ + /* regular/single MPEG internals */ + uint8_t *buffer; /* raw data buffer */ size_t buffer_size; size_t bytes_in_buffer; int buffer_full; /* raw buffer has been filled */ int buffer_used; /* raw buffer has been fed to the decoder */ - - mpg123_handle *m; /* regular/single MPEG decoder */ + mpg123_handle *m; /* MPEG decoder */ + struct mpg123_frameinfo mi; /* start info, so it's available even when resetting */ /* for internal use, assumed to be constant for all frames */ int channels_per_frame; @@ -1042,6 +1053,7 @@ typedef enum { FFMPEG_STANDARD, /* default FFmpeg */ FFMPEG_SWITCH_OPUS, /* Opus without Ogg layer */ FFMPEG_EA_XMA, /* XMA with padding removed and custom streams in SNS blocks */ + FFMPEG_BGW_ATRAC3, /* Encrypted raw ATRAC3 */ //FFMPEG_EA_SCHL, /* Normal header+data (ex. ATRAC3) in SCxx blocks */ //FFMPEG_SFH, /* ATRAC3plus header+data in SFH blocks */ //FFMPEG_AWC_XMA, /* XMA data in AWC blocks, 1 streams per channel */ @@ -1059,6 +1071,7 @@ typedef struct { /* internal sequences, when needed */ int sequence; int samples_done; + uint8_t * key; } ffmpeg_custom_config; typedef struct { @@ -1070,7 +1083,7 @@ typedef struct { uint64_t real_size; // max size within the streamfile uint64_t virtual_offset; // computed offset FFmpeg sees (including fake header) uint64_t virtual_size; // computed size FFmpeg sees (including fake header) - uint64_t virtual_base; // info/base virtual_offset equivalent to current real_offset (block aligned) + uint64_t virtual_base; // info/base virtual_offset equivalent to current real_offset, block aligned (*not* including fake header) uint64_t header_size; // fake header (parseable by FFmpeg) prepended on reads uint8_t *header_insert_block; // fake header data (ie. RIFF) @@ -1143,6 +1156,51 @@ typedef struct { #endif #endif +typedef struct { + int pcm_blocks; + int utk_context_size; + void** utk_context; +} ea_mt_codec_data; + + +#if 0 +//possible future public/opaque API + +/* define standard C param call and name mangling (to avoid __stdcall / .defs) */ +#define VGMSTREAM_CALL __cdecl //needed? + +/* define external function types (during compilation) */ +#if defined(VGMSTREAM_EXPORT) + #define VGMSTREAM_API __declspec(dllexport) /* when exporting/creating vgmstream DLL */ +#elif defined(VGMSTREAM_IMPORT) + #define VGMSTREAM_API __declspec(dllimport) /* when importing/linking vgmstream DLL */ +#else + #define VGMSTREAM_API /* nothing, internal/default */ +#endif + +//VGMSTREAM_API void VGMSTREAM_CALL vgmstream_function(void); + +//info for opaque VGMSTREAM +typedef struct { + int channels; + int sample_rate; + int num_samples; + int loop_start_sample; + int loop_end_sample; + int loop_flag; + int num_streams; + int current_sample; + int average_bitrate; +} VGMSTREAM_INFO; +void vgmstream_get_info(VGMSTREAM* vgmstream, VGMSTREAM_INFO *vgmstream_info); + +//or maybe +enum vgmstream_value_t { VGMSTREAM_CHANNELS, VGMSTREAM_CURRENT_SAMPLE, ... }; +int vgmstream_get_info(VGMSTREAM* vgmstream, vgmstream_value_t type); +// or +int vgmstream_get_current_sample(VGMSTREAM* vgmstream); + +#endif /* -------------------------------------------------------------------------*/ /* vgmstream "public" API */ @@ -1151,6 +1209,7 @@ typedef struct { /* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */ VGMSTREAM * init_vgmstream(const char * const filename); +/* init with custom IO via streamfile */ VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile); /* reset a VGMSTREAM to start of stream */ @@ -1162,49 +1221,55 @@ void close_vgmstream(VGMSTREAM * vgmstream); /* calculate the number of samples to be played based on looping parameters */ int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM * vgmstream); -/* render! */ +/* Decode data into sample buffer */ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); -/* Write a description of the stream into array pointed by desc, - * which must be length bytes long. Will always be null-terminated if length > 0 */ +/* Write a description of the stream into array pointed by desc, which must be length bytes long. + * Will always be null-terminated if length > 0 */ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length); -/* Return the average bitrate in bps of all unique files contained within this - * stream. Compares files by absolute paths. */ +/* Return the average bitrate in bps of all unique files contained within this stream. */ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream); +/* List supported formats and return elements in the list, for plugins that need to know. */ +const char ** vgmstream_get_formats(size_t * size); + +/* Force enable/disable internal looping. Should be done before playing anything, + * and not all codecs support arbitrary loop values ATM. */ +void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample); + /* -------------------------------------------------------------------------*/ /* vgmstream "private" API */ /* -------------------------------------------------------------------------*/ -/* allocate a VGMSTREAM and channel stuff */ +/* Allocate memory and setup a VGMSTREAM */ VGMSTREAM * allocate_vgmstream(int channel_count, int looped); -/* smallest self-contained group of samples is a frame */ +/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream); -/* number of bytes per frame */ +/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */ int get_vgmstream_frame_size(VGMSTREAM * vgmstream); -/* in NDS IMA the frame size is the block size, so the last one is short */ +/* In NDS IMA the frame size is the block size, so the last one is short */ int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream); int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream); -/* Assume that we have written samples_written into the buffer already, and we have samples_to_do consecutive - * samples ahead of us. Decode those samples into the buffer. */ +/* Decode samples into the buffer. Assume that we have written samples_written into the + * buffer already, and we have samples_to_do consecutive samples ahead of us. */ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer); -/* Assume additionally that we have samples_to_do consecutive samples in "data", - * and this this is for channel number "channel" */ -void decode_vgmstream_mem(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer, uint8_t * data, int channel); - -/* calculate number of consecutive samples to do (taking into account stopping for loop start and end) */ +/* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM * vgmstream); -/* Detect start and save values, also detect end and restore values. Only works on exact sample values. - * Returns 1 if loop was done. */ +/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */ int vgmstream_do_loop(VGMSTREAM * vgmstream); /* Open the stream for reading at offset (standarized taking into account layouts, channels and so on). * returns 0 on failure */ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset); +/* get description info */ +const char * get_vgmstream_coding_description(coding_t coding_type); +const char * get_vgmstream_layout_description(layout_t layout_type); +const char * get_vgmstream_meta_description(meta_t meta_type); + #endif diff --git a/Plugins/vgmstream/vgmstream/VGMDecoder.m b/Plugins/vgmstream/vgmstream/VGMDecoder.m index 59467fd58..8bbb6a668 100644 --- a/Plugins/vgmstream/vgmstream/VGMDecoder.m +++ b/Plugins/vgmstream/vgmstream/VGMDecoder.m @@ -136,10 +136,10 @@ { NSMutableArray *array = [[NSMutableArray alloc] init]; - int count = vgmstream_get_formats_length(); - const char ** formats = vgmstream_get_formats(); + size_t count; + const char ** formats = vgmstream_get_formats(&count); - for (int i = 0; i < count; ++i) + for (size_t i = 0; i < count; ++i) { [array addObject:[NSString stringWithUTF8String:formats[i]]]; }