Updated VGMStream to r1050-866-g5cc215b4.

CQTexperiment
Christopher Snowhill 2017-12-16 20:17:41 -08:00
parent 10f2ee1461
commit 16e0a006f2
157 changed files with 8449 additions and 5906 deletions

View File

@ -37,6 +37,40 @@
83345A511F8AEB2800B2EAA4 /* nsw_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */; }; 83345A511F8AEB2800B2EAA4 /* nsw_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */; };
83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4E1F8AEB2800B2EAA4 /* xvag.c */; }; 83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4E1F8AEB2800B2EAA4 /* xvag.c */; };
833A7A2E1ED11961003EC53E /* xau.c in Sources */ = {isa = PBXBuildFile; fileRef = 833A7A2D1ED11961003EC53E /* xau.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 */; }; 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */ = {isa = PBXBuildFile; fileRef = 834D3A6D19F47C98001C54F6 /* g1l.c */; };
8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8350270C1ED119D200C25929 /* ps3_mta2.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 */; }; 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 */; }; 836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0318BDC2180095E648 /* bdsp_blocked.c */; };
836F6F4118BDC2190095E648 /* blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0418BDC2180095E648 /* 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 836F6F4918BDC2190095E648 /* ims_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0C18BDC2180095E648 /* ims_block.c */; };
836F6F4A18BDC2190095E648 /* interleave.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0D18BDC2180095E648 /* interleave.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 */; }; 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 */; }; 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 */; }; 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 */; }; 836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; };
836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; }; 836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; };
836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.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 */; }; 836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; };
836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; }; 836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; };
836F6F6D18BDC2190095E648 /* aifc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3118BDC2180095E648 /* aifc.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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 836F6F8418BDC2190095E648 /* emff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4818BDC2180095E648 /* emff.c */; };
836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4918BDC2180095E648 /* exakt_sc.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 */; }; 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 */; }; 836F6F8918BDC2190095E648 /* gca.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4D18BDC2180095E648 /* gca.c */; };
836F6F8A18BDC2190095E648 /* gcsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4E18BDC2180095E648 /* gcsw.c */; }; 836F6F8A18BDC2190095E648 /* gcsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4E18BDC2180095E648 /* gcsw.c */; };
836F6F8B18BDC2190095E648 /* genh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4F18BDC2180095E648 /* genh.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 */; }; 836F6F8D18BDC2190095E648 /* gsp_gsb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5118BDC2180095E648 /* gsp_gsb.c */; };
836F6F8E18BDC2190095E648 /* halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5218BDC2180095E648 /* halpst.c */; }; 836F6F8E18BDC2190095E648 /* halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5218BDC2180095E648 /* halpst.c */; };
836F6F8F18BDC2190095E648 /* his.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5318BDC2180095E648 /* his.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 */; }; 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 */; }; 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 */; }; 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 */; }; 836F6FC718BDC2190095E648 /* pona.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8B18BDC2180095E648 /* pona.c */; };
836F6FC818BDC2190095E648 /* pos.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8C18BDC2180095E648 /* pos.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 */; }; 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 */; }; 836F702E18BDC2190095E648 /* sli.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF218BDC2190095E648 /* sli.c */; };
836F702F18BDC2190095E648 /* spt_spd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF318BDC2190095E648 /* spt_spd.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 */; }; 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 */; }; 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 */; }; 836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; };
836F703418BDC2190095E648 /* stx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF818BDC2190095E648 /* stx.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 */; }; 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 */; }; 839E21EB1F2EDB0600EE54D7 /* sk_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */; };
83A3F0741E3AD8B900D6A794 /* formats.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F0711E3AD8B900D6A794 /* formats.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 */; }; 83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */; };
83A5F75F198DF021009AF94C /* bfwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A5F75E198DF021009AF94C /* bfwav.c */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */; }; 83AA5D241F6E2F9C0020821C /* awc.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D201F6E2F9B0020821C /* awc.c */; };
83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AA5D211F6E2F9C0020821C /* hca_keys.h */; }; 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 */; }; 83AA5D271F6E2F9C0020821C /* stm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D231F6E2F9C0020821C /* stm.c */; };
83AB8C751E8072A100086084 /* nub_vag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C731E8072A100086084 /* nub_vag.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 */; }; 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 = "<group>"; }; 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nsw_opus.c; sourceTree = "<group>"; };
83345A4E1F8AEB2800B2EAA4 /* xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xvag.c; sourceTree = "<group>"; }; 83345A4E1F8AEB2800B2EAA4 /* xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xvag.c; sourceTree = "<group>"; };
833A7A2D1ED11961003EC53E /* xau.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xau.c; sourceTree = "<group>"; }; 833A7A2D1ED11961003EC53E /* xau.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xau.c; sourceTree = "<group>"; };
8349A8DC1FE6251E00E26435 /* vorbis_custom_utils_vid1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_vid1.c; sourceTree = "<group>"; };
8349A8DD1FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils_bgw_atrac3.c; sourceTree = "<group>"; };
8349A8DE1FE6251F00E26435 /* ea_mt_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_mt_decoder.c; sourceTree = "<group>"; };
8349A8E21FE6253800E26435 /* blocked_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_dec.c; sourceTree = "<group>"; };
8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_1snh.c; sourceTree = "<group>"; };
8349A8E41FE6253800E26435 /* blocked_ea_schl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_schl.c; sourceTree = "<group>"; };
8349A8E51FE6253800E26435 /* blocked_ivaud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ivaud.c; sourceTree = "<group>"; };
8349A8E61FE6253900E26435 /* blocked_vawx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_vawx.c; sourceTree = "<group>"; };
8349A8E71FE6253900E26435 /* blocked_ea_sns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_sns.c; sourceTree = "<group>"; };
8349A8EE1FE6257C00E26435 /* dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dec.c; sourceTree = "<group>"; };
8349A8EF1FE6257C00E26435 /* ezw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ezw.c; sourceTree = "<group>"; };
8349A8F01FE6257C00E26435 /* pc_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_ast.c; sourceTree = "<group>"; };
8349A8F11FE6257D00E26435 /* sab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sab.c; sourceTree = "<group>"; };
8349A8F21FE6257D00E26435 /* ps2_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_pcm.c; sourceTree = "<group>"; };
8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqex_scd_streamfile.h; sourceTree = "<group>"; };
8349A8F41FE6257D00E26435 /* ubi_sb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_sb.c; sourceTree = "<group>"; };
8349A8F51FE6257D00E26435 /* scd_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_pcm.c; sourceTree = "<group>"; };
8349A8F61FE6257E00E26435 /* aix_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aix_streamfile.h; sourceTree = "<group>"; };
8349A8F71FE6257E00E26435 /* ea_eaac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_eaac.c; sourceTree = "<group>"; };
8349A8F81FE6257E00E26435 /* bar_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bar_streamfile.h; sourceTree = "<group>"; };
8349A8F91FE6257E00E26435 /* vsf_tta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vsf_tta.c; sourceTree = "<group>"; };
8349A8FA1FE6257E00E26435 /* ngc_vid1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_vid1.c; sourceTree = "<group>"; };
8349A8FB1FE6257F00E26435 /* omu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = omu.c; sourceTree = "<group>"; };
8349A8FC1FE6257F00E26435 /* ps2_xa2_rrp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xa2_rrp.c; sourceTree = "<group>"; };
8349A8FD1FE6257F00E26435 /* flx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = flx.c; sourceTree = "<group>"; };
8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_adp_otns.c; sourceTree = "<group>"; };
8349A8FF1FE6258000E26435 /* ea_1snh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_1snh.c; sourceTree = "<group>"; };
8349A9001FE6258000E26435 /* afc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = afc.c; sourceTree = "<group>"; };
8349A9011FE6258000E26435 /* vxn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vxn.c; sourceTree = "<group>"; };
8349A9021FE6258100E26435 /* adx_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adx_keys.h; sourceTree = "<group>"; };
8349A9031FE6258100E26435 /* mogg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mogg.c; sourceTree = "<group>"; };
8349A9041FE6258100E26435 /* aax_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aax_streamfile.h; sourceTree = "<group>"; };
8349A9051FE6258100E26435 /* bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = "<group>"; };
8349A9061FE6258100E26435 /* naac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naac.c; sourceTree = "<group>"; };
834D3A6D19F47C98001C54F6 /* g1l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g1l.c; sourceTree = "<group>"; }; 834D3A6D19F47C98001C54F6 /* g1l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g1l.c; sourceTree = "<group>"; };
8350270C1ED119D200C25929 /* ps3_mta2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_mta2.c; sourceTree = "<group>"; }; 8350270C1ED119D200C25929 /* ps3_mta2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_mta2.c; sourceTree = "<group>"; };
835027121ED119E000C25929 /* mta2_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mta2_decoder.c; sourceTree = "<group>"; }; 835027121ED119E000C25929 /* mta2_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mta2_decoder.c; sourceTree = "<group>"; };
@ -586,16 +640,12 @@
836F6E0318BDC2180095E648 /* bdsp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdsp_blocked.c; sourceTree = "<group>"; }; 836F6E0318BDC2180095E648 /* bdsp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdsp_blocked.c; sourceTree = "<group>"; };
836F6E0418BDC2180095E648 /* blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked.c; sourceTree = "<group>"; }; 836F6E0418BDC2180095E648 /* blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked.c; sourceTree = "<group>"; };
836F6E0518BDC2180095E648 /* caf_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = caf_blocked.c; sourceTree = "<group>"; }; 836F6E0518BDC2180095E648 /* caf_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = caf_blocked.c; sourceTree = "<group>"; };
836F6E0618BDC2180095E648 /* de2_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = de2_blocked.c; sourceTree = "<group>"; };
836F6E0718BDC2180095E648 /* ea_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_block.c; sourceTree = "<group>"; };
836F6E0818BDC2180095E648 /* emff_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff_blocked.c; sourceTree = "<group>"; }; 836F6E0818BDC2180095E648 /* emff_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff_blocked.c; sourceTree = "<group>"; };
836F6E0918BDC2180095E648 /* filp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filp_blocked.c; sourceTree = "<group>"; }; 836F6E0918BDC2180095E648 /* filp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filp_blocked.c; sourceTree = "<group>"; };
836F6E0A18BDC2180095E648 /* gsb_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsb_blocked.c; sourceTree = "<group>"; }; 836F6E0A18BDC2180095E648 /* gsb_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsb_blocked.c; sourceTree = "<group>"; };
836F6E0B18BDC2180095E648 /* halpst_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst_blocked.c; sourceTree = "<group>"; }; 836F6E0B18BDC2180095E648 /* halpst_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst_blocked.c; sourceTree = "<group>"; };
836F6E0C18BDC2180095E648 /* ims_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ims_block.c; sourceTree = "<group>"; }; 836F6E0C18BDC2180095E648 /* ims_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ims_block.c; sourceTree = "<group>"; };
836F6E0D18BDC2180095E648 /* interleave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interleave.c; sourceTree = "<group>"; }; 836F6E0D18BDC2180095E648 /* interleave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interleave.c; sourceTree = "<group>"; };
836F6E0E18BDC2180095E648 /* interleave_byte.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interleave_byte.c; sourceTree = "<group>"; };
836F6E0F18BDC2180095E648 /* ivaud_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivaud_layout.c; sourceTree = "<group>"; };
836F6E1018BDC2180095E648 /* layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = layout.h; sourceTree = "<group>"; }; 836F6E1018BDC2180095E648 /* layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = layout.h; sourceTree = "<group>"; };
836F6E1218BDC2180095E648 /* mus_acm_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mus_acm_layout.c; sourceTree = "<group>"; }; 836F6E1218BDC2180095E648 /* mus_acm_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mus_acm_layout.c; sourceTree = "<group>"; };
836F6E1318BDC2180095E648 /* mxch_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mxch_blocked.c; sourceTree = "<group>"; }; 836F6E1318BDC2180095E648 /* mxch_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mxch_blocked.c; sourceTree = "<group>"; };
@ -617,7 +667,6 @@
836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = "<group>"; }; 836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = "<group>"; };
836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = "<group>"; }; 836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = "<group>"; };
836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = "<group>"; }; 836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = "<group>"; };
836F6E2E18BDC2180095E648 /* afc_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = afc_header.c; sourceTree = "<group>"; };
836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = "<group>"; }; 836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = "<group>"; };
836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = "<group>"; }; 836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = "<group>"; };
836F6E3118BDC2180095E648 /* aifc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aifc.c; sourceTree = "<group>"; }; 836F6E3118BDC2180095E648 /* aifc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aifc.c; sourceTree = "<group>"; };
@ -637,12 +686,10 @@
836F6E3F18BDC2180095E648 /* dc_idvi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_idvi.c; sourceTree = "<group>"; }; 836F6E3F18BDC2180095E648 /* dc_idvi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_idvi.c; sourceTree = "<group>"; };
836F6E4018BDC2180095E648 /* dc_kcey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_kcey.c; sourceTree = "<group>"; }; 836F6E4018BDC2180095E648 /* dc_kcey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_kcey.c; sourceTree = "<group>"; };
836F6E4118BDC2180095E648 /* dc_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_str.c; sourceTree = "<group>"; }; 836F6E4118BDC2180095E648 /* dc_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_str.c; sourceTree = "<group>"; };
836F6E4218BDC2180095E648 /* de2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = de2.c; sourceTree = "<group>"; };
836F6E4318BDC2180095E648 /* dmsg_segh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dmsg_segh.c; sourceTree = "<group>"; }; 836F6E4318BDC2180095E648 /* dmsg_segh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dmsg_segh.c; sourceTree = "<group>"; };
836F6E4418BDC2180095E648 /* dsp_bdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_bdsp.c; sourceTree = "<group>"; }; 836F6E4418BDC2180095E648 /* dsp_bdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_bdsp.c; sourceTree = "<group>"; };
836F6E4518BDC2180095E648 /* dsp_sth_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_sth_str.c; sourceTree = "<group>"; }; 836F6E4518BDC2180095E648 /* dsp_sth_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_sth_str.c; sourceTree = "<group>"; };
836F6E4618BDC2180095E648 /* ea_schl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_schl.c; sourceTree = "<group>"; }; 836F6E4618BDC2180095E648 /* ea_schl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_schl.c; sourceTree = "<group>"; };
836F6E4718BDC2180095E648 /* ea_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_old.c; sourceTree = "<group>"; };
836F6E4818BDC2180095E648 /* emff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff.c; sourceTree = "<group>"; }; 836F6E4818BDC2180095E648 /* emff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff.c; sourceTree = "<group>"; };
836F6E4918BDC2180095E648 /* exakt_sc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exakt_sc.c; sourceTree = "<group>"; }; 836F6E4918BDC2180095E648 /* exakt_sc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exakt_sc.c; sourceTree = "<group>"; };
836F6E4A18BDC2180095E648 /* excitebots.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = excitebots.c; sourceTree = "<group>"; }; 836F6E4A18BDC2180095E648 /* excitebots.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = excitebots.c; sourceTree = "<group>"; };
@ -651,7 +698,6 @@
836F6E4D18BDC2180095E648 /* gca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gca.c; sourceTree = "<group>"; }; 836F6E4D18BDC2180095E648 /* gca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gca.c; sourceTree = "<group>"; };
836F6E4E18BDC2180095E648 /* gcsw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gcsw.c; sourceTree = "<group>"; }; 836F6E4E18BDC2180095E648 /* gcsw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gcsw.c; sourceTree = "<group>"; };
836F6E4F18BDC2180095E648 /* genh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = genh.c; sourceTree = "<group>"; }; 836F6E4F18BDC2180095E648 /* genh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = genh.c; sourceTree = "<group>"; };
836F6E5018BDC2180095E648 /* gh3_bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gh3_bar.c; sourceTree = "<group>"; };
836F6E5118BDC2180095E648 /* gsp_gsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsp_gsb.c; sourceTree = "<group>"; }; 836F6E5118BDC2180095E648 /* gsp_gsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsp_gsb.c; sourceTree = "<group>"; };
836F6E5218BDC2180095E648 /* halpst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst.c; sourceTree = "<group>"; }; 836F6E5218BDC2180095E648 /* halpst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst.c; sourceTree = "<group>"; };
836F6E5318BDC2180095E648 /* his.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = his.c; sourceTree = "<group>"; }; 836F6E5318BDC2180095E648 /* his.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = his.c; sourceTree = "<group>"; };
@ -705,8 +751,6 @@
836F6E8618BDC2180095E648 /* pc_mxst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_mxst.c; sourceTree = "<group>"; }; 836F6E8618BDC2180095E648 /* pc_mxst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_mxst.c; sourceTree = "<group>"; };
836F6E8718BDC2180095E648 /* pc_smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_smp.c; sourceTree = "<group>"; }; 836F6E8718BDC2180095E648 /* pc_smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_smp.c; sourceTree = "<group>"; };
836F6E8818BDC2180095E648 /* pc_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_snds.c; sourceTree = "<group>"; }; 836F6E8818BDC2180095E648 /* pc_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_snds.c; sourceTree = "<group>"; };
836F6E8918BDC2180095E648 /* pc_sob.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_sob.c; sourceTree = "<group>"; };
836F6E8A18BDC2180095E648 /* pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcm.c; sourceTree = "<group>"; };
836F6E8B18BDC2180095E648 /* pona.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pona.c; sourceTree = "<group>"; }; 836F6E8B18BDC2180095E648 /* pona.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pona.c; sourceTree = "<group>"; };
836F6E8C18BDC2180095E648 /* pos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pos.c; sourceTree = "<group>"; }; 836F6E8C18BDC2180095E648 /* pos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pos.c; sourceTree = "<group>"; };
836F6E8D18BDC2180095E648 /* ps2_2pfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_2pfs.c; sourceTree = "<group>"; }; 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_2pfs.c; sourceTree = "<group>"; };
@ -806,7 +850,6 @@
836F6EF218BDC2190095E648 /* sli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sli.c; sourceTree = "<group>"; }; 836F6EF218BDC2190095E648 /* sli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sli.c; sourceTree = "<group>"; };
836F6EF318BDC2190095E648 /* spt_spd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spt_spd.c; sourceTree = "<group>"; }; 836F6EF318BDC2190095E648 /* spt_spd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spt_spd.c; sourceTree = "<group>"; };
836F6EF418BDC2190095E648 /* sqex_scd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqex_scd.c; sourceTree = "<group>"; }; 836F6EF418BDC2190095E648 /* sqex_scd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqex_scd.c; sourceTree = "<group>"; };
836F6EF518BDC2190095E648 /* ss_stream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ss_stream.c; sourceTree = "<group>"; };
836F6EF618BDC2190095E648 /* str_asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_asr.c; sourceTree = "<group>"; }; 836F6EF618BDC2190095E648 /* str_asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_asr.c; sourceTree = "<group>"; };
836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = "<group>"; }; 836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = "<group>"; };
836F6EF818BDC2190095E648 /* stx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stx.c; sourceTree = "<group>"; }; 836F6EF818BDC2190095E648 /* stx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stx.c; sourceTree = "<group>"; };
@ -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 = "<group>"; }; 839E21DF1F2EDAF000EE54D7 /* vorbis_custom_utils_sk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_sk.c; sourceTree = "<group>"; };
839E21EA1F2EDB0500EE54D7 /* sk_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sk_aud.c; sourceTree = "<group>"; }; 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sk_aud.c; sourceTree = "<group>"; };
83A3F0711E3AD8B900D6A794 /* formats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = formats.c; sourceTree = "<group>"; }; 83A3F0711E3AD8B900D6A794 /* formats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = formats.c; sourceTree = "<group>"; };
83A3F0721E3AD8B900D6A794 /* formats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = formats.h; sourceTree = "<group>"; };
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; }; 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; };
83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = "<group>"; }; 83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = "<group>"; };
83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_xa_decoder.c; sourceTree = "<group>"; }; 83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_xa_decoder.c; sourceTree = "<group>"; };
@ -893,10 +935,8 @@
83AA5D151F6E2F600020821C /* ea_xas_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_xas_decoder.c; sourceTree = "<group>"; }; 83AA5D151F6E2F600020821C /* ea_xas_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_xas_decoder.c; sourceTree = "<group>"; };
83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_vgs.c; sourceTree = "<group>"; }; 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_vgs.c; sourceTree = "<group>"; };
83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_awc.c; sourceTree = "<group>"; }; 83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_awc.c; sourceTree = "<group>"; };
83AA5D1C1F6E2F7F0020821C /* ea_sns_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_sns_blocked.c; sourceTree = "<group>"; };
83AA5D201F6E2F9B0020821C /* awc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awc.c; sourceTree = "<group>"; }; 83AA5D201F6E2F9B0020821C /* awc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awc.c; sourceTree = "<group>"; };
83AA5D211F6E2F9C0020821C /* hca_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hca_keys.h; sourceTree = "<group>"; }; 83AA5D211F6E2F9C0020821C /* hca_keys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hca_keys.h; sourceTree = "<group>"; };
83AA5D221F6E2F9C0020821C /* ea_snu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_snu.c; sourceTree = "<group>"; };
83AA5D231F6E2F9C0020821C /* stm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stm.c; sourceTree = "<group>"; }; 83AA5D231F6E2F9C0020821C /* stm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stm.c; sourceTree = "<group>"; };
83AB8C731E8072A100086084 /* nub_vag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_vag.c; sourceTree = "<group>"; }; 83AB8C731E8072A100086084 /* nub_vag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_vag.c; sourceTree = "<group>"; };
83AB8C741E8072A100086084 /* x360_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_ast.c; sourceTree = "<group>"; }; 83AB8C741E8072A100086084 /* x360_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_ast.c; sourceTree = "<group>"; };
@ -1038,7 +1078,6 @@
836F6DFF18BDC2180095E648 /* layout */, 836F6DFF18BDC2180095E648 /* layout */,
836F6E2718BDC2180095E648 /* meta */, 836F6E2718BDC2180095E648 /* meta */,
83A3F0711E3AD8B900D6A794 /* formats.c */, 83A3F0711E3AD8B900D6A794 /* formats.c */,
83A3F0721E3AD8B900D6A794 /* formats.h */,
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */, 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */,
836F6F1718BDC2190095E648 /* streamfile.c */, 836F6F1718BDC2190095E648 /* streamfile.c */,
836F6F1818BDC2190095E648 /* streamfile.h */, 836F6F1818BDC2190095E648 /* streamfile.h */,
@ -1054,6 +1093,9 @@
836F6DDF18BDC2180095E648 /* coding */ = { 836F6DDF18BDC2180095E648 /* coding */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( 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 */, 83345A491F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c */,
8374EE361F787AB500033E90 /* ffmpeg_decoder_utils_ea_xma.c */, 8374EE361F787AB500033E90 /* ffmpeg_decoder_utils_ea_xma.c */,
8374EE3D1F787AB600033E90 /* ffmpeg_decoder_utils.c */, 8374EE3D1F787AB600033E90 /* ffmpeg_decoder_utils.c */,
@ -1116,9 +1158,14 @@
836F6DFF18BDC2180095E648 /* layout */ = { 836F6DFF18BDC2180095E648 /* layout */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( 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 */, 83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */,
83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */, 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */,
83AA5D1C1F6E2F7F0020821C /* ea_sns_blocked.c */,
830165A11F256BF400CA0941 /* hwas_blocked.c */, 830165A11F256BF400CA0941 /* hwas_blocked.c */,
831BD1201EEE1D2A00198540 /* rws_blocked.c */, 831BD1201EEE1D2A00198540 /* rws_blocked.c */,
836F6E0018BDC2180095E648 /* aax_layout.c */, 836F6E0018BDC2180095E648 /* aax_layout.c */,
@ -1127,16 +1174,12 @@
836F6E0318BDC2180095E648 /* bdsp_blocked.c */, 836F6E0318BDC2180095E648 /* bdsp_blocked.c */,
836F6E0418BDC2180095E648 /* blocked.c */, 836F6E0418BDC2180095E648 /* blocked.c */,
836F6E0518BDC2180095E648 /* caf_blocked.c */, 836F6E0518BDC2180095E648 /* caf_blocked.c */,
836F6E0618BDC2180095E648 /* de2_blocked.c */,
836F6E0718BDC2180095E648 /* ea_block.c */,
836F6E0818BDC2180095E648 /* emff_blocked.c */, 836F6E0818BDC2180095E648 /* emff_blocked.c */,
836F6E0918BDC2180095E648 /* filp_blocked.c */, 836F6E0918BDC2180095E648 /* filp_blocked.c */,
836F6E0A18BDC2180095E648 /* gsb_blocked.c */, 836F6E0A18BDC2180095E648 /* gsb_blocked.c */,
836F6E0B18BDC2180095E648 /* halpst_blocked.c */, 836F6E0B18BDC2180095E648 /* halpst_blocked.c */,
836F6E0C18BDC2180095E648 /* ims_block.c */, 836F6E0C18BDC2180095E648 /* ims_block.c */,
836F6E0D18BDC2180095E648 /* interleave.c */, 836F6E0D18BDC2180095E648 /* interleave.c */,
836F6E0E18BDC2180095E648 /* interleave_byte.c */,
836F6E0F18BDC2180095E648 /* ivaud_layout.c */,
836F6E1018BDC2180095E648 /* layout.h */, 836F6E1018BDC2180095E648 /* layout.h */,
836F6E1218BDC2180095E648 /* mus_acm_layout.c */, 836F6E1218BDC2180095E648 /* mus_acm_layout.c */,
836F6E1318BDC2180095E648 /* mxch_blocked.c */, 836F6E1318BDC2180095E648 /* mxch_blocked.c */,
@ -1161,12 +1204,36 @@
836F6E2718BDC2180095E648 /* meta */ = { 836F6E2718BDC2180095E648 /* meta */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( 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 */, 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */,
83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */, 83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */,
83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */, 83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */,
83345A4E1F8AEB2800B2EAA4 /* xvag.c */, 83345A4E1F8AEB2800B2EAA4 /* xvag.c */,
83AA5D201F6E2F9B0020821C /* awc.c */, 83AA5D201F6E2F9B0020821C /* awc.c */,
83AA5D221F6E2F9C0020821C /* ea_snu.c */,
83AA5D211F6E2F9C0020821C /* hca_keys.h */, 83AA5D211F6E2F9C0020821C /* hca_keys.h */,
83AA5D231F6E2F9C0020821C /* stm.c */, 83AA5D231F6E2F9C0020821C /* stm.c */,
839E21EA1F2EDB0500EE54D7 /* sk_aud.c */, 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */,
@ -1212,7 +1279,6 @@
836F6E2A18BDC2180095E648 /* aax.c */, 836F6E2A18BDC2180095E648 /* aax.c */,
836F6E2B18BDC2180095E648 /* acm.c */, 836F6E2B18BDC2180095E648 /* acm.c */,
836F6E2C18BDC2180095E648 /* ads.c */, 836F6E2C18BDC2180095E648 /* ads.c */,
836F6E2E18BDC2180095E648 /* afc_header.c */,
836F6E2F18BDC2180095E648 /* agsc.c */, 836F6E2F18BDC2180095E648 /* agsc.c */,
836F6E3018BDC2180095E648 /* ahx.c */, 836F6E3018BDC2180095E648 /* ahx.c */,
836F6E3118BDC2180095E648 /* aifc.c */, 836F6E3118BDC2180095E648 /* aifc.c */,
@ -1232,12 +1298,10 @@
836F6E3F18BDC2180095E648 /* dc_idvi.c */, 836F6E3F18BDC2180095E648 /* dc_idvi.c */,
836F6E4018BDC2180095E648 /* dc_kcey.c */, 836F6E4018BDC2180095E648 /* dc_kcey.c */,
836F6E4118BDC2180095E648 /* dc_str.c */, 836F6E4118BDC2180095E648 /* dc_str.c */,
836F6E4218BDC2180095E648 /* de2.c */,
836F6E4318BDC2180095E648 /* dmsg_segh.c */, 836F6E4318BDC2180095E648 /* dmsg_segh.c */,
836F6E4418BDC2180095E648 /* dsp_bdsp.c */, 836F6E4418BDC2180095E648 /* dsp_bdsp.c */,
836F6E4518BDC2180095E648 /* dsp_sth_str.c */, 836F6E4518BDC2180095E648 /* dsp_sth_str.c */,
836F6E4618BDC2180095E648 /* ea_schl.c */, 836F6E4618BDC2180095E648 /* ea_schl.c */,
836F6E4718BDC2180095E648 /* ea_old.c */,
836F6E4818BDC2180095E648 /* emff.c */, 836F6E4818BDC2180095E648 /* emff.c */,
836F6E4918BDC2180095E648 /* exakt_sc.c */, 836F6E4918BDC2180095E648 /* exakt_sc.c */,
836F6E4A18BDC2180095E648 /* excitebots.c */, 836F6E4A18BDC2180095E648 /* excitebots.c */,
@ -1246,7 +1310,6 @@
836F6E4D18BDC2180095E648 /* gca.c */, 836F6E4D18BDC2180095E648 /* gca.c */,
836F6E4E18BDC2180095E648 /* gcsw.c */, 836F6E4E18BDC2180095E648 /* gcsw.c */,
836F6E4F18BDC2180095E648 /* genh.c */, 836F6E4F18BDC2180095E648 /* genh.c */,
836F6E5018BDC2180095E648 /* gh3_bar.c */,
836F6E5118BDC2180095E648 /* gsp_gsb.c */, 836F6E5118BDC2180095E648 /* gsp_gsb.c */,
836F6E5218BDC2180095E648 /* halpst.c */, 836F6E5218BDC2180095E648 /* halpst.c */,
836F6E5318BDC2180095E648 /* his.c */, 836F6E5318BDC2180095E648 /* his.c */,
@ -1300,8 +1363,6 @@
836F6E8618BDC2180095E648 /* pc_mxst.c */, 836F6E8618BDC2180095E648 /* pc_mxst.c */,
836F6E8718BDC2180095E648 /* pc_smp.c */, 836F6E8718BDC2180095E648 /* pc_smp.c */,
836F6E8818BDC2180095E648 /* pc_snds.c */, 836F6E8818BDC2180095E648 /* pc_snds.c */,
836F6E8918BDC2180095E648 /* pc_sob.c */,
836F6E8A18BDC2180095E648 /* pcm.c */,
836F6E8B18BDC2180095E648 /* pona.c */, 836F6E8B18BDC2180095E648 /* pona.c */,
836F6E8C18BDC2180095E648 /* pos.c */, 836F6E8C18BDC2180095E648 /* pos.c */,
836F6E8D18BDC2180095E648 /* ps2_2pfs.c */, 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */,
@ -1401,7 +1462,6 @@
836F6EF218BDC2190095E648 /* sli.c */, 836F6EF218BDC2190095E648 /* sli.c */,
836F6EF318BDC2190095E648 /* spt_spd.c */, 836F6EF318BDC2190095E648 /* spt_spd.c */,
836F6EF418BDC2190095E648 /* sqex_scd.c */, 836F6EF418BDC2190095E648 /* sqex_scd.c */,
836F6EF518BDC2190095E648 /* ss_stream.c */,
836F6EF618BDC2190095E648 /* str_asr.c */, 836F6EF618BDC2190095E648 /* str_asr.c */,
836F6EF718BDC2190095E648 /* str_snds.c */, 836F6EF718BDC2190095E648 /* str_snds.c */,
836F6EF818BDC2190095E648 /* stx.c */, 836F6EF818BDC2190095E648 /* stx.c */,
@ -1475,12 +1535,14 @@
836F705518BDC2190095E648 /* streamtypes.h in Headers */, 836F705518BDC2190095E648 /* streamtypes.h in Headers */,
836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */, 836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */,
836F6F3518BDC2190095E648 /* nwa_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 */, 836F6F2718BDC2190095E648 /* g72x_state.h in Headers */,
839E21E01F2EDAF100EE54D7 /* vorbis_custom_data_fsb.h in Headers */, 839E21E01F2EDAF100EE54D7 /* vorbis_custom_data_fsb.h in Headers */,
836F705418BDC2190095E648 /* streamfile.h in Headers */, 836F705418BDC2190095E648 /* streamfile.h in Headers */,
8374EE401F787AB600033E90 /* ffmpeg_decoder_utils.h in Headers */, 8374EE401F787AB600033E90 /* ffmpeg_decoder_utils.h in Headers */,
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */, 83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */,
83A3F0751E3AD8B900D6A794 /* formats.h in Headers */,
8323894B1D22419B00482226 /* clHCA.h in Headers */, 8323894B1D22419B00482226 /* clHCA.h in Headers */,
839E21E81F2EDAF100EE54D7 /* mpeg_decoder.h in Headers */, 839E21E81F2EDAF100EE54D7 /* mpeg_decoder.h in Headers */,
839E21E51F2EDAF100EE54D7 /* vorbis_custom_decoder.h in Headers */, 839E21E51F2EDAF100EE54D7 /* vorbis_custom_decoder.h in Headers */,
@ -1489,6 +1551,8 @@
48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */, 48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */,
836F705718BDC2190095E648 /* util.h in Headers */, 836F705718BDC2190095E648 /* util.h in Headers */,
836F6F9A18BDC2190095E648 /* meta.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 */, 836F6F4D18BDC2190095E648 /* layout.h in Headers */,
83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */, 83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */,
836F6F2318BDC2190095E648 /* coding.h in Headers */, 836F6F2318BDC2190095E648 /* coding.h in Headers */,
@ -1641,6 +1705,7 @@
files = ( files = (
839E21E21F2EDAF100EE54D7 /* vorbis_custom_utils_wwise.c in Sources */, 839E21E21F2EDAF100EE54D7 /* vorbis_custom_utils_wwise.c in Sources */,
83E56BA51F2EE3520026BC60 /* vorbis_custom_utils_ogl.c in Sources */, 83E56BA51F2EE3520026BC60 /* vorbis_custom_utils_ogl.c in Sources */,
8349A9071FE6258200E26435 /* dec.c in Sources */,
839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */, 839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */,
839E21E41F2EDAF100EE54D7 /* vorbis_custom_utils_fsb.c in Sources */, 839E21E41F2EDAF100EE54D7 /* vorbis_custom_utils_fsb.c in Sources */,
839E21E11F2EDAF100EE54D7 /* vorbis_custom_decoder.c in Sources */, 839E21E11F2EDAF100EE54D7 /* vorbis_custom_decoder.c in Sources */,
@ -1652,8 +1717,10 @@
8301659C1F256BD000CA0941 /* nds_strm_ffta2.c in Sources */, 8301659C1F256BD000CA0941 /* nds_strm_ffta2.c in Sources */,
83CAB8E31F0B0755001BC993 /* pc_xa30.c in Sources */, 83CAB8E31F0B0755001BC993 /* pc_xa30.c in Sources */,
83CAB8E21F0B0752001BC993 /* wii_04sw.c in Sources */, 83CAB8E21F0B0752001BC993 /* wii_04sw.c in Sources */,
8349A8DF1FE6251F00E26435 /* vorbis_custom_utils_vid1.c in Sources */,
839B54571EEE1DA000048A2D /* rws_blocked.c in Sources */, 839B54571EEE1DA000048A2D /* rws_blocked.c in Sources */,
839B54521EEE1D9600048A2D /* ngc_ulw.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 */, 836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */,
836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */, 836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */,
836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */, 836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */,
@ -1664,7 +1731,6 @@
836F6F7418BDC2190095E648 /* bgw.c in Sources */, 836F6F7418BDC2190095E648 /* bgw.c in Sources */,
836F6F7218BDC2190095E648 /* baf.c in Sources */, 836F6F7218BDC2190095E648 /* baf.c in Sources */,
83F5F8831908D0A400C8E65F /* fsb5.c in Sources */, 83F5F8831908D0A400C8E65F /* fsb5.c in Sources */,
836F6F4B18BDC2190095E648 /* interleave_byte.c in Sources */,
836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */, 836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */,
836F700C18BDC2190095E648 /* ps2_wb.c in Sources */, 836F700C18BDC2190095E648 /* ps2_wb.c in Sources */,
836F6F7D18BDC2190095E648 /* dc_str.c in Sources */, 836F6F7D18BDC2190095E648 /* dc_str.c in Sources */,
@ -1678,6 +1744,7 @@
836F6F9B18BDC2190095E648 /* mn_str.c in Sources */, 836F6F9B18BDC2190095E648 /* mn_str.c in Sources */,
836F6F5918BDC2190095E648 /* tra_blocked.c in Sources */, 836F6F5918BDC2190095E648 /* tra_blocked.c in Sources */,
836F6F9F18BDC2190095E648 /* musc.c in Sources */, 836F6F9F18BDC2190095E648 /* musc.c in Sources */,
8349A9121FE6258200E26435 /* vsf_tta.c in Sources */,
836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */, 836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */,
836F6FA118BDC2190095E648 /* myspd.c in Sources */, 836F6FA118BDC2190095E648 /* myspd.c in Sources */,
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */, 836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */,
@ -1691,6 +1758,7 @@
83299FD01E7660C7003A3242 /* bik.c in Sources */, 83299FD01E7660C7003A3242 /* bik.c in Sources */,
836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */, 836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */,
836F6FBB18BDC2190095E648 /* ngca.c in Sources */, 836F6FBB18BDC2190095E648 /* ngca.c in Sources */,
8349A91E1FE6258200E26435 /* bar.c in Sources */,
836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */, 836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */,
832389521D224C0800482226 /* hca_decoder.c in Sources */, 832389521D224C0800482226 /* hca_decoder.c in Sources */,
836F6F9418BDC2190095E648 /* ivb.c in Sources */, 836F6F9418BDC2190095E648 /* ivb.c in Sources */,
@ -1700,21 +1768,27 @@
836F6F2218BDC2190095E648 /* at3_decoder.c in Sources */, 836F6F2218BDC2190095E648 /* at3_decoder.c in Sources */,
83EDE5D91A70951A005F5D84 /* btsnd.c in Sources */, 83EDE5D91A70951A005F5D84 /* btsnd.c in Sources */,
836F6FFC18BDC2190095E648 /* ps2_ster.c in Sources */, 836F6FFC18BDC2190095E648 /* ps2_ster.c in Sources */,
8349A9171FE6258200E26435 /* pc_adp_otns.c in Sources */,
836F701E18BDC2190095E648 /* redspark.c in Sources */, 836F701E18BDC2190095E648 /* redspark.c in Sources */,
836F6FA018BDC2190095E648 /* musx.c in Sources */, 836F6FA018BDC2190095E648 /* musx.c in Sources */,
836F705818BDC2190095E648 /* vgmstream.c in Sources */, 836F705818BDC2190095E648 /* vgmstream.c in Sources */,
8349A90A1FE6258200E26435 /* sab.c in Sources */,
836F6F6818BDC2190095E648 /* ads.c in Sources */, 836F6F6818BDC2190095E648 /* ads.c in Sources */,
83AB8C761E8072A100086084 /* x360_ast.c in Sources */, 83AB8C761E8072A100086084 /* x360_ast.c in Sources */,
836F6F8B18BDC2190095E648 /* genh.c in Sources */, 836F6F8B18BDC2190095E648 /* genh.c in Sources */,
8349A8EA1FE6253900E26435 /* blocked_ea_schl.c in Sources */,
836F705118BDC2190095E648 /* zsd.c in Sources */, 836F705118BDC2190095E648 /* zsd.c in Sources */,
8349A91F1FE6258200E26435 /* naac.c in Sources */,
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */, 836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */,
836F703C18BDC2190095E648 /* wii_bns.c in Sources */, 836F703C18BDC2190095E648 /* wii_bns.c in Sources */,
835027131ED119E000C25929 /* mta2_decoder.c in Sources */, 835027131ED119E000C25929 /* mta2_decoder.c in Sources */,
836F6FA718BDC2190095E648 /* nds_strm.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 */, 83A3F0741E3AD8B900D6A794 /* formats.c in Sources */,
836F6F6E18BDC2190095E648 /* aix.c in Sources */, 836F6F6E18BDC2190095E648 /* aix.c in Sources */,
836F703118BDC2190095E648 /* ss_stream.c in Sources */,
836F6F8718BDC2190095E648 /* ffw.c in Sources */, 836F6F8718BDC2190095E648 /* ffw.c in Sources */,
8349A9141FE6258200E26435 /* omu.c in Sources */,
836F6FE418BDC2190095E648 /* ps2_leg.c in Sources */, 836F6FE418BDC2190095E648 /* ps2_leg.c in Sources */,
836F705618BDC2190095E648 /* util.c in Sources */, 836F705618BDC2190095E648 /* util.c in Sources */,
836F703618BDC2190095E648 /* thp.c in Sources */, 836F703618BDC2190095E648 /* thp.c in Sources */,
@ -1745,16 +1819,17 @@
836F6F6518BDC2190095E648 /* 2dx9.c in Sources */, 836F6F6518BDC2190095E648 /* 2dx9.c in Sources */,
836F700818BDC2190095E648 /* ps2_vms.c in Sources */, 836F700818BDC2190095E648 /* ps2_vms.c in Sources */,
836F702418BDC2190095E648 /* rwsd.c in Sources */, 836F702418BDC2190095E648 /* rwsd.c in Sources */,
836F6F7E18BDC2190095E648 /* de2.c in Sources */,
836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */, 836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */,
836F6F6618BDC2190095E648 /* aax.c in Sources */, 836F6F6618BDC2190095E648 /* aax.c in Sources */,
836F6F4C18BDC2190095E648 /* ivaud_layout.c in Sources */,
836F6FD618BDC2190095E648 /* ps2_exst.c in Sources */, 836F6FD618BDC2190095E648 /* ps2_exst.c in Sources */,
836F6F6718BDC2190095E648 /* acm.c in Sources */, 836F6F6718BDC2190095E648 /* acm.c in Sources */,
836F6F8A18BDC2190095E648 /* gcsw.c in Sources */, 836F6F8A18BDC2190095E648 /* gcsw.c in Sources */,
836F6F9C18BDC2190095E648 /* mp4.c in Sources */, 836F6F9C18BDC2190095E648 /* mp4.c in Sources */,
8349A9101FE6258200E26435 /* ea_eaac.c in Sources */,
836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */, 836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */,
8349A8ED1FE6253900E26435 /* blocked_ea_sns.c in Sources */,
836F6F6F18BDC2190095E648 /* akb.c in Sources */, 836F6F6F18BDC2190095E648 /* akb.c in Sources */,
8349A9181FE6258200E26435 /* ea_1snh.c in Sources */,
836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */, 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */,
83709E071ECBC1A4005C03D3 /* mss.c in Sources */, 83709E071ECBC1A4005C03D3 /* mss.c in Sources */,
836F6F8F18BDC2190095E648 /* his.c in Sources */, 836F6F8F18BDC2190095E648 /* his.c in Sources */,
@ -1762,7 +1837,6 @@
836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */, 836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */,
836F6FCB18BDC2190095E648 /* ps2_ads.c in Sources */, 836F6FCB18BDC2190095E648 /* ps2_ads.c in Sources */,
836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */, 836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */,
83AA5D261F6E2F9C0020821C /* ea_snu.c in Sources */,
83AA5D171F6E2F600020821C /* mpeg_custom_utils_ealayer3.c in Sources */, 83AA5D171F6E2F600020821C /* mpeg_custom_utils_ealayer3.c in Sources */,
83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */, 83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */,
836F704C18BDC2190095E648 /* xbox_xvas.c in Sources */, 836F704C18BDC2190095E648 /* xbox_xvas.c in Sources */,
@ -1775,16 +1849,15 @@
836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */, 836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */,
836F6F7918BDC2190095E648 /* dc_asd.c in Sources */, 836F6F7918BDC2190095E648 /* dc_asd.c in Sources */,
836F6FC118BDC2190095E648 /* pc_adp.c in Sources */, 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */,
836F6F8318BDC2190095E648 /* ea_old.c in Sources */,
836F701A18BDC2190095E648 /* psx_fag.c in Sources */, 836F701A18BDC2190095E648 /* psx_fag.c in Sources */,
836F703B18BDC2190095E648 /* vsf.c in Sources */, 836F703B18BDC2190095E648 /* vsf.c in Sources */,
836F6F3D18BDC2190095E648 /* aax_layout.c in Sources */, 836F6F3D18BDC2190095E648 /* aax_layout.c in Sources */,
83AA5D1F1F6E2F800020821C /* ea_sns_blocked.c in Sources */,
836F6F8218BDC2190095E648 /* ea_schl.c in Sources */, 836F6F8218BDC2190095E648 /* ea_schl.c in Sources */,
836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */, 836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */,
836F6F7318BDC2190095E648 /* bcstm.c in Sources */, 836F6F7318BDC2190095E648 /* bcstm.c in Sources */,
83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */, 83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */,
836F704018BDC2190095E648 /* wii_sng.c in Sources */, 836F704018BDC2190095E648 /* wii_sng.c in Sources */,
8349A9131FE6258200E26435 /* ngc_vid1.c in Sources */,
8350C0551E071881009E0A93 /* xma.c in Sources */, 8350C0551E071881009E0A93 /* xma.c in Sources */,
836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */, 836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */,
836F704218BDC2190095E648 /* wii_sts.c in Sources */, 836F704218BDC2190095E648 /* wii_sts.c in Sources */,
@ -1799,7 +1872,6 @@
836F702B18BDC2190095E648 /* sdt.c in Sources */, 836F702B18BDC2190095E648 /* sdt.c in Sources */,
836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */, 836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */,
836F702C18BDC2190095E648 /* seg.c in Sources */, 836F702C18BDC2190095E648 /* seg.c in Sources */,
836F6F6A18BDC2190095E648 /* afc_header.c in Sources */,
836F700918BDC2190095E648 /* ps2_voi.c in Sources */, 836F700918BDC2190095E648 /* ps2_voi.c in Sources */,
836F6F3E18BDC2190095E648 /* aix_layout.c in Sources */, 836F6F3E18BDC2190095E648 /* aix_layout.c in Sources */,
836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */, 836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */,
@ -1814,6 +1886,7 @@
836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */, 836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */,
836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */, 836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */,
836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */, 836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */,
8349A8EC1FE6253900E26435 /* blocked_vawx.c in Sources */,
836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */, 836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */,
836F700418BDC2190095E648 /* ps2_vas.c in Sources */, 836F700418BDC2190095E648 /* ps2_vas.c in Sources */,
836F6F9818BDC2190095E648 /* mattel_hyperscan.c in Sources */, 836F6F9818BDC2190095E648 /* mattel_hyperscan.c in Sources */,
@ -1822,7 +1895,7 @@
83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */, 83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */,
836F6F6D18BDC2190095E648 /* aifc.c in Sources */, 836F6F6D18BDC2190095E648 /* aifc.c in Sources */,
836F702218BDC2190095E648 /* rsd.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 */, 83345A501F8AEB2800B2EAA4 /* pc_al2.c in Sources */,
836F702518BDC2190095E648 /* rwx.c in Sources */, 836F702518BDC2190095E648 /* rwx.c in Sources */,
836F6F3A18BDC2190095E648 /* sdx2_decoder.c in Sources */, 836F6F3A18BDC2190095E648 /* sdx2_decoder.c in Sources */,
@ -1851,6 +1924,7 @@
836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */, 836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */,
836F6F5118BDC2190095E648 /* nolayout.c in Sources */, 836F6F5118BDC2190095E648 /* nolayout.c in Sources */,
83AA5D241F6E2F9C0020821C /* awc.c in Sources */, 83AA5D241F6E2F9C0020821C /* awc.c in Sources */,
8349A8E91FE6253900E26435 /* blocked_ea_1snh.c in Sources */,
836F702918BDC2190095E648 /* sat_sap.c in Sources */, 836F702918BDC2190095E648 /* sat_sap.c in Sources */,
836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */, 836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */,
831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */, 831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */,
@ -1869,11 +1943,13 @@
83709E061ECBC1A4005C03D3 /* mc3.c in Sources */, 83709E061ECBC1A4005C03D3 /* mc3.c in Sources */,
831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */, 831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */,
836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */, 836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */,
8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */,
836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */, 836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */,
836F6F4A18BDC2190095E648 /* interleave.c in Sources */, 836F6F4A18BDC2190095E648 /* interleave.c in Sources */,
83EDE5D81A70951A005F5D84 /* mca.c in Sources */, 83EDE5D81A70951A005F5D84 /* mca.c in Sources */,
831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */, 831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */,
838BDB6C1D3AFAB10022CA6F /* ffmpeg_decoder.c in Sources */, 838BDB6C1D3AFAB10022CA6F /* ffmpeg_decoder.c in Sources */,
8349A8E11FE6251F00E26435 /* ea_mt_decoder.c in Sources */,
836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */, 836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */,
836F702F18BDC2190095E648 /* spt_spd.c in Sources */, 836F702F18BDC2190095E648 /* spt_spd.c in Sources */,
836F704618BDC2190095E648 /* x360_tra.c in Sources */, 836F704618BDC2190095E648 /* x360_tra.c in Sources */,
@ -1882,7 +1958,9 @@
834D3A6E19F47C98001C54F6 /* g1l.c in Sources */, 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */,
836F6FC318BDC2190095E648 /* pc_smp.c in Sources */, 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */,
836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */, 836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */,
8349A9091FE6258200E26435 /* pc_ast.c in Sources */,
836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */, 836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */,
8349A91C1FE6258200E26435 /* mogg.c in Sources */,
836F703D18BDC2190095E648 /* wii_mus.c in Sources */, 836F703D18BDC2190095E648 /* wii_mus.c in Sources */,
836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */, 836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */,
831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */, 831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */,
@ -1901,14 +1979,16 @@
836F6F7718BDC2190095E648 /* capdsp.c in Sources */, 836F6F7718BDC2190095E648 /* capdsp.c in Sources */,
836F6FB018BDC2190095E648 /* ngc_dsp_ygo.c in Sources */, 836F6FB018BDC2190095E648 /* ngc_dsp_ygo.c in Sources */,
836F703318BDC2190095E648 /* str_snds.c in Sources */, 836F703318BDC2190095E648 /* str_snds.c in Sources */,
8349A9191FE6258200E26435 /* afc.c in Sources */,
836F703718BDC2190095E648 /* tun.c in Sources */, 836F703718BDC2190095E648 /* tun.c in Sources */,
836F700B18BDC2190095E648 /* ps2_wad.c in Sources */, 836F700B18BDC2190095E648 /* ps2_wad.c in Sources */,
8349A9161FE6258200E26435 /* flx.c in Sources */,
831BA61E1EAC61A500CF89B0 /* vawx.c in Sources */, 831BA61E1EAC61A500CF89B0 /* vawx.c in Sources */,
836F702A18BDC2190095E648 /* sd9.c in Sources */, 836F702A18BDC2190095E648 /* sd9.c in Sources */,
836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */, 836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */,
836F6F4418BDC2190095E648 /* ea_block.c in Sources */,
836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */, 836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */,
836F6FF618BDC2190095E648 /* ps2_sfs.c in Sources */, 836F6FF618BDC2190095E648 /* ps2_sfs.c in Sources */,
8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */,
836F6F9518BDC2190095E648 /* kraw.c in Sources */, 836F6F9518BDC2190095E648 /* kraw.c in Sources */,
836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */, 836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */,
83709E051ECBC1A4005C03D3 /* gtd.c in Sources */, 83709E051ECBC1A4005C03D3 /* gtd.c in Sources */,
@ -1926,8 +2006,8 @@
836F700318BDC2190095E648 /* ps2_vag.c in Sources */, 836F700318BDC2190095E648 /* ps2_vag.c in Sources */,
836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */, 836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */,
831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */, 831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */,
836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */,
836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */, 836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */,
8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */,
831BA6181EAC61A500CF89B0 /* adx.c in Sources */, 831BA6181EAC61A500CF89B0 /* adx.c in Sources */,
836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */, 836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */,
836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */, 836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */,
@ -1937,6 +2017,7 @@
836F6F4918BDC2190095E648 /* ims_block.c in Sources */, 836F6F4918BDC2190095E648 /* ims_block.c in Sources */,
836F6F7518BDC2190095E648 /* bnsf.c in Sources */, 836F6F7518BDC2190095E648 /* bnsf.c in Sources */,
836F704318BDC2190095E648 /* wpd.c in Sources */, 836F704318BDC2190095E648 /* wpd.c in Sources */,
8349A9081FE6258200E26435 /* ezw.c in Sources */,
836F6FE118BDC2190095E648 /* ps2_jstm.c in Sources */, 836F6FE118BDC2190095E648 /* ps2_jstm.c in Sources */,
836F6FD918BDC2190095E648 /* ps2_gcm.c in Sources */, 836F6FD918BDC2190095E648 /* ps2_gcm.c in Sources */,
836F6F8E18BDC2190095E648 /* halpst.c in Sources */, 836F6F8E18BDC2190095E648 /* halpst.c in Sources */,
@ -1959,7 +2040,6 @@
836F700718BDC2190095E648 /* ps2_vgv.c in Sources */, 836F700718BDC2190095E648 /* ps2_vgv.c in Sources */,
836F704F18BDC2190095E648 /* xwb.c in Sources */, 836F704F18BDC2190095E648 /* xwb.c in Sources */,
8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */, 8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */,
836F6FC518BDC2190095E648 /* pc_sob.c in Sources */,
836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */, 836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */,
836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */, 836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */,
836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */, 836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */,
@ -1983,6 +2063,7 @@
836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */, 836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */,
836F6F9218BDC2190095E648 /* ish_isd.c in Sources */, 836F6F9218BDC2190095E648 /* ish_isd.c in Sources */,
836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */, 836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */,
8349A9151FE6258200E26435 /* ps2_xa2_rrp.c in Sources */,
836F703518BDC2190095E648 /* svs.c in Sources */, 836F703518BDC2190095E648 /* svs.c in Sources */,
836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */, 836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */,
836F6F9D18BDC2190095E648 /* msvp.c in Sources */, 836F6F9D18BDC2190095E648 /* msvp.c in Sources */,
@ -1990,7 +2071,6 @@
836F705018BDC2190095E648 /* ydsp.c in Sources */, 836F705018BDC2190095E648 /* ydsp.c in Sources */,
836F702718BDC2190095E648 /* sat_baka.c in Sources */, 836F702718BDC2190095E648 /* sat_baka.c in Sources */,
83345A4A1F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c in Sources */, 83345A4A1F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c in Sources */,
836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */,
836F704B18BDC2190095E648 /* xbox_xmu.c in Sources */, 836F704B18BDC2190095E648 /* xbox_xmu.c in Sources */,
832389501D2246C300482226 /* hca.c in Sources */, 832389501D2246C300482226 /* hca.c in Sources */,
836F701B18BDC2190095E648 /* psx_gms.c in Sources */, 836F701B18BDC2190095E648 /* psx_gms.c in Sources */,

View File

@ -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_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_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(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_xbox_ima_int(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_snds_ima(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(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_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); 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_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_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_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 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 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 */ /* 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(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); size_t dsp_bytes_to_samples(size_t bytes, int channels);
int32_t dsp_nibbles_to_samples(int32_t nibbles); int32_t dsp_nibbles_to_samples(int32_t nibbles);
void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing); 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 */ /* xa_decoder */
void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); 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 */ /* ea_xa_decoder */
void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); 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 */ /* mc3_decoder */
void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); 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 */ /* hca_decoder */
void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
void reset_hca(VGMSTREAM *vgmstream); void reset_hca(VGMSTREAM *vgmstream);
@ -167,11 +177,11 @@ void free_mpeg(mpeg_codec_data *data);
void flush_mpeg(mpeg_codec_data * data); void flush_mpeg(mpeg_codec_data * data);
long mpeg_bytes_to_samples(long bytes, const 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 #endif
#ifdef VGM_USE_G7221 #ifdef VGM_USE_G7221
/* g7221_decoder */ /* 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 decode_g7221(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_g7221(VGMSTREAM *vgmstream); void reset_g7221(VGMSTREAM *vgmstream);
void free_g7221(VGMSTREAM *vgmstream); void free_g7221(VGMSTREAM *vgmstream);
@ -179,6 +189,7 @@ void free_g7221(VGMSTREAM *vgmstream);
#ifdef VGM_USE_G719 #ifdef VGM_USE_G719
/* g719_decoder */ /* 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 decode_g719(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
void reset_g719(VGMSTREAM *vgmstream); void reset_g719(VGMSTREAM *vgmstream);
void free_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 atrac3_bytes_to_samples(size_t bytes, int full_block_align);
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align); size_t 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*/ #endif /*_CODING_H*/

View File

@ -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) */ * so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */
return (bytes / full_block_align) * 2048; 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);
}

View File

@ -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);
}

View File

@ -29,59 +29,57 @@ static const int EA_XA_TABLE[20] = {
0, -1, -3, -4 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) { 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; uint8_t frame_info;
int32_t sample_count;
int32_t coef1, coef2; int32_t coef1, coef2;
int i, shift; int i, sample_count, shift;
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
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 */ /* header */
frame_info = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile); frame_info = read_8bit(stream->offset,stream->streamfile);
channel_offset++;
if (frame_info == 0xEE) { /* PCM frame (used in later revisions), samples always BE */ 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_history1_32 = read_16bitBE(stream->offset + 0x01 + 0x00,stream->streamfile);
stream->adpcm_history2_32 = read_16bitBE(stream->offset+channel_offset+0x02,stream->streamfile); stream->adpcm_history2_32 = read_16bitBE(stream->offset + 0x01 + 0x02,stream->streamfile);
channel_offset += 4;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
outbuf[sample_count] = read_16bitBE(stream->offset+channel_offset,stream->streamfile); outbuf[sample_count] = read_16bitBE(stream->offset + 0x01 + 2*0x02 + i*0x02,stream->streamfile);
channel_offset+=2;
} }
/* Only increment offset on complete frame */ /* only increment offset on complete frame */
if (channel_offset-stream->channel_start_offset == (2*28)+5) if (i == frame_samples)
stream->channel_start_offset += (2*28)+5; stream->offset += pcm_frame_size;
}
} else { /* ADPCM frame */ else { /* ADPCM frame */
coef1 = EA_XA_TABLE[(frame_info >> 4) + 0]; coef1 = EA_XA_TABLE[(frame_info >> 4) + 0];
coef2 = EA_XA_TABLE[(frame_info >> 4) + 4]; coef2 = EA_XA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F) + 8; shift = (frame_info & 0x0F) + 8;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte, sample_nibble; uint8_t sample_byte, sample_nibble;
int32_t sample; int32_t new_sample;
off_t byte_offset = (stream->offset + channel_offset + i/2); 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_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
sample_nibble = (!(i%2) ? sample_byte >> 4 : sample_byte & 0x0F); /* i=even > high nibble */ sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32) >> 8; new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32) >> 8;
sample = clamp16(sample); new_sample = clamp16(new_sample);
outbuf[sample_count] = sample; outbuf[sample_count] = new_sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32; 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 */ /* only increment offset on complete frame */
if (channel_offset - stream->channel_start_offset == 0x0F) if (i == frame_samples)
stream->channel_start_offset += 0x0F; stream->offset += xa_frame_size;
} }
} }
@ -90,43 +88,42 @@ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing
uint8_t frame_info; uint8_t frame_info;
int32_t coef1, coef2; int32_t coef1, coef2;
int i, sample_count, shift; 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 */ 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) */ /* header (coefs ch0+ch1 + shift ch0+ch1) */
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); frame_info = read_8bit(stream->offset+0x00,stream->streamfile);
channel_offset++;
coef1 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 0]; coef1 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 0];
coef2 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 4]; coef2 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 4];
shift = (frame_info & 0x0F) + 8; shift = (frame_info & 0x0F) + 8;
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); frame_info = read_8bit(stream->offset+0x01,stream->streamfile);
channel_offset++;
shift = (hn ? frame_info >> 4 : frame_info & 0x0F) + 8; shift = (hn ? frame_info >> 4 : frame_info & 0x0F) + 8;
/* samples */ /* samples */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte, sample_nibble; uint8_t sample_byte, sample_nibble;
int32_t sample; int32_t new_sample;
off_t byte_offset = (stream->offset + channel_offset + i); 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_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
sample_nibble = (hn ? sample_byte >> 4 : sample_byte & 0x0F); sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ new_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; new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
sample = clamp16(sample); new_sample = clamp16(new_sample);
outbuf[sample_count] = sample; outbuf[sample_count] = new_sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32; 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 */ /* only increment offset on complete frame */
if(channel_offset - stream->channel_start_offset == 0x1E) if (i == frame_samples)
stream->channel_start_offset += 0x1E; stream->offset += frame_size;
} }
/* EA-XA v1 mono/interleave */ /* EA-XA v1 mono/interleave */
@ -134,13 +131,13 @@ void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa
uint8_t frame_info; uint8_t frame_info;
int32_t coef1, coef2; int32_t coef1, coef2;
int i, sample_count, shift; 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) */ /* header (coefs+shift ch0) */
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); frame_info = read_8bit(stream->offset,stream->streamfile);
channel_offset++;
coef1 = EA_XA_TABLE[(frame_info >> 4) + 0]; coef1 = EA_XA_TABLE[(frame_info >> 4) + 0];
coef2 = EA_XA_TABLE[(frame_info >> 4) + 4]; coef2 = EA_XA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F) + 8; shift = (frame_info & 0x0F) + 8;
@ -148,39 +145,38 @@ void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa
/* samples */ /* samples */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte, sample_nibble; uint8_t sample_byte, sample_nibble;
int32_t sample; int32_t new_sample;
off_t byte_offset = (stream->offset + channel_offset + i/2); 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_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
sample_nibble = (!(i%2) ? sample_byte >> 4 : sample_byte & 0x0F); /* i=even > high nibble */ sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ new_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; new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
sample = clamp16(sample); new_sample = clamp16(new_sample);
outbuf[sample_count] = sample; outbuf[sample_count] = new_sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32; 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 */ /* only increment offset on complete frame */
if(channel_offset - stream->channel_start_offset == 0x0F) if (i == frame_samples)
stream->channel_start_offset += 0x0F; 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) { 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; uint8_t frame_info;
int32_t coef1, coef2; int32_t coef1, coef2;
int i, sample_count, shift; 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) */ /* header (coefs+shift ch0 + coefs+shift ch1) */
frame_info = read_8bit(channel_offset,stream->streamfile); frame_info = read_8bit(stream->offset + channel,stream->streamfile);
channel_offset += channelspacing;
coef1 = EA_XA_TABLE[(frame_info >> 4) + 0]; coef1 = EA_XA_TABLE[(frame_info >> 4) + 0];
coef2 = EA_XA_TABLE[(frame_info >> 4) + 4]; coef2 = EA_XA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F) + 8; shift = (frame_info & 0x0F) + 8;
@ -188,27 +184,22 @@ void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac
/* samples */ /* samples */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte, sample_nibble; uint8_t sample_byte, sample_nibble;
int32_t sample; int32_t new_sample;
off_t byte_offset = (stream->offset + channel_offset); 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_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
sample_nibble = (i&1) ? sample_byte & 0x0F : sample_byte >> 4; sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */ new_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; new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
sample = clamp16(sample); new_sample = clamp16(new_sample);
outbuf[sample_count] = sample; outbuf[sample_count] = new_sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32; stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample; stream->adpcm_history1_32 = new_sample;
if(i&1)
stream->offset+=channelspacing;
} }
channel_offset+=i;
/* Only increment offset on complete frame */ /* only increment offset on complete frame */
if (channel_offset - stream->channel_start_offset == frame_size) { if (i == frame_samples)
stream->channel_start_offset += frame_size; stream->offset += frame_size;
stream->offset=0;
}
} }

View File

@ -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 * 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. * 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. * 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) { static int init_seek(ffmpeg_codec_data * data) {
int ret, ts_index, found_first = 0; 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) { switch(data->config.type) {
case FFMPEG_EA_XMA: ret = ffmpeg_custom_read_eaxma(data, buf, buf_size); break; 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_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_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; //case FFMPEG_SFH: ret = ffmpeg_custom_read_sfh(data, buf, buf_size); break;
default: ret = ffmpeg_custom_read_standard(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 */ //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_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; 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) { switch(data->config.type) {
case FFMPEG_EA_XMA: offset = ffmpeg_custom_seek_eaxma(data, offset); break; 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_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_EA_SCHL: offset = ffmpeg_custom_seek_ea_schl(data, offset); break;
//case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break; //case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break;
default: offset = ffmpeg_custom_seek_standard(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) { switch(data->config.type) {
case FFMPEG_EA_XMA: bytes = ffmpeg_custom_size_eaxma(data); break; 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_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_EA_SCHL: bytes = ffmpeg_custom_size_ea_schl(data); break;
//case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break; //case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break;
default: bytes = ffmpeg_custom_size_standard(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); close_streamfile(data->streamfile);
data->streamfile = NULL; data->streamfile = NULL;
} }
if (data->config.key) {
free(data->config.key);
}
free(data); free(data);
} }

View File

@ -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) { 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; return virtual_offset;
} }

View File

@ -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_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset);
int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data); 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); //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_seek_ea_schl(ffmpeg_codec_data *data, int64_t virtual_offset);
//int64_t ffmpeg_custom_size_ea_schl(ffmpeg_codec_data *data); //int64_t ffmpeg_custom_size_ea_schl(ffmpeg_codec_data *data);

View File

@ -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

View File

@ -3,7 +3,7 @@
#ifdef VGM_USE_FFMPEG #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_MAX_STREAMS_PER_SNS_BLOCK 4 /* XMA2 max is 8ch = 4 * 2ch */
#define EAXMA_XMA_PACKET_SIZE 0x800 #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) #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 == 0) goto fail;
if (max_packets * num_streams * EAXMA_XMA_PACKET_SIZE > EAXMA_XMA_BUFFER_SIZE) { 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; goto fail;
} }
@ -134,12 +135,13 @@ fail:
int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset) { int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset) {
int64_t real_offset, virtual_base; 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 /* 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 */ * 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; real_offset = data->real_offset;
virtual_base = data->virtual_base; 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 */ /* find target block */
while (virtual_base < virtual_offset) { while (virtual_base < seek_virtual_offset) {
size_t data_size, extra_size = 0; size_t data_size, extra_size = 0;
size_t block_size = read_32bitBE(real_offset, data->streamfile); 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); extra_size = EAXMA_XMA_PACKET_SIZE - (data_size % EAXMA_XMA_PACKET_SIZE);
/* stop if virtual_offset lands inside current block */ /* stop if virtual_offset lands inside current block */
if (data_size + extra_size > virtual_offset) if (data_size + extra_size > seek_virtual_offset)
break; break;
real_offset += (block_size & 0x00FFFFFF); real_offset += (block_size & 0x00FFFFFF);

View File

@ -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 ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset) {
int64_t real_offset, virtual_base; int64_t real_offset, virtual_base;
int64_t current_virtual_offset = data->virtual_offset; 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) */ /* 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; real_offset = data->real_offset;
virtual_base = data->virtual_base; 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 */ /* find target block */
while (virtual_base < virtual_offset) { while (virtual_base < seek_virtual_offset) {
size_t extra_size; size_t extra_size;
size_t data_size = read_32bitBE(real_offset, data->streamfile); size_t data_size = read_32bitBE(real_offset, data->streamfile);
extra_size = 0x1b + (int)(data_size / 0xFF + 1); /* OggS page: base size + lacing values */ extra_size = 0x1b + (int)(data_size / 0xFF + 1); /* OggS page: base size + lacing values */
/* stop if virtual_offset lands inside current block */ /* stop if virtual_offset lands inside current block */
if (data_size + extra_size > virtual_offset) if (data_size + extra_size > seek_virtual_offset)
break; break;
real_offset += 0x04 + 0x04 + data_size; real_offset += 0x04 + 0x04 + data_size;
@ -332,8 +333,8 @@ fail:
static size_t make_opus_comment(uint8_t * buf, int buf_size) { static size_t make_opus_comment(uint8_t * buf, int buf_size) {
size_t comment_size; size_t comment_size;
int vendor_string_length, user_comment_0_length; int vendor_string_length, user_comment_0_length;
char * vendor_string = "vgmstream"; const char * vendor_string = "vgmstream";
char * user_comment_0_string = "vgmstream Opus converter"; const char * user_comment_0_string = "vgmstream Opus converter";
vendor_string_length = strlen(vendor_string); vendor_string_length = strlen(vendor_string);
user_comment_0_length = strlen(user_comment_0_string); user_comment_0_length = strlen(user_comment_0_string);

View File

@ -4,6 +4,31 @@
#ifdef VGM_USE_G719 #ifdef VGM_USE_G719
#include "../stack_alloc.h" #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) { void decode_g719(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel]; VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
g719_codec_data *data = vgmstream->codec_data; g719_codec_data *data = vgmstream->codec_data;

View File

@ -121,7 +121,7 @@ g72x_init_state(
* computes the estimated signal from 6-zero predictor. * computes the estimated signal from 6-zero predictor.
* *
*/ */
int static int
predictor_zero( predictor_zero(
struct g72x_state *state_ptr) struct g72x_state *state_ptr)
{ {
@ -139,7 +139,7 @@ predictor_zero(
* computes the estimated signal from 2-pole predictor. * computes the estimated signal from 2-pole predictor.
* *
*/ */
int static int
predictor_pole( predictor_pole(
struct g72x_state *state_ptr) struct g72x_state *state_ptr)
{ {
@ -152,7 +152,7 @@ predictor_pole(
* computes the quantization step size of the adaptive quantizer. * computes the quantization step size of the adaptive quantizer.
* *
*/ */
int static int
step_size( step_size(
struct g72x_state *state_ptr) struct g72x_state *state_ptr)
{ {
@ -181,7 +181,7 @@ step_size(
* codeword 'i' and quantization step size scale factor 'y'. * codeword 'i' and quantization step size scale factor 'y'.
* Multiplication is performed in log base 2 domain as addition. * Multiplication is performed in log base 2 domain as addition.
*/ */
int static int
reconstruct( reconstruct(
int sign, /* 0 for non-negative value */ int sign, /* 0 for non-negative value */
int dqln, /* G.72x codeword */ int dqln, /* G.72x codeword */
@ -210,7 +210,7 @@ reconstruct(
* *
* updates the state variables for each output code * updates the state variables for each output code
*/ */
void static void
update( update(
/*int code_size,*/ /* distinguish 723_40 with others */ /*int code_size,*/ /* distinguish 723_40 with others */
int y, /* quantizer step size */ 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. * returns the resulting linear PCM, A-law or u-law value.
* return -1 for unknown out_coding value. * return -1 for unknown out_coding value.
*/ */
int static int
g721_decoder( g721_decoder(
int i, int i,
struct g72x_state *state_ptr) struct g72x_state *state_ptr)

View File

@ -3,6 +3,32 @@
#ifdef VGM_USE_G7221 #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) { void decode_g7221(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel]; VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
g7221_codec_data *data = vgmstream->codec_data; g7221_codec_data *data = vgmstream->codec_data;

View File

@ -7,17 +7,18 @@
* *
* All IMAs are mostly the same with these variations: * All IMAs are mostly the same with these variations:
* - interleave: blocks and channels are handled externally (layouts) or internally (mixed channels) * - 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 * - expand type: ms-ima style or others; low or high nibble first
* *
* todo: * 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 * 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. * 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, 7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31, 16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66, 34, 37, 41, 45, 50, 55, 60, 66,
@ -32,48 +33,32 @@ static const int32_t ADPCMTable[89] =
32767 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,
-1, -1, -1, -1, 2, 4, 6, 8 -1, -1, -1, -1, 2, 4, 6, 8
}; };
/* Original IMA */ /* Standard IMA (most common) */
static void ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) { 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; int sample_nibble, sample_decoded, step, delta;
//"original" ima nibble expansion /* calculate diff = [signed] (step / 8) + (step / 4) + (step / 2) + (step) [when code = 4+2+1]
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; * simplified through math, using bitwise ops to avoid rounding:
sample_decoded = *hist1 << 3; * diff = (code + 1/2) * (step / 4)
step = ADPCMTable[*step_index]; * > diff = (step * nibble / 4) + (step / 8)
delta = step * (sample_nibble & 7) * 2 + step; * > diff = (((step * nibble) + (step / 2)) / 4) */
if (sample_nibble & 8)
sample_decoded -= delta;
else
sample_decoded += delta;
*hist1 = clamp16(sample_decoded >> 3); sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; /* ADPCM code */
*step_index += IMA_IndexTable[sample_nibble]; sample_decoded = *hist1; /* predictor value */
if (*step_index < 0) *step_index=0; step = ADPCMTable[*step_index]; /* current step */
if (*step_index > 88) *step_index=88;
}
/* 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; delta = step >> 3;
if (sample_nibble & 1) delta += step >> 2; if (sample_nibble & 1) delta += step >> 2;
if (sample_nibble & 2) delta += step >> 1; if (sample_nibble & 2) delta += step >> 1;
if (sample_nibble & 4) delta += step; if (sample_nibble & 4) delta += step;
if (sample_nibble & 8) if (sample_nibble & 8) delta = -delta;
sample_decoded -= delta; sample_decoded += delta;
else
sample_decoded += delta;
*hist1 = clamp16(sample_decoded); *hist1 = clamp16(sample_decoded);
*step_index += IMA_IndexTable[sample_nibble]; *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; 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) */ /* Apple's 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) { 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; int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1; sample_decoded = *hist1;
step = ADPCMTable[*step_index]; step = ADPCMTable[*step_index];
delta = step >> 3; delta = step >> 3;
if (sample_nibble & 1) delta += step >> 2; if (sample_nibble & 1) delta += step >> 2;
if (sample_nibble & 2) delta += step >> 1; if (sample_nibble & 2) delta += step >> 1;
if (sample_nibble & 4) delta += step; if (sample_nibble & 4) delta += step;
if (sample_nibble & 8) if (sample_nibble & 8) delta = -delta;
sample_decoded -= delta; sample_decoded += delta;
else
sample_decoded += delta;
*hist1 = clamp16(sample_decoded); //no need for this actually *hist1 = clamp16(sample_decoded); //no need for this actually
*step_index += IMA_IndexTable[sample_nibble]; *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; 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) { 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; int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1;
*step_index += IMA_IndexTable[sample_nibble]; *step_index += IMA_IndexTable[sample_nibble];
if (*step_index < 0) *step_index=0; if (*step_index < 0) *step_index=0;
if (*step_index > 88) *step_index=88; if (*step_index > 88) *step_index=88;
step = ADPCMTable[*step_index]; 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; if (sample_nibble & 8) delta = -delta;
sample_decoded = *hist1 + delta; sample_decoded += delta;
*hist1 = clamp16(sample_decoded); *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) { 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; int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1; sample_decoded = *hist1;
step = ADPCMTable[*step_index]; step = ADPCMTable[*step_index];
delta = 0; delta = 0;
if(sample_nibble & 4) delta = step << 2; if(sample_nibble & 4) delta = step << 2;
if(sample_nibble & 2) delta += step << 1; if(sample_nibble & 2) delta += step << 1;
if(sample_nibble & 1) delta += step; if(sample_nibble & 1) delta += step;
delta >>= 2; delta >>= 2;
if(sample_nibble & 8) if (sample_nibble & 8) delta = -delta;
sample_decoded -= delta; sample_decoded += delta;
else
sample_decoded += delta;
*hist1 = clamp16(sample_decoded); *hist1 = clamp16(sample_decoded);
*step_index += IMA_IndexTable[sample_nibble]; *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; 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) { sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
int i, sample_count; sample_decoded = *hist1;
step = ADPCMTable[*step_index];
int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? delta = (((sample_nibble & 7) * 2 + 1) * step) >> 3; /* custom */
int step_index = stream->adpcm_step_index; if (sample_nibble & 8) delta = -delta;
sample_decoded += delta;
//external interleave *hist1 = clamp16(sample_decoded);
*step_index += IMA_IndexTable[sample_nibble];
//normal header if (*step_index < 0) *step_index=0;
if (first_sample == 0) { if (*step_index > 88) *step_index=88;
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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
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);
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; /* DVI/IMA */
/* ************************************ */
int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? /* Standard DVI/IMA ADPCM (as in, ADPCM recommended by the IMA using Intel/DVI's implementation).
int step_index = stream->adpcm_step_index; * 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). */
//external interleave 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) {
//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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
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);
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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int nibble_shift;
offset = (channelspacing==1) ?
stream->offset + 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) {
int i, sample_count = 0; int i, sample_count = 0;
int32_t hist1 = stream->adpcm_history1_32; int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index; int step_index = stream->adpcm_step_index;
//internal interleave (0x24 size), mono /* external interleave */
int block_samples = (0x24 - 0x4) * 2; /* block size - header, 2 samples per byte */
first_sample = first_sample % block_samples;
//normal header /* no header (external setup), pre-clamp for wrong values */
if (first_sample == 0) { if (step_index < 0) step_index=0;
off_t header_offset = stream->offset; if (step_index > 88) step_index=88;
hist1 = read_16bitLE(header_offset,stream->streamfile); /* decode nibbles */
step_index = read_16bitLE(header_offset+2,stream->streamfile); for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) {
if (step_index < 0) step_index=0; off_t byte_offset = is_stereo ?
if (step_index > 88) step_index=88; 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 std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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);
outbuf[sample_count] = (short)(hist1); 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; 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_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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; 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) */
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) {
int i, sample_count; int i, sample_count;
int32_t hist1 = stream->adpcm_history1_32; 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; off_t byte_offset = stream->offset + i/2;
int nibble_shift = (i&1?4:0); //low nibble order 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); outbuf[sample_count] = (short)(hist1);
} }
@ -478,38 +225,6 @@ void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
stream->adpcm_step_index = step_index; 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = packet_offset + 2 + i/2;
int nibble_shift = (i&1?4:0); //low nibble first
ms_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_snds_ima(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) {
int i, sample_count; int i, sample_count;
@ -556,6 +271,300 @@ void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
stream->adpcm_step_index = step_index; 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int nibble_shift;
offset = (channelspacing==1) ?
stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = (stream->offset + 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) { 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; 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 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 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); 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) //last nibble/sample in block is ignored (next header sample contains it)
if (i < block_samples) { 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); outbuf[sample_count] = (short)(hist1);
sample_count+=channelspacing; sample_count+=channelspacing;
//todo atenuation: apparently from hcs's analysis Wwise IMA decodes nibbles slightly different, reducing dbs //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; 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 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); 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; off_t byte_offset = stream->offset + 4 + i/2;
int nibble_shift = (i&1?4:0); //low nibble first 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); 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) { 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) */ /* 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 */ /* 2 samples per byte (2 nibbles) in stereo or mono config */
return bytes / channels * 2; 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);
}

View File

@ -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_data_size = info.frame_size;
int current_padding = 0; 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) current_padding = (current_data_size % data->config.fsb_padding)
? data->config.fsb_padding - (current_data_size % data->config.fsb_padding) ? data->config.fsb_padding - (current_data_size % data->config.fsb_padding)
: 0; : 0;
@ -59,7 +60,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
case MPEG_STANDARD: case MPEG_STANDARD:
case MPEG_AHX: case MPEG_AHX:
case MPEG_EA: case MPEG_EA:
if (data->channels_per_frame != data->config.channels) if (info.channels != data->config.channels)
goto fail; /* no multichannel expected */ goto fail; /* no multichannel expected */
break; 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 //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) // (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 #if 0
/* set encoder delay (samples to skip at the beginning of a stream) if needed, which varies with encoder used */ /* set encoder delay (samples to skip at the beginning of a stream) if needed, which varies with encoder used */
switch(data->type) { switch(data->type) {
@ -87,7 +89,8 @@ fail:
/* writes data to the buffer and moves offsets */ /* 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; mpeg_frame_info info;
size_t current_data_size = 0; size_t current_data_size = 0;
size_t current_padding = 0; size_t current_padding = 0;
@ -108,9 +111,9 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
goto fail; goto fail;
current_data_size = info.frame_size; 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) */ /* 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. */ * 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) { if ((info.layer == 3 && data->config.fsb_padding) || data->config.fsb_padding == 16) {
current_padding = (current_data_size % data->config.fsb_padding) current_padding = (current_data_size % data->config.fsb_padding)
? data->config.fsb_padding - (current_data_size % data->config.fsb_padding) ? data->config.fsb_padding - (current_data_size % data->config.fsb_padding)
: 0; : 0;
@ -135,14 +138,14 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
current_data_size = info.frame_size; current_data_size = info.frame_size;
break; 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); VGM_LOG("MPEG: incorrect data_size 0x%x\n", current_data_size);
goto fail; goto fail;
} }
/* read single frame */ /* 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 */ /* 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 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 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; case 1152: info->frame_size = (144l * info->bit_rate * 1000l / info->sample_rate + padding); break;
default: goto fail;
} }
return 1; return 1;

View File

@ -3,11 +3,12 @@
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
#define MPEG_AHX_EXPECTED_FRAME_SIZE 0x414 #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 */ /* 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 */ /* 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 current_data_size = 0;
size_t file_size = get_streamfile_size(stream->streamfile); 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++; 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); VGM_LOG("MPEG AHX: incorrect data_size 0x%x\n", current_data_size);
goto fail; goto fail;
} }
/* 0-fill up to expected size to keep mpg123 happy */ /* 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); ms->bytes_in_buffer = read_streamfile(ms->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); memset(ms->buffer + ms->bytes_in_buffer,0, MPEG_AHX_EXPECTED_FRAME_SIZE - ms->bytes_in_buffer);
data->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE; ms->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE;
/* decrypt if needed */ /* decrypt if needed */
switch(data->config.encryption) { switch(data->config.encryption) {
case 0x00: break; case 0x00: break;
case 0x08: ahx_decrypt_type08(data); break; case 0x08: ahx_decrypt_type08(ms->buffer, &data->config); break;
default: default:
VGM_LOG("MPEG AHX: unknown encryption 0x%x\n", data->config.encryption); VGM_LOG("MPEG AHX: unknown encryption 0x%x\n", data->config.encryption);
break; /* garbled frame */ break; /* garbled frame */
@ -66,7 +67,7 @@ fail:
} }
/* Decrypts an AHX type 0x08 (keystring) encrypted frame. Algorithm by Thealexbarney */ /* 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; int i, index, encrypted_bits;
uint32_t value; uint32_t value;
uint16_t current_key; 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. /* 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 */ * 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; index = (value >> (32-3-2)) & 0x03;
switch(index) { switch(index) {
case 0: current_key = 0; break; case 0: current_key = 0; break;
case 1: current_key = data->config.cri_key1; break; case 1: current_key = config->cri_key1; break;
case 2: current_key = data->config.cri_key2; break; case 2: current_key = config->cri_key2; break;
case 3: current_key = data->config.cri_key3; break; case 3: current_key = config->cri_key3; break;
default: goto fail; default: goto fail;
} }
/* AHX for DC: 16b, normal: 6b (no idea, probably some Layer II field) */ /* 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): /* decrypt next bitstream 2b pairs, up to 16b (max key size):
* - read 2b from bitstream (from higher to lower) * - read 2b from bitstream (from higher to lower)
@ -101,7 +102,7 @@ static int ahx_decrypt_type08(mpeg_codec_data *data) {
} }
/* write output */ /* write output */
put_32bitBE(data->buffer + 0x0d, value); put_32bitBE(buffer + 0x0d, value);
return 1; return 1;
fail: fail:

View File

@ -170,7 +170,7 @@ int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data,
goto fail; goto fail;
current_data_size = info.frame_size; 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; stream->offset += current_data_size;

View File

@ -7,11 +7,12 @@
* with regular MPEG data and optional PCM blocks. We transform EA-frames to MPEG-frames on the fly * 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. * 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 * Layer III MPEG1 uses two granules (data chunks) per frame, while MPEG2/2.5 ("LSF mode") only one.
* contain one granule, so to reconstruct one MPEG-frame we need two EA-frames (MPEG1) or one (MPEG2). * 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. * 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 * Reference: https://www.mp3-tech.org/programmer/docs/mp3_theory.pdf
* https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/mpegaudiodec_template.c#L1306 * https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/mpegaudiodec_template.c#L1306
*/ */
@ -24,27 +25,20 @@
#define EALAYER3_MAX_GRANULES 2 #define EALAYER3_MAX_GRANULES 2
#define EALAYER3_MAX_CHANNELS 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 */ /* parsed info from a single EALayer3 frame */
typedef struct { typedef struct {
/* EALayer3 v1 header */ /* EALayer3 v1 header */
uint32_t v1_pcm_flag; uint32_t v1_pcm_flag;
uint32_t v1_pcm_decode_discard; uint32_t v1_pcm_decode_discard;
uint32_t v1_pcm_number; uint32_t v1_pcm_number;
uint32_t v1_pcm_unknown;
/* EALayer3 v2 header */ /* EALayer3 v2 header */
uint32_t v2_extended_flag; uint32_t v2_extended_flag;
uint32_t v2_stereo_flag; uint32_t v2_stereo_flag;
uint32_t v2_unknown; /* unused? */ uint32_t v2_unknown; /* unused? */
uint32_t v2_frame_size; /* full size including headers and pcm block */ 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_mode_value; /* samples to use depending on mode */
uint32_t v2_pcm_number; uint32_t v2_pcm_number;
uint32_t v2_common_size; /* common header+data size; can be zero */ uint32_t v2_common_size; /* common header+data size; can be zero */
@ -79,32 +73,26 @@ typedef struct {
} ealayer3_frame_info; } ealayer3_frame_info;
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);
static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame); 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(ealayer3_bitstream *is, ealayer3_frame_info * eaf); static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_common(ealayer3_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(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os); 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 ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf);
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start);
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);
/* **************************************************************************** */ /* **************************************************************************** */
/* EXTERNAL API */ /* 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 mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type) {
int ok; int ok;
ealayer3_frame_info eaf; ealayer3_frame_info eaf;
ealayer3_bitstream is; vgm_bitstream is = {0};
uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE]; uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE];
//;VGM_LOG("EAFRAME: EALayer3 init at %lx\n", start_offset); //;VGM_LOG("init at %lx\n", start_offset);
if (data->type == MPEG_EAL32P || data->type == MPEG_EAL32S)
goto fail; /* untested */
/* get first frame for info */ /* 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); ok = ealayer3_parse_frame(data, &is, &eaf);
if (!ok) goto fail; if (!ok) goto fail;
} }
VGM_ASSERT(!eaf.mpeg1, "MPEG EAL3: mpeg2 found at 0x%lx\n", start_offset); /* untested */
;VGM_ASSERT(!eaf.mpeg1, "MPEG EAL3: mpeg2 found at 0x%lx\n", start_offset);
*coding_type = coding_MPEG_ealayer3; *coding_type = coding_MPEG_ealayer3;
data->channels_per_frame = eaf.channels; data->channels_per_frame = eaf.channels;
data->samples_per_frame = eaf.mpeg1 ? 1152 : 576; 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) */ /* encoder delay: EALayer3 handles this while decoding (skips samples as writes PCM blocks) */
return 1; return 1;
@ -138,15 +118,20 @@ fail:
/* writes data to the buffer and moves offsets, transforming EALayer3 frames */ /* 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 mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) {
int ok; mpeg_custom_stream *ms = data->streams[num_stream];
off_t current_offset = stream->offset; int ok, granule_found;
off_t info_offset = stream->offset;
ealayer3_frame_info eaf_0, eaf_1; 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]; 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.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.bufsize = read_streamfile(ibuf_0,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
is_0.b_off = 0; is_0.b_off = 0;
@ -158,51 +143,54 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
if (!ok) goto fail; if (!ok) goto fail;
stream->offset += eaf_0.eaframe_size; 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 (!ealayer3_skip_data(stream, data, num_stream, 0))
if (eaf_0.mpeg1) { goto fail;
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;
ok = ealayer3_parse_frame(data, &is_1, &eaf_1); }
if (!ok) goto fail;
ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_1); /* get second frame/granule (MPEG1 only) if first granule was found */
if (!ok) goto fail; 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 */ ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_1);
if (eaf_1.v1_pcm_flag == 0xEE) if (!ok) goto fail;
granule1_found = 0;
else stream->offset += eaf_1.eaframe_size;
granule1_found = 1; /* assume it does (bad infinite loops) */ //;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);
}
while(!granule1_found); if (!ealayer3_skip_data(stream, data, num_stream, 0))
} goto fail;
else {
memset(&eaf_1, 0, sizeof(ealayer3_frame_info)); /* 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 */ /* rebuild EALayer frame to MPEG frame */
{ {
os.buf = data->buffer; os.buf = ms->buffer;
os.bufsize = data->buffer_size; os.bufsize = ms->buffer_size;
os.b_off = 0; 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); ok = ealayer3_rebuild_mpeg_frame(&is_0, &eaf_0, &is_1, &eaf_1, &os);
if (!ok) goto fail; 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; return 1;
fail: fail:
return 0; return 0;
@ -213,31 +201,29 @@ fail:
/* INTERNAL HELPERS */ /* 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; int ok;
/* make sure as there is re-parsing in loops */
memset(eaf, 0, sizeof(ealayer3_frame_info)); memset(eaf, 0, sizeof(ealayer3_frame_info));
switch(data->type) { 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_EAL32P:
case MPEG_EAL32S: ok = ealayer3_parse_frame_v2(is, eaf); break; case MPEG_EAL32S: ok = ealayer3_parse_frame_v2(is, eaf); break;
default: goto fail; default: goto fail;
} }
if (!ok) 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; return 1;
fail: fail:
return 0; 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; int ok;
/* read EA-frame V1 header */ /* 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"); VGM_LOG("MPEG EAL3 v1: header not 0x00 or 0xEE\n");
goto fail; /* wrong offset? */ 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 */ /* check PCM block */
if (eaf->v1_pcm_flag == 0xEE) { 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_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 */ 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->pre_size += 2+2; /* 16b+16b */
eaf->pcm_size = (2*eaf->v1_pcm_number * channels_per_frame); eaf->pcm_size = (2*eaf->v1_pcm_number * channels_per_frame);
}
else { if (is_v1b) { /* extra 32b in v1b */
/* read EA-frame common header */ r_bits(is, 32,&eaf->v1_pcm_unknown);
ok = ealayer3_parse_frame_common(is, eaf); eaf->pre_size += 4; /* 32b */
if (!ok) goto fail; 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; eaf->eaframe_size = eaf->pre_size + eaf->common_size + eaf->pcm_size;
@ -277,8 +268,9 @@ fail:
return 0; return 0;
} }
/* read V2"PCM" and V2"Spike" EALayer3 frame (exactly the same but V2P seems to have bigger
static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf) { * PCM blocks and maybe smaller frames) */
static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf) {
int ok; int ok;
/* read EA-frame V2 header */ /* 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, 1,&eaf->v2_stereo_flag);
r_bits(is, 2,&eaf->v2_unknown); r_bits(is, 2,&eaf->v2_unknown);
r_bits(is, 12,&eaf->v2_frame_size); r_bits(is, 12,&eaf->v2_frame_size);
eaf->pre_size = 2; /* 16b */ eaf->pre_size = 2; /* 16b */
if (eaf->v2_extended_flag) { 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_mode_value);
r_bits(is, 10,&eaf->v2_pcm_number); r_bits(is, 10,&eaf->v2_pcm_number);
r_bits(is, 10,&eaf->v2_common_size); r_bits(is, 10,&eaf->v2_common_size);
eaf->pre_size += 4; /* 32b */ eaf->pre_size += 4; /* 32b */
} }
/* read EA-frame common header */ /* read EA-frame common header */
ok = ealayer3_parse_frame_common(is, eaf); if (!eaf->v2_extended_flag || (eaf->v2_extended_flag && eaf->v2_common_size)) {
if (!ok) goto fail; 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;
} }
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->pcm_size = (2*eaf->v2_pcm_number * eaf->channels);
eaf->eaframe_size = eaf->pre_size + eaf->common_size + eaf->pcm_size; 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); 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; goto fail;
} }
@ -324,8 +315,8 @@ fail:
} }
/* Parses a EALayer3 frame (common part) */ /* parses an EALayer3 frame (common part) */
static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf) { static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf) {
/* index tables */ /* index tables */
static const int versions[4] = { /* MPEG 2.5 */ 3, /* reserved */ -1, /* MPEG 2 */ 2, /* MPEG 1 */ 1 }; 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] */ 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) */ 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]; 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 */ 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); 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; 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 */ /* converts an 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) { 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; uint32_t c = 0;
int i,j; int i,j;
int expected_bitrate_index, expected_frame_size; int expected_bitrate_index, expected_frame_size;
if (!eaf_0->common_size && !eaf_1->common_size) /* ignore PCM-only frames */
return 1; /* empty frames, PCM block only */ if (!eaf_0->common_size)
return 1;
/* 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;
}
/* extra checks */ /* extra checks */
if (eaf_0->mpeg1) { if (eaf_0->mpeg1 && (!eaf_1
if (!eaf_1 || eaf_0->mpeg1 != eaf_1->mpeg1
|| eaf_0->mpeg1 != eaf_1->mpeg1 || eaf_0->version != eaf_1->version
|| eaf_0->version != eaf_1->version || eaf_0->granule_index == eaf_1->granule_index
|| eaf_0->granule_index == eaf_1->granule_index || !eaf_0->common_size || !eaf_1->common_size)) {
|| !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);
VGM_LOG("MPEG EAL3: EA-frames for MPEG1 don't match at 0x%lx\n", os->offset); goto fail;
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 */ /* write MPEG1/2 frame header */
w_bits(os, 11, 0x7FF); /* sync */ w_bits(os, 11, 0x7FF); /* sync */
w_bits(os, 2, eaf_0->version_index); 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) { 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); /* bit reservoir! shouldn't happen with free bitrate, otherwise it's hard to fix as needs complex buffering/calcs */
//todo bit reservoir! (doesn't seem to affect the output too much) 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);
//;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);
} }
else { else {
/* fill ancillary data (ignored) */ /* fill ancillary data (ignored) */
@ -541,7 +540,9 @@ fail:
return 0; 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) { 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]; mpeg_custom_stream *ms = data->streams[num_stream];
size_t bytes_filled; 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; bytes_filled = sizeof(sample)*ms->samples_filled*data->channels_per_frame;
if (bytes_filled + eaf->pcm_size > ms->output_buffer_size) { 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); VGM_LOG("MPEG EAL3: can't fill the sample buffer with 0x%x\n", eaf->pcm_size);
goto fail; goto fail;
} }
if (eaf->v1_pcm_number) { 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_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); 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) //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 */ /* special meanings */
if (decode_to_discard == 576) if (data->type == MPEG_EAL31) {
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number; 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; 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: #if 0
* BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3 /* todo supposed skip modes (only seen 0x00):
* *
* AB00CCCC CCCCCCCC if A is set: DDEEEEEE EEEEFFFF FFFFFFGG GGGGGGGG * AB00CCCC CCCCCCCC if A is set: DDEEEEEE EEEEFFFF FFFFFFGG GGGGGGGG
* D = mode: * D = BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3
* E = bytes to discard (mode == 0) or skip (mode == 1 or 2) before outputting the uncompressed samples * E = samples to discard (mode == 0) or skip (mode == 1 or 2) before outputting the uncompressed samples
* (when mode == 3 this is ignored) * (when mode == 3 this is ignored)
* F = number of uncompressed sample frames * F = number of uncompressed sample frames (pcm block)
* G = MPEG granule size (can be zero) * G = MPEG granule size (can be zero)
* *
* if 0: 576 - E if G == 0 then F * if 0: 576 - E if G == 0 then F
* if 1: 576 if G == 0 then F * if 1: 576 if G == 0 then F
* if 2: 576 if G == 0 then F * 2 * if 2: 576 if G == 0 then F * 2
* if 3: 576 * 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; return 1;
fail: fail:
return 0; return 0;
} }
/* ********************************************* */
/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */ /* Skip EA-frames from other streams for multichannel (interleaved 1 EA-frame per stream).
static int r_bits(ealayer3_bitstream * is, int num_bits, uint32_t * value) { * Due to EALayer3 being in blocks and other complexities (we can't go past a block) all
off_t off, pos; * streams's offsets should start in the first stream's EA-frame.
int i, bit_buf, bit_val; *
if (num_bits == 0) return 1; * So to properly read one MPEG-frame from a stream we need to:
if (num_bits > 32 || num_bits < 0 || is->b_off + num_bits > is->bufsize*8) goto fail; * - 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? */ for (i = 0; i < skips; i++) {
*value |= bit_val; /* set bit */ 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++; ok = ealayer3_parse_frame(data, &is, &eaf);
if (pos%8 == 0) { /* new byte starts */ if (!ok) goto fail;
pos = 0;
off++; 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; return 1;
fail: fail:
return 0; return 0;

View File

@ -10,10 +10,9 @@
* - don't force channel param and get them from frame headers for some types (for MPEG_STANDARD) * - 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 * - 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 * - 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 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); 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) if (channels_per_frame != channels)
goto fail; 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 */ /* reinit, to ignore the reading done */
mpg123_open_feed(main_m); 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)); data = calloc(1,sizeof(mpeg_codec_data));
if (!data) goto fail; 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 */ /* keep around to decode */
data->custom = 1; data->custom = 1;
data->type = type; data->type = type;
@ -137,6 +133,7 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start
/* init per subtype */ /* init per subtype */
switch(data->type) { switch(data->type) {
case MPEG_EAL31: case MPEG_EAL31:
case MPEG_EAL31b:
case MPEG_EAL32P: case MPEG_EAL32P:
case MPEG_EAL32S: ok = mpeg_custom_setup_init_ealayer3(streamFile, start_offset, data, coding_type); break; 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; 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_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)); data->streams[i]->output_buffer = calloc(data->streams[i]->output_buffer_size, sizeof(uint8_t));
if (!data->streams[i]->output_buffer) goto fail; 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 */ /* end of stream, fill rest with 0s */
if (!data->bytes_in_buffer) { 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; break;
} }
@ -367,7 +369,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
int rc, ok; int rc, ok;
mpeg_custom_stream *ms = data->streams[num_stream]; 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 */ /* wait until samples are depleted, so buffers don't grow too big */
if (ms->samples_filled - ms->samples_used > 0) { 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; ms->samples_used = 0;
/* extra EOF check for edge cases when the caller tries to read more samples than possible */ /* 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"); VGM_LOG("MPEG: EOF found but more data is requested\n");
goto decode_fail; goto decode_fail;
} }
/* read more raw data (could fill the sample buffer too in some cases, namely EALayer3) */ /* 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"); //;VGM_LOG("MPEG: reading more raw data\n");
switch(data->type) { switch(data->type) {
case MPEG_EAL31: case MPEG_EAL31:
case MPEG_EAL31b:
case MPEG_EAL32P: case MPEG_EAL32P:
case MPEG_EAL32S: ok = mpeg_custom_parse_frame_ealayer3(stream, data, num_stream); break; 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; 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) { if (!ok) {
VGM_LOG("MPEG: cannot parse frame @ around %lx\n",stream->offset); VGM_LOG("MPEG: cannot parse frame @ around %lx\n",stream->offset);
goto decode_fail; /* mpg123 could resync but custom MPEGs wouldn't need that */ 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) */ /* parse frame may not touch the buffer (only move offset, or fill the sample buffer) */
if (data->bytes_in_buffer) { if (ms->bytes_in_buffer) {
data->buffer_full = 1; ms->buffer_full = 1;
data->buffer_used = 0; 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; 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 */ /* feed new raw data to the decoder if needed, copy decoded results to frame buffer output */
if (!data->buffer_used) { if (!ms->buffer_used) {
//;VGM_LOG("MPEG: feed new data and get samples \n"); //;VGM_LOG("MPEG: feed new data and get samples\n");
rc = mpg123_decode(ms->m, 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, (unsigned char*)ms->output_buffer + bytes_filled, ms->output_buffer_size - bytes_filled,
&bytes_done); &bytes_done);
data->buffer_used = 1; ms->buffer_used = 1;
} }
else { else {
//;VGM_LOG("MPEG: get samples from old data\n"); //;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 /* 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) */ * (but only with empty mpg123 buffer, EA blocks wait for all samples decoded before advancing blocks) */
if (!bytes_done && rc == MPG123_NEED_MORE) { if (!bytes_done && rc == MPG123_NEED_MORE) {
//;VGM_LOG("MPEG: need more raw data to get samples (bytest_done=%x)\n", bytes_done); //;VGM_LOG("MPEG: need more raw data to get samples (bytes_done=%x)\n", bytes_done);
data->buffer_full = 0; ms->buffer_full = 0;
} }
//;VGM_LOG("MPEG: stream samples now=%i, filled=%i)\n\n", ms->samples_filled, samples_filled);
return; return;
decode_fail: decode_fail:
@ -490,6 +482,7 @@ void free_mpeg(mpeg_codec_data *data) {
int i; int i;
for (i=0; i < data->streams_size; i++) { for (i=0; i < data->streams_size; i++) {
mpg123_delete(data->streams[i]->m); mpg123_delete(data->streams[i]->m);
free(data->streams[i]->buffer);
free(data->streams[i]->output_buffer); free(data->streams[i]->output_buffer);
free(data->streams[i]); free(data->streams[i]);
} }
@ -537,6 +530,8 @@ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) {
/* seek multistream */ /* seek multistream */
if (!data->custom) { if (!data->custom) {
mpg123_feedseek(data->m, num_sample,SEEK_SET,&input_offset); 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) if (vgmstream->loop_ch)
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset + input_offset; 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_filled = 0;
data->streams[i]->samples_used = 0; data->streams[i]->samples_used = 0;
data->streams[i]->decode_to_discard = 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) if (vgmstream->loop_ch)
vgmstream->loop_ch[i].offset = vgmstream->loop_ch[i].channel_start_offset; 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_filled = 0;
data->streams[i]->samples_used = 0; data->streams[i]->samples_used = 0;
data->streams[i]->decode_to_discard = 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 */ 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) { 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 not found just return 0 and expect to fail (if used for num_samples) */
if (!data->custom) { 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 */ /* 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 0;
}
return (int64_t)bytes * mi.rate * 8 / (mi.bitrate * 1000); return (int64_t)bytes * data->mi.rate * 8 / (data->mi.bitrate * 1000);
} }
else { else {
return 0; /* a bit too complex for what is worth */ return 0; /* a bit too complex for what is worth */
} }
} }
#if 0
/* disables/enables stderr output, for MPEG known to contain recoverable errors */ /* disables/enables stderr output, for MPEG known to contain recoverable errors */
void mpeg_set_error_logging(mpeg_codec_data * data, int enable) { void mpeg_set_error_logging(mpeg_codec_data * data, int enable) {
if (!data->custom) { if (!data->custom) {
@ -621,5 +619,5 @@ void mpeg_set_error_logging(mpeg_codec_data * data, int enable) {
} }
} }
} }
#endif
#endif #endif

View File

@ -2,6 +2,7 @@
#define _MPEG_DECODER_H_ #define _MPEG_DECODER_H_
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../coding/coding.h"
/* used by mpeg_decoder.c, but scattered in other .c files */ /* used by mpeg_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_MPEG #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_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_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_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream);
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);
int mpeg_custom_parse_frame_ealayer3(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); int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream);

View File

@ -37,13 +37,11 @@ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
} }
/* read from memory rather than a file */ /* 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; int i=first_sample;
int32_t sample_count; int32_t sample_count;
int framesin = first_sample/14; int8_t header = mem[0];
int8_t header = mem[framesin*8];
int32_t scale = 1 << (header & 0xf); int32_t scale = 1 << (header & 0xf);
int coef_index = (header >> 4) & 0xf; int coef_index = (header >> 4) & 0xf;
int32_t hist1 = stream->adpcm_history1_16; 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; first_sample = first_sample%14;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = mem[framesin*8+1+i/2]; int sample_byte = mem[1 + i/2];
outbuf[sample_count] = clamp16(( outbuf[sample_count] = clamp16((
(((i&1? (((i&1?
@ -72,6 +70,27 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
stream->adpcm_history2_16 = hist2; stream->adpcm_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 * 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 * variants don't have a proper sample count, so we (who are interested

View File

@ -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_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_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_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; default: goto fail;
} }
if(!ok) 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_WWISE: ok = vorbis_custom_parse_packet_wwise(stream, data); break;
case VORBIS_OGL: ok = vorbis_custom_parse_packet_ogl(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_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; default: goto decode_fail;
} }
if(!ok) { 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 */ /* parse the fake ogg packet into a logical vorbis block */
rc = vorbis_synthesis(&data->vb,&data->op); rc = vorbis_synthesis(&data->vb,&data->op);
if (rc == OV_ENOTAUDIO) { if (rc == OV_ENOTAUDIO) {
VGM_LOG("Vorbis: not an audio packet @ %lx\n",stream->offset); VGM_LOG("Vorbis: not an audio packet (size=0x%x) @ %lx\n",(size_t)data->op.bytes,stream->offset);
continue; /* not tested */ //VGM_LOGB(data->op.packet, (size_t)data->op.bytes,0);
continue; /* seems ok? */
} else if (rc != 0) { } else if (rc != 0) {
VGM_LOG("Vorbis: cannot parse Vorbis block @ %lx\n",stream->offset); VGM_LOG("Vorbis: cannot parse Vorbis block @ %lx\n",stream->offset);
goto decode_fail; goto decode_fail;
@ -164,7 +167,7 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample
decode_fail: decode_fail:
/* on error just put some 0 samples */ /* 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) */ /* converts from internal Vorbis format to standard PCM (mostly from Xiph's decoder_example.c) */

View File

@ -2,6 +2,7 @@
#define _VORBIS_CUSTOM_DECODER_H_ #define _VORBIS_CUSTOM_DECODER_H_
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../coding/coding.h"
/* used by vorbis_custom_decoder.c, but scattered in other .c files */ /* used by vorbis_custom_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_VORBIS #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_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_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_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_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_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_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_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/* VGM_USE_VORBIS */
#endif/*_VORBIS_CUSTOM_DECODER_H_ */ #endif/*_VORBIS_CUSTOM_DECODER_H_ */

View File

@ -0,0 +1,152 @@
#include "vorbis_custom_decoder.h"
#ifdef VGM_USE_VORBIS
#include <vorbis/codec.h>
/* **************************************************************************** */
/* 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

View File

@ -13,25 +13,17 @@
/* DEFS */ /* 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_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 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 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_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 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_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(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);
static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw); static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_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(vgm_bitstream * ow, vgm_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_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 int ww2ogg_tremor_ilog(unsigned int v);
static unsigned int ww2ogg_tremor_book_maptype1_quantvals(unsigned int entries, unsigned int dimensions); 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_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 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 */ /* 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) */ /* 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) { 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; int rc, granulepos;
size_t header_size, packet_size; 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 */ /* prepare helper structs */
ow.buf = obuf; ow.buf = obuf;
ow.bufsize = obufsize; ow.bufsize = obufsize;
ow.b_off = 0 ; ow.b_off = 0;
ow.mode = BITSTREAM_VORBIS;
iw.buf = ibuf; iw.buf = ibuf;
iw.bufsize = ibufsize; iw.bufsize = ibufsize;
iw.b_off = 0; iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
rc = ww2ogg_generate_vorbis_packet(&ow,&iw, streamFile,offset, data, big_endian); rc = ww2ogg_generate_vorbis_packet(&ow,&iw, streamFile,offset, data, big_endian);
if (!rc) goto fail; if (!rc) goto fail;
@ -206,7 +197,7 @@ fail:
/* Transforms a Wwise setup packet into a real Vorbis one (depending on config). */ /* 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) { 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; int rc, granulepos;
size_t header_size, packet_size; 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.buf = obuf;
ow.bufsize = obufsize; ow.bufsize = obufsize;
ow.b_off = 0; ow.b_off = 0;
ow.mode = BITSTREAM_VORBIS;
iw.buf = ibuf; iw.buf = ibuf;
iw.bufsize = ibufsize; iw.bufsize = ibufsize;
iw.b_off = 0; iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
rc = ww2ogg_generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile); rc = ww2ogg_generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile);
if (!rc) goto fail; 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. /* 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) */ * (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; int i,granule;
size_t header_size, packet_size, data_size; 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 */ /* get next first byte to read next_mode_number */
uint32_t next_mode_number; uint32_t next_mode_number;
uint8_t nbuf[1]; uint8_t nbuf[1];
ww_bitstream nw; vgm_bitstream nw;
nw.buf = nbuf; nw.buf = nbuf;
nw.bufsize = 1; nw.bufsize = 1;
nw.b_off = 0; nw.b_off = 0;
nw.mode = BITSTREAM_VORBIS;
if (read_streamfile(nw.buf, next_offset + next_header_size, nw.bufsize, streamFile) != nw.bufsize) if (read_streamfile(nw.buf, next_offset + next_header_size, nw.bufsize, streamFile) != nw.bufsize)
goto fail; goto fail;
@ -409,7 +405,7 @@ fail:
/* Rebuild a Wwise setup (simplified with removed stuff), recreating all six setup parts. /* 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) */ * (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; int i,j,k;
uint32_t codebook_count = 0, floor_count = 0, residue_count = 0; uint32_t codebook_count = 0, floor_count = 0, residue_count = 0;
uint32_t codebook_count_less1 = 0; uint32_t codebook_count_less1 = 0;
@ -798,7 +794,7 @@ fail:
/* copies Vorbis codebooks (untouched, but size uncertain) */ /* 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; int i;
uint32_t id = 0, dimensions = 0, entries = 0; uint32_t id = 0, dimensions = 0, entries = 0;
uint32_t ordered = 0, lookup_type = 0; uint32_t ordered = 0, lookup_type = 0;
@ -914,7 +910,7 @@ fail:
/* rebuilds a Wwise codebook into a Vorbis codebook */ /* 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; int i;
uint32_t id = 0, dimensions = 0, entries = 0; uint32_t id = 0, dimensions = 0, entries = 0;
uint32_t ordered = 0, lookup_type = 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 */ /* 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 */ size_t ibufsize = 0x8000; /* arbitrary max size of a codebook */
uint8_t ibuf[0x8000]; /* Wwise codebook buffer */ uint8_t ibuf[0x8000]; /* Wwise codebook buffer */
size_t cb_size; size_t cb_size;
ww_bitstream iw; vgm_bitstream iw;
cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, streamFile); cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, streamFile);
if (cb_size == 0) goto fail; 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.buf = ibuf;
iw.bufsize = ibufsize; iw.bufsize = ibufsize;
iw.b_off = 0; iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, streamFile); return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, streamFile);
fail: fail:
@ -1228,70 +1225,4 @@ fail:
return 0; 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 #endif

View File

@ -7,21 +7,21 @@ const int SHC = 10;
double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125}; double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125};
double K1[4] = { 0.0, 0.0, -0.8125,-0.859375}; 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))); } { return ((int)((-K0[fid]) * (1 << SHC))); }
int IK1(int fid) static int IK1(int fid)
{ return ((int)((-K1[fid]) * (1 << SHC))); } { 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 < Minim) value = Minim;
if (value > Maxim) value = Maxim; if (value > Maxim) value = Maxim;
return value; return value;
} }
void init_get_high_nibble(VGMSTREAM *vgmstream) { void xa_init_get_high_nibble(VGMSTREAM *vgmstream) {
vgmstream->get_high_nibble=1; 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) { 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; 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)) 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; 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->get_high_nibble,stream->streamfile) & 0xf; shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->xa_get_high_nibble,stream->streamfile) & 0xf;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+16+framesin+(i*4),stream->streamfile); short sample_byte = (short)read_8bit(stream->offset+16+framesin+(i*4),stream->streamfile);
scale = ((vgmstream->get_high_nibble ? scale = ((vgmstream->xa_get_high_nibble ?
sample_byte >> 4 : sample_byte >> 4 :
sample_byte & 0x0f)<<12); 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_history1_32=hist1;
stream->adpcm_history2_32=hist2; 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;
}
}

View File

@ -1,4 +1,4 @@
#include "formats.h" #include "vgmstream.h"
//#define VGM_REGISTER_TYPE(extension) ... //#define VGM_REGISTER_TYPE(extension) ...
//#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */ //#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */
@ -52,6 +52,7 @@ static const char* extension_list[] = {
"bar", "bar",
"bcstm", "bcstm",
"bcwav", "bcwav",
"bd3", //txth/reserved [Elevator Action Deluxe (PS3)]
"bdsp", "bdsp",
"bfstm", "bfstm",
"bfwav", "bfwav",
@ -81,6 +82,7 @@ static const char* extension_list[] = {
"capdsp", "capdsp",
"cbd2", "cbd2",
"ccc", "ccc",
"cd",
"cfn", "cfn",
"ckd", "ckd",
"cnk", "cnk",
@ -92,6 +94,7 @@ static const char* extension_list[] = {
"dcs", "dcs",
"ddsp", "ddsp",
"de2", "de2",
"dec",
"dmsg", "dmsg",
"dsp", "dsp",
"dspw", "dspw",
@ -103,10 +106,12 @@ static const char* extension_list[] = {
"emff", "emff",
"enth", "enth",
"exa", "exa",
"ezw",
"fag", "fag",
"ffw", "ffw",
"filp", "filp",
"flx",
"fsb", "fsb",
"fwav", "fwav",
@ -132,7 +137,7 @@ static const char* extension_list[] = {
"iab", "iab",
"iadp", "iadp",
"idsp", "idsp",
"idvi", "idvi", //fake extension (to be removed)
"ikm", "ikm",
"ild", "ild",
"int", "int",
@ -147,12 +152,13 @@ static const char* extension_list[] = {
"jstm", "jstm",
"kces", "kces",
"kcey", "kcey", //fake extension (to be removed)
"khv", "khv",
"kovs", "kovs",
"kraw", "kraw",
"laac", //fake extension, for AAC (tri-Ace/FFmpeg) "laac", //fake extension, for AAC (tri-Ace/FFmpeg)
"lac3", //fake extension, for AC3
"leg", "leg",
"lmp4", //fake extension, for MP4s "lmp4", //fake extension, for MP4s
"logg", //fake extension, for OGGs "logg", //fake extension, for OGGs
@ -174,7 +180,9 @@ static const char* extension_list[] = {
"mic", "mic",
"mihb", "mihb",
"mnstr", "mnstr",
"mogg",
//"mp4", //common //"mp4", //common
//"mpc", //FFmpeg, not parsed (musepack) //common
"mpdsp", "mpdsp",
"mpds", "mpds",
"msa", "msa",
@ -190,6 +198,7 @@ static const char* extension_list[] = {
"mxst", "mxst",
"myspd", "myspd",
"naac",
"ndp", "ndp",
"ngca", "ngca",
"nps", "nps",
@ -201,7 +210,7 @@ static const char* extension_list[] = {
"ogl", "ogl",
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"omu", "omu",
"opus", //"opus", //common
"otm", "otm",
"p1d", //txth/reserved [Farming Simulator 18 (3DS)] "p1d", //txth/reserved [Farming Simulator 18 (3DS)]
@ -226,7 +235,8 @@ static const char* extension_list[] = {
"rrds", "rrds",
"rsd", "rsd",
"rsf", "rsf",
"rstm", "rsm",
"rstm", //rsm header id
"rvws", "rvws",
"rwar", "rwar",
"rwav", "rwav",
@ -239,10 +249,19 @@ static const char* extension_list[] = {
"sab", "sab",
"sad", "sad",
"sap", "sap",
"sb0",
"sb1",
"sb2",
"sb3",
"sb4",
"sb5",
"sb6",
"sb7",
"sc", "sc",
"scd", "scd",
"sck", "sck",
"sd9", "sd9",
"sdf",
"sdt", "sdt",
"seg", "seg",
"sf0", "sf0",
@ -255,10 +274,11 @@ static const char* extension_list[] = {
"sl3", "sl3",
"sli", "sli",
"smp", "smp",
"smpl", "smpl", //fake extension (to be removed)
"snd", "snd",
"snds", "snds",
"sng", "sng",
"snr",
"sns", "sns",
"snu", "snu",
"spd", "spd",
@ -267,8 +287,6 @@ static const char* extension_list[] = {
"spsd", "spsd",
"spw", "spw",
"ss2", "ss2",
"ss3",
"ss7",
"ssm", "ssm",
"sss", "sss",
"ster", "ster",
@ -299,21 +317,24 @@ static const char* extension_list[] = {
"ulw", "ulw",
"um3", "um3",
"v0",
//"v1", //dual channel with v0
"vag", "vag",
"vas", "vas",
"vawx", "vawx",
"vb", "vb",
"vbk", "vbk",
"vds",
"vdm",
"vgs", "vgs",
"vgv", "vgv",
"vig", "vig",
"vds",
"vdm",
"vms", "vms",
"voi", "voi",
"vpk", "vpk",
"vs", "vs",
"vsf", "vsf",
"vxn",
"waa", "waa",
"wac", "wac",
@ -365,22 +386,12 @@ static const char* extension_list[] = {
//, NULL //end mark //, NULL //end mark
}; };
/** /* List supported formats and return elements in the list, for plugins that need to know. */
* List of supported formats. const char ** vgmstream_get_formats(size_t * size) {
* *size = sizeof(extension_list) / sizeof(char*);
* For plugins that need to know (test.exe doesn't use it)
*/
const char ** vgmstream_get_formats() {
return extension_list; return extension_list;
} }
/**
* Number of elements in the list.
*/
int vgmstream_get_formats_length() {
return sizeof(extension_list) / sizeof(char*);
}
/* internal description info */ /* internal description info */
@ -404,51 +415,54 @@ static const coding_info coding_info_list[] = {
{coding_PCM16LE, "Little Endian 16-bit PCM"}, {coding_PCM16LE, "Little Endian 16-bit PCM"},
{coding_PCM16LE_XOR_int, "Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"}, {coding_PCM16LE_XOR_int, "Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"},
{coding_PCM16BE, "Big Endian 16-bit PCM"}, {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, "8-bit PCM"},
{coding_PCM8_int, "8-bit PCM with 1 byte interleave (block)"},
{coding_PCM8_U, "8-bit unsigned PCM"}, {coding_PCM8_U, "8-bit unsigned PCM"},
{coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave"}, {coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave (block)"},
{coding_PCM8_int, "8-bit PCM with 1 byte interleave"}, {coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave (block)"},
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"},
{coding_ULAW, "8-bit u-Law"}, {coding_ULAW, "8-bit u-Law"},
{coding_ALAW, "8-bit a-Law"}, {coding_ALAW, "8-bit a-Law"},
{coding_PCMFLOAT, "32-bit float PCM"}, {coding_PCMFLOAT, "32-bit float PCM"},
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"}, {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 (fixed coefficients)"},
{coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM with 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_8, "CRI ADX 4-bit ADPCM (type 8 encryption)"},
{coding_CRI_ADX_enc_9, "CRI ADX 4-bit ADPCM (type 9 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, "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_DTK, "Nintendo DTK 4-bit ADPCM"},
{coding_NGC_AFC, "Nintendo AFC 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_G721, "CCITT G.721 4-bit ADPCM"},
{coding_XA, "CD-ROM XA 4-bit ADPCM"},
{coding_PSX, "Playstation 4-bit ADPCM"}, {coding_PSX, "Playstation 4-bit ADPCM"},
{coding_PSX_badflags, "Playstation 4-bit ADPCM (bad flags)"}, {coding_PSX_badflags, "Playstation 4-bit ADPCM (bad flags)"},
{coding_PSX_bmdx, "Playstation 4-bit ADPCM (BMDX encryption)"}, {coding_PSX_bmdx, "Playstation 4-bit ADPCM (BMDX encryption)"},
{coding_PSX_cfg, "Playstation 4-bit ADPCM (configurable)"}, {coding_PSX_cfg, "Playstation 4-bit ADPCM (configurable)"},
{coding_HEVAG, "Playstation Vita HEVAG 4-bit ADPCM"}, {coding_HEVAG, "Playstation Vita HEVAG 4-bit ADPCM"},
{coding_XA, "CD-ROM XA 4-bit ADPCM"},
{coding_XBOX, "XBOX 4-bit IMA ADPCM"}, {coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM v1"},
{coding_XBOX_int, "XBOX 4-bit IMA ADPCM (interleaved)"}, {coding_EA_XA_int, "Electronic Arts EA-XA 4-bit ADPCM v1 (mono/interleave)"},
{coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM (v1)"}, {coding_EA_XA_V2, "Electronic Arts EA-XA 4-bit ADPCM v2"},
{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_MAXIS_XA, "Maxis EA-XA 4-bit ADPCM"}, {coding_MAXIS_XA, "Maxis EA-XA 4-bit ADPCM"},
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, {coding_EA_XAS, "Electronic Arts EA-XAS 4-bit ADPCM"},
{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_IMA, "IMA 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_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, "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_APPLE_IMA4, "Apple Quicktime 4-bit IMA ADPCM"},
{coding_SNDS_IMA, "Heavy Iron .snds 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"}, {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_WWISE_IMA, "Audiokinetic Wwise 4-bit IMA ADPCM"},
{coding_REF_IMA, "Reflections 4-bit IMA ADPCM"}, {coding_REF_IMA, "Reflections 4-bit IMA ADPCM"},
{coding_AWC_IMA, "Rockstar AWC 4-bit IMA ADPCM"}, {coding_AWC_IMA, "Rockstar AWC 4-bit IMA ADPCM"},
{coding_WS, "Westwood Studios VBR ADPCM"}, {coding_UBI_IMA, "Ubisoft 4-bit IMA 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_MSADPCM, "Microsoft 4-bit ADPCM"}, {coding_MSADPCM, "Microsoft 4-bit ADPCM"},
{coding_WS, "Westwood Studios VBR ADPCM"},
{coding_AICA, "Yamaha AICA 4-bit ADPCM"}, {coding_AICA, "Yamaha AICA 4-bit ADPCM"},
{coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"}, {coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"},
{coding_L5_555, "Level-5 0x555 4-bit ADPCM"}, {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_MTAF, "Konami MTAF 4-bit ADPCM"},
{coding_MTA2, "Konami MTA2 4-bit ADPCM"}, {coding_MTA2, "Konami MTA2 4-bit ADPCM"},
{coding_MC3, "Paradigm MC3 3-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 #ifdef VGM_USE_VORBIS
{coding_ogg_vorbis, "Ogg Vorbis"}, {coding_ogg_vorbis, "Ogg Vorbis"},
@ -505,20 +529,19 @@ static const layout_info layout_info_list[] = {
{layout_none, "flat (no layout)"}, {layout_none, "flat (no layout)"},
{layout_interleave, "interleave"}, {layout_interleave, "interleave"},
{layout_interleave_shortblock, "interleave with short last block"}, {layout_interleave_shortblock, "interleave with short last block"},
{layout_interleave_byte, "sub-frame interleave"},
{layout_mxch_blocked, "MxCh blocked"}, {layout_mxch_blocked, "MxCh blocked"},
{layout_ast_blocked, "AST blocked"}, {layout_ast_blocked, "AST blocked"},
{layout_halpst_blocked, "HALPST blocked"}, {layout_halpst_blocked, "HALPST blocked"},
{layout_xa_blocked, "CD-ROM XA"}, {layout_xa_blocked, "CD-ROM XA"},
{layout_ea_blocked, "Electronic Arts SCxx blocked"}, {layout_blocked_ea_schl, "blocked (EA SCHl)"},
{layout_eacs_blocked, "Electronic Arts EACS blocked"}, {layout_blocked_ea_1snh, "blocked (EA 1SNh)"},
{layout_caf_blocked, "CAF blocked"}, {layout_caf_blocked, "CAF blocked"},
{layout_wsi_blocked, ".wsi blocked"}, {layout_wsi_blocked, ".wsi blocked"},
{layout_xvas_blocked, ".xvas blocked"}, {layout_xvas_blocked, ".xvas blocked"},
{layout_str_snds_blocked, ".str SNDS blocked"}, {layout_str_snds_blocked, ".str SNDS blocked"},
{layout_ws_aud_blocked, "Westwood Studios .aud blocked"}, {layout_ws_aud_blocked, "Westwood Studios .aud blocked"},
{layout_matx_blocked, "Matrix .matx blocked"}, {layout_matx_blocked, "Matrix .matx blocked"},
{layout_de2_blocked, "de2 blocked"}, {layout_blocked_dec, "blocked (DEC)"},
{layout_vs_blocked, "vs blocked"}, {layout_vs_blocked, "vs blocked"},
{layout_emff_ps2_blocked, "EMFF (PS2) blocked"}, {layout_emff_ps2_blocked, "EMFF (PS2) blocked"},
{layout_emff_ngc_blocked, "EMFF (NGC/WII) 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_psx_mgav_blocked, "MGAV blocked"},
{layout_ps2_adm_blocked, "ADM blocked"}, {layout_ps2_adm_blocked, "ADM blocked"},
{layout_dsp_bdsp_blocked, "DSP 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_iab_blocked, "IAB blocked"},
{layout_ps2_strlr_blocked, "The Bouncer STR blocked"}, {layout_ps2_strlr_blocked, "The Bouncer STR blocked"},
{layout_rws_blocked, "RWS 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_aix, "AIX interleave, internally 18-byte interleaved"},
{layout_aax, "AAX blocked, 18-byte interleaved"}, {layout_aax, "AAX blocked, 18-byte interleaved"},
{layout_scd_int, "SCD multistream interleave"}, {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_awc, "blocked (AWC)"},
{layout_blocked_vgs, "blocked (VGS)"}, {layout_blocked_vgs, "blocked (VGS)"},
{layout_blocked_vawx, "blocked (VAWX)"},
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
{layout_ogg_vorbis, "Ogg"}, {layout_ogg_vorbis, "Ogg"},
#endif #endif
@ -561,8 +585,8 @@ static const meta_info meta_info_list[] = {
{meta_UTF_DSP, "CRI ADPCM_WII header"}, {meta_UTF_DSP, "CRI ADPCM_WII header"},
{meta_DSP_AGSC, "Retro Studios AGSC header"}, {meta_DSP_AGSC, "Retro Studios AGSC header"},
{meta_DSP_CSMP, "Retro Studios CSMP header"}, {meta_DSP_CSMP, "Retro Studios CSMP header"},
{meta_NGC_ADPDTK, "assumed Nintendo ADP by .adp extension and valid first frame"}, {meta_NGC_ADPDTK, "Nintendo ADP raw header"},
{meta_RSF, "assumed Retro Studios RSF by .rsf extension and valid first bytes"}, {meta_RSF, "Retro Studios RSF raw header"},
{meta_AFC, "Nintendo AFC header"}, {meta_AFC, "Nintendo AFC header"},
{meta_AST, "Nintendo AST header"}, {meta_AST, "Nintendo AST header"},
{meta_HALPST, "HAL Laboratory HALPST 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_HGC1, "Knights of the Temple 2 hgC1 Header"},
{meta_AUS, "Capcom AUS Header"}, {meta_AUS, "Capcom AUS Header"},
{meta_RWS, "RenderWare RWS header"}, {meta_RWS, "RenderWare RWS header"},
{meta_EACS_PC, "Electronic Arts EACS header (PC)"}, {meta_EA_1SNH, "Electronic Arts 1SNh/EACS header"},
{meta_EACS_PSX, "Electronic Arts EACS header (PSX)"},
{meta_EACS_SAT, "Electronic Arts EACS header (SATURN)"},
{meta_SL3, "SL3 Header"}, {meta_SL3, "SL3 Header"},
{meta_FSB1, "FMOD Sample Bank (FSB1) Header"}, {meta_FSB1, "FMOD Sample Bank (FSB1) Header"},
{meta_FSB2, "FMOD Sample Bank (FSB2) 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_FILP, "Bio Hazard - Gun Survivor FILp Header"},
{meta_IKM, "Zwei!! IKM Header"}, {meta_IKM, "Zwei!! IKM Header"},
{meta_SFS, "Baroque SFS Header"}, {meta_SFS, "Baroque SFS Header"},
{meta_DVI, "DVI Header"}, {meta_SAT_DVI, "Konami KCEN DVI. header"},
{meta_KCEY, "KCEYCOMP Header"}, {meta_DC_KCEY, "Konami KCEY KCEYCOMP header"},
{meta_BG00, "Falcom BG00 Header"}, {meta_BG00, "Falcom BG00 Header"},
{meta_PS2_RSTM, "Rockstar Games RSTM Header"}, {meta_PS2_RSTM, "Rockstar Games RSTM Header"},
{meta_ACM, "InterPlay ACM 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, "RIFX WAVE header"},
{meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"}, {meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"},
{meta_XNB, "Microsoft XNA Game Studio 4.0 header"}, {meta_XNB, "Microsoft XNA Game Studio 4.0 header"},
{meta_PCM_SCD, "PCM file with custom header (SCD)"}, {meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"},
{meta_PCM_PS2, "PCM file with custom header (PS2)"}, {meta_PS2_PCM, "Konami KCEJ East .PCM header"},
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"}, {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"},
{meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"}, {meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"},
{meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"}, {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_XBOX_WVS, "Metal Arms WVS Header (XBOX)"},
{meta_NGC_WVS, "Metal Arms WVS Header (GameCube)"}, {meta_NGC_WVS, "Metal Arms WVS Header (GameCube)"},
{meta_XBOX_MATX, "assumed Matrix file by .matx extension"}, {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_VS, "Men in Black VS Header"},
{meta_DC_STR, "Sega Stream Asset Builder header"}, {meta_DC_STR, "Sega Stream Asset Builder header"},
{meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"}, {meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"},
{meta_XBOX_XMU, "XMU header"}, {meta_XBOX_XMU, "XMU header"},
{meta_XBOX_XVAS, "assumed TMNT file by .xvas extension"}, {meta_XBOX_XVAS, "assumed TMNT file by .xvas extension"},
{meta_PS2_XA2, "Acclaim XA2 Header"}, {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_NGC_YMF, "YMF DSP Header"},
{meta_PS2_CCC, "CCC Header"}, {meta_PS2_CCC, "CCC Header"},
{meta_PSX_FAG, "FAG 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_NGC_SWD, "PSF + Standard DSP Headers"},
{meta_CAFF, "Apple Core Audio Format Header"}, {meta_CAFF, "Apple Core Audio Format Header"},
{meta_PC_MXST, "Lego Island MxSt 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_MAXIS_XA, "Maxis XAI/XAJ Header"},
{meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"}, {meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"},
{meta_WII_BNS, "Nintendo BNS header"}, {meta_WII_BNS, "Nintendo BNS header"},
{meta_WII_WAS, "WAS (iSWS) DSP header"}, {meta_WII_WAS, "WAS (iSWS) DSP header"},
{meta_XBOX_HLWAV, "Half Life 2 bgm header"}, {meta_XBOX_HLWAV, "Half Life 2 bgm header"},
{meta_STX, "Nintendo .stx 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_HIS, "Her Interactive Sound header"},
{meta_PS2_AST, "KOEI AST header"}, {meta_PS2_AST, "KOEI AST header"},
{meta_CAPDSP, "Capcom DSP header"}, {meta_CAPDSP, "Capcom DSP header"},
@ -788,15 +811,15 @@ static const meta_info meta_info_list[] = {
{meta_PS2_STER, "STER Header"}, {meta_PS2_STER, "STER Header"},
{meta_BNSF, "Namco Bandai BNSF header"}, {meta_BNSF, "Namco Bandai BNSF header"},
{meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"}, {meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"},
{meta_S14, "assumed Polycom Siren 14 by .s14 extension"}, {meta_S14, "Namco .S14 raw header"},
{meta_SSS, "assumed Polycom Siren 14 by .sss extension"}, {meta_SSS, "Namco .SSS raw header"},
{meta_PS2_GCM, "GCM 'MCG' 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_PS2_MSA, "Psyvariar -Complete Edition- MSA header"},
{meta_PC_SMP, "Ghostbusters .smp Header"}, {meta_PC_SMP, "Ghostbusters .smp Header"},
{meta_NGC_PDT, "PDT DSP header"}, {meta_NGC_PDT, "PDT DSP header"},
{meta_NGC_BO2, "Blood Omen 2 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_TK1, "Tekken TK5STRM1 Header"},
{meta_PS2_ADSC, "ADSC Header"}, {meta_PS2_ADSC, "ADSC Header"},
{meta_NGC_DSP_MPDS, "MPDS DSP header"}, {meta_NGC_DSP_MPDS, "MPDS DSP header"},
@ -826,7 +849,7 @@ static const meta_info meta_info_list[] = {
{meta_NGCA, "NGCA header"}, {meta_NGCA, "NGCA header"},
{meta_WII_RAS, "RAS header"}, {meta_WII_RAS, "RAS header"},
{meta_PS2_SPM, "SPM 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_VGS, "Princess Soft VGS header"},
{meta_PS2_IAB, "IAB header"}, {meta_PS2_IAB, "IAB header"},
{meta_PS2_STRLR, "STR L/R 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_MTAF, "Konami MTAF header"},
{meta_PS2_VAG1, "Konami VAG Mono header (VAG1)"}, {meta_PS2_VAG1, "Konami VAG Mono header (VAG1)"},
{meta_PS2_VAG2, "Konami VAG Stereo header (VAG2)"}, {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_WPD, "WPD 'DPW' header"},
{meta_MN_STR, "Mini Ninjas 'STR' header"}, {meta_MN_STR, "Mini Ninjas 'STR' header"},
{meta_MSS, "Guerilla MCSS 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_NUB_XMA, "Namco NUB XMA header"},
{meta_X360_PASX, "Namco PASX header"}, {meta_X360_PASX, "Namco PASX header"},
{meta_XMA_RIFF, "Microsoft XMA RIFF 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_WWISE_RIFF, "Audiokinetic Wwise RIFF header"},
{meta_UBI_RAKI, "Ubisoft RAKI header"}, {meta_UBI_RAKI, "Ubisoft RAKI header"},
{meta_SXD, "Sony SXD 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_BINK, "RAD Game Tools Bink header"},
{meta_EA_SNU, "Electronic Arts SNU header"}, {meta_EA_SNU, "Electronic Arts SNU header"},
{meta_AWC, "Rockstar AWC 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_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 #ifdef VGM_USE_VORBIS
{meta_OGG_VORBIS, "Ogg Vorbis"}, {meta_OGG_VORBIS, "Ogg Vorbis"},

View File

@ -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_ */

View File

@ -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_per_frame = get_vgmstream_samples_per_frame(vgmstream);
int samples_this_block; int samples_this_block;
/* get samples in the current block */
if (vgmstream->current_block_samples) { if (vgmstream->current_block_samples) {
samples_this_block = 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... */
/* assume 4 bit */
/* TODO: get_vgmstream_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else { } else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
} }
while (samples_written<sample_count) { /* decode all samples */
while (samples_written < sample_count) {
int samples_to_do; int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
/* on loop those values are changed */
if (vgmstream->current_block_samples) { if (vgmstream->current_block_samples) {
samples_this_block = 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; samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else { } else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; 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; 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); 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) if (vgmstream->current_block_offset >= 0) {
samples_to_do=sample_count-samples_written;
if (vgmstream->current_block_offset>=0)
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer); decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer);
}
else { else {
/* block end signal (used below): partially 0-set buffer */
int i; int i;
/* we've run off the end! */ for (i = samples_written*vgmstream->channels; i < (samples_written+samples_to_do)*vgmstream->channels; i++) {
for (i=samples_written*vgmstream->channels; buffer[i]=0;
i<(samples_written+samples_to_do)*vgmstream->channels;i++) }
buffer[i]=0;
} }
samples_written += samples_to_do; samples_written += samples_to_do;
vgmstream->current_sample += 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 if (vgmstream->samples_into_block==samples_this_block
/*&& vgmstream->current_sample < vgmstream->num_samples*/) { /* don't go past last block */ /*&& vgmstream->current_sample < vgmstream->num_samples*/) { /* don't go past last block */
switch (vgmstream->layout_type) { switch (vgmstream->layout_type) {
case layout_ast_blocked: case layout_ast_blocked:
ast_block_update(vgmstream->next_block_offset,vgmstream); ast_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_mxch_blocked: case layout_mxch_blocked:
mxch_block_update(vgmstream->next_block_offset,vgmstream); mxch_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_halpst_blocked: case layout_halpst_blocked:
if (vgmstream->next_block_offset>=0) if (vgmstream->next_block_offset>=0)
halpst_block_update(vgmstream->next_block_offset,vgmstream); halpst_block_update(vgmstream->next_block_offset,vgmstream);
else 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; 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: case layout_wsi_blocked:
wsi_block_update(vgmstream->next_block_offset,vgmstream); wsi_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
@ -90,8 +101,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_matx_blocked: case layout_matx_blocked:
matx_block_update(vgmstream->next_block_offset,vgmstream); matx_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_de2_blocked: case layout_blocked_dec:
de2_block_update(vgmstream->next_block_offset,vgmstream); block_update_dec(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_emff_ps2_blocked: case layout_emff_ps2_blocked:
emff_ps2_block_update(vgmstream->next_block_offset,vgmstream); 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: case layout_vs_blocked:
vs_block_update(vgmstream->next_block_offset,vgmstream); vs_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_xvas_blocked: case layout_xvas_blocked:
xvas_block_update(vgmstream->next_block_offset,vgmstream); xvas_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_thp_blocked: case layout_thp_blocked:
thp_block_update(vgmstream->next_block_offset,vgmstream); thp_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_filp_blocked: case layout_filp_blocked:
filp_block_update(vgmstream->next_block_offset,vgmstream); filp_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_ivaud_blocked: case layout_blocked_ivaud:
ivaud_block_update(vgmstream->next_block_offset,vgmstream); block_update_ivaud(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_psx_mgav_blocked: case layout_psx_mgav_blocked:
psx_mgav_block_update(vgmstream->next_block_offset,vgmstream); psx_mgav_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_ps2_adm_blocked: case layout_ps2_adm_blocked:
ps2_adm_block_update(vgmstream->next_block_offset,vgmstream); ps2_adm_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_dsp_bdsp_blocked: case layout_dsp_bdsp_blocked:
dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream); dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_tra_blocked: case layout_tra_blocked:
tra_block_update(vgmstream->next_block_offset,vgmstream); tra_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_ps2_iab_blocked: case layout_ps2_iab_blocked:
ps2_iab_block_update(vgmstream->next_block_offset,vgmstream); ps2_iab_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_ps2_strlr_blocked: case layout_ps2_strlr_blocked:
ps2_strlr_block_update(vgmstream->next_block_offset,vgmstream); ps2_strlr_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
@ -141,8 +152,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_hwas_blocked: case layout_hwas_blocked:
hwas_block_update(vgmstream->next_block_offset,vgmstream); hwas_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_ea_sns_blocked: case layout_blocked_ea_sns:
ea_sns_block_update(vgmstream->next_block_offset,vgmstream); block_update_ea_sns(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_blocked_awc: case layout_blocked_awc:
block_update_awc(vgmstream->next_block_offset,vgmstream); 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: case layout_blocked_vgs:
block_update_vgs(vgmstream->next_block_offset,vgmstream); block_update_vgs(vgmstream->next_block_offset,vgmstream);
break; break;
default: case layout_blocked_vawx:
block_update_vawx(vgmstream->next_block_offset,vgmstream);
break;
default:
break; break;
} }
/* for VBR these may change */ /* 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); samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
/* get samples in the current block */
if (vgmstream->current_block_samples) { if (vgmstream->current_block_samples) {
samples_this_block = 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; samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else { } else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
} }
vgmstream->samples_into_block=0;
vgmstream->samples_into_block = 0;
} }
} }

View File

@ -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;
}
}

View File

@ -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;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = block_offset + block_header + i;
}
break;
case coding_PCM16_int:
vgmstream->current_block_size /= vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = block_offset + block_header + (i*2);
}
break;
case coding_PSX:
vgmstream->current_block_size /= vgmstream->channels;
for (i=0;i<vgmstream->channels;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;
}
}

View File

@ -3,7 +3,7 @@
#include "../vgmstream.h" #include "../vgmstream.h"
/* set up for the block at the given offset */ /* 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 i;
int new_schl = 0; int new_schl = 0;
STREAMFILE* streamFile = vgmstream->ch[0].streamfile; STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
@ -91,7 +91,7 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
break; break;
/* id, size, IMA hist, stereo/mono data */ /* id, size, IMA hist, stereo/mono data */
case coding_EACS_IMA: case coding_DVI_IMA:
for(i = 0; i < vgmstream->channels; i++) { for(i = 0; i < vgmstream->channels; i++) {
off_t header_offset = block_offset + 0xc + i*4; off_t header_offset = block_offset + 0xc + i*4;
vgmstream->ch[i].adpcm_history1_32 = read_16bitLE(header_offset+0x00, vgmstream->ch[i].streamfile); 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; 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 #ifdef VGM_USE_MPEG
/* id, size, samples, offset?, unknown (null for MP2, some constant for all blocks for EALayer3) */ /* id, size, samples, offset?, unknown (null for MP2, some constant for all blocks for EALayer3) */
case coding_MPEG_custom: 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->next_block_offset = block_offset + block_size;
vgmstream->current_block_samples = block_samples; vgmstream->current_block_samples = block_samples;
vgmstream->current_block_size = 0; /* uses current_block_samples instead */ 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;i<vgmstream->channels;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;i<vgmstream->channels;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;i<vgmstream->channels;i++)
vgmstream->ch[i].offset = vgmstream->current_block_offset+8+(i*(vgmstream->current_block_size/2));
} else {
for (i=0;i<vgmstream->channels;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;
} }

View File

@ -3,7 +3,7 @@
#include "../vgmstream.h" #include "../vgmstream.h"
/* EA "SNS "blocks (most common in .SNS) */ /* 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; STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
uint32_t block_size, block_samples; uint32_t block_size, block_samples;
size_t file_size = get_streamfile_size(streamFile); size_t file_size = get_streamfile_size(streamFile);
@ -21,15 +21,25 @@ void ea_sns_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
return; 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) { 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; block_size &= 0x00FFFFFF;
} }
for (i = 0; i < vgmstream->channels; i++) { for (i = 0; i < vgmstream->channels; i++) {
off_t channel_start = 0x00; off_t channel_start = 0x00;
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start; 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; vgmstream->current_block_offset = block_offset;

View File

@ -2,7 +2,7 @@
#include "../vgmstream.h" #include "../vgmstream.h"
/* set up for the block at the given offset */ /* 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; int i;
off_t start_offset; off_t start_offset;
off_t interleave_size; off_t interleave_size;

View File

@ -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;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = block_offset + 0x10*i;
}
}

View File

@ -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;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + 8;
}
}

View File

@ -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_written<sample_count) {
int samples_to_do;
if (vgmstream->loop_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;j<vgmstream->channels;j++) {
for (i=0;i<frame_size;i++) {
sample_data[i] = read_8bit(vgmstream->ch[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;chan<vgmstream->channels;chan++)
vgmstream->ch[chan].offset+=frame_size*vgmstream->channels;
vgmstream->samples_into_block=0;
}
}
}

View File

@ -5,19 +5,18 @@
#include "../vgmstream.h" #include "../vgmstream.h"
/* blocked layouts */ /* 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 ast_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void mxch_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 halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream); void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ea_schl_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 eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void caf_block_update(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 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); 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 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); 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 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_awc(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vgs(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 */ /* other layouts */
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); 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_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_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);

View File

@ -48,7 +48,7 @@ void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
read_32bitBE(vgmstream->current_block_offset+4, read_32bitBE(vgmstream->current_block_offset+4,
vgmstream->ch[0].streamfile); vgmstream->ch[0].streamfile);
for (i=0;i<vgmstream->channels;i++) { for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18; vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18 + i * vgmstream->interleave_block_size;
} }
} }

View File

@ -12,8 +12,8 @@ void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile); nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile);
vgmstream->next_block_offset = vgmstream->current_block_offset vgmstream->next_block_offset = vgmstream->current_block_offset
+ vgmstream->thpNextFrameSize; + vgmstream->full_block_size;
vgmstream->thpNextFrameSize=nextFrameSize; vgmstream->full_block_size = nextFrameSize;
start_offset=vgmstream->current_block_offset start_offset=vgmstream->current_block_offset
+ read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10; + read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10;

View File

@ -4,48 +4,69 @@
/* set up for the block at the given offset */ /* set up for the block at the given offset */
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream) { void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
int8_t currentChannel=0;
int8_t subAudio=0;
int i; xa_init_get_high_nibble(vgmstream);
int8_t currentChannel=0;
int8_t subAudio=0;
init_get_high_nibble(vgmstream);
if(vgmstream->samples_into_block!=0) /* don't change this variable in the init process */
// don't change this variable in the init process if (vgmstream->samples_into_block != 0)
vgmstream->xa_sector_length+=128; vgmstream->xa_sector_length += 0x80;
// We get to the end of a sector ? /* XA mode2/form2 sector
if(vgmstream->xa_sector_length==(18*128)) { * 0x00: sync word
vgmstream->xa_sector_length=0; * 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 :( /* submode flags (typical audio value = 0x64)
if (!vgmstream->xa_headerless) { * - 7: end of file
block_offset+=0x30; * - 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: begin:
// Search for selected channel & valid audio // Search for selected channel & valid audio
currentChannel=read_8bit(block_offset-7,vgmstream->ch[0].streamfile); currentChannel = read_8bit(block_offset-0x07,vgmstream->ch[0].streamfile);
subAudio=read_8bit(block_offset-6,vgmstream->ch[0].streamfile); subAudio = read_8bit(block_offset-0x06,vgmstream->ch[0].streamfile);
// audio is coded as 0x64 // audio is coded as 0x64
if(!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) { if (!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) {
// go to next sector // go to next sector
block_offset+=2352; block_offset += 0x930;
if(currentChannel!=-1) goto begin; if (currentChannel!=-1) goto begin;
} }
} }
} }
vgmstream->current_block_offset = block_offset; vgmstream->current_block_offset = block_offset;
// Quid : how to stop the current channel ??? // Quid : how to stop the current channel ???
// i set up 0 to current_block_size to make vgmstream not playing bad samples // i set up 0 to current_block_size to make vgmstream not playing bad samples
// another way to do it ??? // another way to do it ???
// (as the number of samples can be false in cd-xa due to multi-channels) // (as the number of samples can be false in cd-xa due to multi-channels)
vgmstream->current_block_size = (currentChannel==-1?0:112); vgmstream->current_block_size = (currentChannel==-1 ? 0 : 0x70);
vgmstream->next_block_offset = vgmstream->current_block_offset+128; vgmstream->next_block_offset = vgmstream->current_block_offset + 0x80;
for (i=0;i<vgmstream->channels;i++) { for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset; vgmstream->ch[i].offset = vgmstream->current_block_offset;
} }
} }

View File

@ -3,8 +3,7 @@
#include "../util.h" #include "../util.h"
/* .dsp w/ Cstr header, seen in Star Fox Assault and Donkey Konga */ /* .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; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];

View File

@ -1,16 +1,5 @@
#include "../vgmstream.h"
#include "meta.h" #include "meta.h"
#include "../util.h" #include "aax_streamfile.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);
struct utf_query 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 * init_vgmstream_aax(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileAAX = NULL; STREAMFILE * streamFileAAX = NULL;
STREAMFILE * streamFileADX = NULL; STREAMFILE * streamFileADX = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
@ -131,7 +119,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
int channel_count = 0, segment_count; int channel_count = 0, segment_count;
int sample_rate = 0; int sample_rate = 0;
int i; int i;
long aax_data_offset; long aax_data_offset;
@ -297,91 +285,6 @@ fail:
return NULL; 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 */ /* @UTF table reading, abridged */
static struct utf_query_result analyze_utf(STREAMFILE *infile, const long offset, const struct utf_query *query) 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 */ /* CRI's UTF wrapper around DSP */
VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
int table_error = 0; int table_error = 0;
@ -843,4 +745,3 @@ fail:
if (vgmstream) close_vgmstream(vgmstream); if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -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_ */

View File

@ -2,12 +2,13 @@
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#endif #endif
#include <math.h> #include <math.h>
#include <string.h>
#include <limits.h> #include <limits.h>
#include "meta.h"
#include "meta.h"
#include "adx_keys.h"
#include "../coding/coding.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); 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; 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 */ /* 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) 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; startoff=read_16bitBE(2, file)+4;
endoff=(read_32bitBE(12, file)+31)/32*18*read_8bit(7, file)+startoff; 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 */ /* try to guess key */
#define MAX_FRAMES (INT_MAX/0x8000) const adxkey_info * keys = NULL;
struct { uint16_t start, mult, add; } *keys = NULL;
int keycount = 0, keymask = 0; int keycount = 0, keymask = 0;
int scales_to_do; int scales_to_do;
int key_id; int key_id;
/* allocate storage for scales */ /* 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)); scales = malloc(scales_to_do*sizeof(uint16_t));
if (!scales) { if (!scales) {
goto find_key_cleanup; 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) if (type == 8)
{ {
keys = &keys_8; keys = adxkey8_list;
keycount = keys_8_count; keycount = adxkey8_list_count;
keymask = 0x6000; keymask = 0x6000;
} }
else if (type == 9) 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. * but the maximum value assigned by the encoder is 0x1000.
* This is written to the ADX file as 0xFFF, leaving the high bit * This is written to the ADX file as 0xFFF, leaving the high bit
* empty, which is used to validate a key */ * empty, which is used to validate a key */
keys = &keys_9; keys = adxkey9_list;
keycount = keys_9_count; keycount = adxkey9_list_count;
keymask = 0x1000; 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; uint16_t add = keys[key_id].add;
int i; 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<bruteframe && for (i=0;i<bruteframe &&
((prescales[i]&keymask)==(xor&keymask) || ((prescales[i]&keymask)==(xor&keymask) ||
prescales[i]==0); prescales[i]==0);

View File

@ -0,0 +1,330 @@
#ifndef _ADX_KEYS_H_
#define _ADX_KEYS_H_
/* Tests each start/mult/add vs derived key8/9 (if provided), as most where brute forced.
* Mainly for debugging purposes (info from VGAudio / ADX_Decoder) */
//#define ADX_VERIFY_DERIVED_KEYS 1
typedef struct {
uint16_t start,mult,add; /* XOR values derived from the actual key */
char* key8; /* keystring used by type 8 encryption */
uint64_t key9; /* keycode used by type 9 encryption */
} adxkey_info;
/**
* List of known keys, cracked from the sound files.
* Keystrings (type 8) and keycodes (type 9) from VGAudio / game's executables / 2ch.net.
* Multiple keys may work for a game due to how they are derived.
*/
static const adxkey_info adxkey8_list[] = {
/* Clover Studio (GOD HAND, Okami) */
{0x49e1,0x4a57,0x553d, "karaage",0},
/* Grasshopper Manufacture 0 (Blood+) */
{0x5f5d,0x58bd,0x55ed, NULL,0}, // estimated
/* Grasshopper Manufacture 1 (Killer7) */
{0x50fb,0x5803,0x5701, "GHM",0},
/* Grasshopper Manufacture 2 (Samurai Champloo) */
{0x4f3f,0x472f,0x562f, "GHMSC",0},
/* Moss Ltd (Raiden III) */
{0x66f5,0x58bd,0x4459, "(C)2005 MOSS LTD. BMW Z4",0},
/* Sonic Team 0 (Phantasy Star Universe) */
{0x5deb,0x5f27,0x673f, "3x5k62bg9ptbwy",0},
/* G.rev 0 (Senko no Ronde) */
{0x46d3,0x5ced,0x474d, "ranatus",0},
/* Sonic Team 1 (NiGHTS: Journey of Dreams) */
{0x440b,0x6539,0x5723, "sakakit4649",0},
/* unknown source */
{0x586d,0x5d65,0x63eb, NULL,0}, // from guessadx (unique?)
/* Navel (Shuffle! On the Stage (PS2)) */
{0x4969,0x5deb,0x467f, "SHUF",0},
/* Success (Aoishiro (PS2)) */
{0x4d65,0x5eb7,0x5dfd, "wakasugi",0},
/* Sonic Team 2 (Sonic and the Black Knight) */
{0x55b7,0x6191,0x5a77, "morio",0},
/* Enterbrain (Amagami) */
{0x5a17,0x509f,0x5bfd, "mituba",0}, /* also AHX key */
/* Yamasa (Yamasa Digi Portable: Matsuri no Tatsujin) */
{0x4c01,0x549d,0x676f, NULL,0}, // confirmed unique with guessadx
/* Kadokawa Shoten (Fragments Blue) */
{0x5803,0x4555,0x47bf, NULL,0}, // confirmed unique with guessadx
/* Namco (Soulcalibur IV) */
{0x59ed,0x4679,0x46c9, NULL,0}, // confirmed unique with guessadx
/* G.rev 1 (Senko no Ronde DUO) */
{0x6157,0x6809,0x4045, NULL,0}, // from guessadx
/* ASCII Media Works 0 (Nogizaka Haruka no Himitsu: Cosplay Hajimemashita) */
{0x45af,0x5f27,0x52b1, NULL,0}, // 2nd from guessadx, other was {0x45ad,0x5f27,0x10fd}
/* D3 Publisher 0 (Little Anchor) */
{0x5f65,0x5b3d,0x5f65, NULL,0}, // confirmed unique with guessadx
/* Marvelous 0 (Hanayoi Romanesque: Ai to Kanashimi) */
{0x5563,0x5047,0x43ed, NULL,0}, // 2nd from guessadx, other was {0x5562,0x5047,0x1433}
/* Capcom (Mobile Suit Gundam: Gundam vs. Gundam NEXT PLUS) */
{0x4f7b,0x4fdb,0x5cbf, "CS-GGNX+",0},
/* Developer: Bridge NetShop
* Publisher: Kadokawa Shoten (Shoukan Shoujo: Elemental Girl Calling) */
{0x4f7b,0x5071,0x4c61, NULL,0}, // confirmed unique with guessadx
/* Developer: Net Corporation
* Publisher: Tecmo (Rakushou! Pachi-Slot Sengen 6: Rio 2 Cruising Vanadis) */
{0x53e9,0x586d,0x4eaf, NULL,0}, // confirmed unique with guessadx
/* Developer: Aquaplus
* Tears to Tiara Gaiden Avalon no Kagi (PS3) */
{0x47e1,0x60e9,0x51c1, NULL,0}, // confirmed unique with guessadx
/* Developer: Broccoli
* Neon Genesis Evangelion: Koutetsu no Girlfriend 2nd (PS2) */
{0x481d,0x4f25,0x5243, NULL,0}, // confirmed unique with guessadx
/* Developer: Marvelous
* Futakoi Alternative (PS2) */
{0x413b,0x543b,0x57d1, NULL,0}, // confirmed unique with guessadx
/* Developer: Marvelous
* Gakuen Utopia - Manabi Straight! KiraKira Happy Festa! (PS2) */
{0x440b,0x4327,0x564b, "MANABIST",0},
/* Developer: Datam Polystar
* Soshite Kono Uchuu ni Kirameku Kimi no Shi XXX (PS2) */
{0x5f5d,0x552b,0x5507, NULL,0}, // confirmed unique with guessadx
/* Developer: Sega
* Sakura Taisen: Atsuki Chishio Ni (PS2) */
{0x645d,0x6011,0x5c29, NULL,0}, // confirmed unique with guessadx
/* Developer: Sega
* Sakura Taisen 3 ~Paris wa Moeteiru ka~ (PS2) */
{0x62ad,0x4b13,0x5957, NULL,0}, // confirmed unique with guessadx
/* Developer: Jinx
* Sotsugyou 2nd Generation (PS2) */
{0x6305,0x509f,0x4c01, NULL,0}, // First guess from guessadx, other was {0x6307,0x509f,0x2ac5}
/* La Corda d'Oro (2005)(-)(Koei)[PSP] */
{0x55b7,0x67e5,0x5387, NULL,0}, // confirmed unique with guessadx
/* Nanatsuiro * Drops Pure!! (2007)(Media Works)[PS2] */
{0x6731,0x645d,0x566b, NULL,0}, // confirmed unique with guessadx
/* Shakugan no Shana (2006)(Vridge)(Media Works)[PS2] */
{0x5fc5,0x63d9,0x599f, NULL,0}, // confirmed unique with guessadx
/* Uragiri wa Boku no Namae o Shitteiru (2010)(Kadokawa Shoten)[PS2] */
{0x4c73,0x4d8d,0x5827, NULL,0}, // confirmed unique with guessadx
/* StormLover Kai!! (2012)(D3 Publisher)[PSP] */
{0x5a11,0x67e5,0x6751, NULL,0}, // confirmed unique with guessadx
/* Sora no Otoshimono - DokiDoki Summer Vacation (2010)(Kadokawa Shoten)[PSP] */
{0x5e75,0x4a89,0x4c61, NULL,0}, // confirmed unique with guessadx
/* Boku wa Koukuu Kanseikan - Airport Hero Naha (2006)(Sonic Powered)(Electronic Arts)[PSP] */
{0x64ab,0x5297,0x632f, NULL,0}, // confirmed unique with guessadx
/* Lucky Star - Net Idol Meister (2009)(Kadokawa Shoten)[PSP] */
{0x4d82,0x5243,0x0685, NULL,0}, // confirmed unique with guessadx
/* Ishin Renka: Ryouma Gaiden (2010-11-25)(-)(D3 Publisher)[PSP] */
{0x54d1,0x526d,0x5e8b, NULL,0}, // ?
/* Lucky Star - Ryouou Gakuen Outousai Portable (2010-12-22)(-)(Kadokawa Shoten)[PSP] */
{0x4d06,0x663b,0x7d09, NULL,0}, // ?
/* Marriage Royale - Prism Story (2010-04-28)(-)(ASCII Media Works)[PSP] */
{0x40a9,0x46b1,0x62ad, NULL,0}, // ?
/* Nogizaka Haruka no Himitsu - Doujinshi Hajime Mashita (2010-10-28)(-)(ASCII Media Works)[PSP] */
{0x4601,0x671f,0x0455, NULL,0}, // ?
/* Slotter Mania P - Mach Go Go Go III (2011-01-06)(-)(Dorart)[PSP] */
{0x41ef,0x463d,0x5507, NULL,0}, // ?
/* Nichijou - Uchuujin (2011-07-28)(-)(Kadokawa Shoten)[PSP] */
{0x4369,0x486d,0x5461, NULL,0}, // ?
/* R-15 Portable (2011-10-27)(-)(Kadokawa Shoten)[PSP] */
{0x6809,0x5fd5,0x5bb1, NULL,0}, // ?
/* Suzumiya Haruhi-chan no Mahjong (2011-07-07)(-)(Kadokawa Shoten)[PSP] */
{0x5c33,0x4133,0x4ce7, NULL,0}, // ?
/* Storm Lover Natsu Koi!! (2011-08-04)(Vridge)(D3 Publisher)[PSP] */
{0x4133,0x5a01,0x5723, NULL,0}, // ?
};
static const adxkey_info adxkey9_list[] = {
/* Phantasy Star Online 2 */
{0x07d2,0x1ec5,0x0c7f, NULL,0}, // guessed with degod
/* Dragon Ball Z: Dokkan Battle */
{0x0003,0x0d19,0x043b, NULL,416383518}, // 0000000018D1821E
/* Kisou Ryouhei Gunhound EX (2013-01-31)(Dracue)[PSP] */
{0x0005,0x0bcd,0x1add, NULL,683461999}, // 0000000028BCCD6F
/* Raramagi (Android) */
{0x0000,0x2b99,0x3e33, NULL,45719322}, // 0000000002B99F1A (12160794 also works)
/* Sonic Runners (Android) */
{0x0000,0x12fd,0x1fbd, NULL,19910623}, // 00000000012FCFDF
/* Fallen Princess (iOS/Android) */
{0x5e4b,0x190d,0x76bb, NULL,145552191146490718}, // 02051AF25990FB5E
/* Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android) */
{0x3f10,0x3651,0x6d31, NULL,4867249871962584729}, // 438BF1F883653699
};
static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]);
static const int adxkey9_list_count = sizeof(adxkey9_list) / sizeof(adxkey9_list[0]);
#ifdef ADX_VERIFY_DERIVED_KEYS
/* used to derive keystrings, see VGAudio for how to calculate */
static const uint16_t key8_primes[0x400] = {
0x401B,0x4021,0x4025,0x402B,0x4031,0x403F,0x4043,0x4045,0x405D,0x4061,0x4067,0x406D,0x4087,0x4091,0x40A3,0x40A9,
0x40B1,0x40B7,0x40BD,0x40DB,0x40DF,0x40EB,0x40F7,0x40F9,0x4109,0x410B,0x4111,0x4115,0x4121,0x4133,0x4135,0x413B,
0x413F,0x4159,0x4165,0x416B,0x4177,0x417B,0x4193,0x41AB,0x41B7,0x41BD,0x41BF,0x41CB,0x41E7,0x41EF,0x41F3,0x41F9,
0x4205,0x4207,0x4219,0x421F,0x4223,0x4229,0x422F,0x4243,0x4253,0x4255,0x425B,0x4261,0x4273,0x427D,0x4283,0x4285,
0x4289,0x4291,0x4297,0x429D,0x42B5,0x42C5,0x42CB,0x42D3,0x42DD,0x42E3,0x42F1,0x4307,0x430F,0x431F,0x4325,0x4327,
0x4333,0x4337,0x4339,0x434F,0x4357,0x4369,0x438B,0x438D,0x4393,0x43A5,0x43A9,0x43AF,0x43B5,0x43BD,0x43C7,0x43CF,
0x43E1,0x43E7,0x43EB,0x43ED,0x43F1,0x43F9,0x4409,0x440B,0x4417,0x4423,0x4429,0x443B,0x443F,0x4445,0x444B,0x4451,
0x4453,0x4459,0x4465,0x446F,0x4483,0x448F,0x44A1,0x44A5,0x44AB,0x44AD,0x44BD,0x44BF,0x44C9,0x44D7,0x44DB,0x44F9,
0x44FB,0x4505,0x4511,0x4513,0x452B,0x4531,0x4541,0x4549,0x4553,0x4555,0x4561,0x4577,0x457D,0x457F,0x458F,0x45A3,
0x45AD,0x45AF,0x45BB,0x45C7,0x45D9,0x45E3,0x45EF,0x45F5,0x45F7,0x4601,0x4603,0x4609,0x4613,0x4625,0x4627,0x4633,
0x4639,0x463D,0x4643,0x4645,0x465D,0x4679,0x467B,0x467F,0x4681,0x468B,0x468D,0x469D,0x46A9,0x46B1,0x46C7,0x46C9,
0x46CF,0x46D3,0x46D5,0x46DF,0x46E5,0x46F9,0x4705,0x470F,0x4717,0x4723,0x4729,0x472F,0x4735,0x4739,0x474B,0x474D,
0x4751,0x475D,0x476F,0x4771,0x477D,0x4783,0x4787,0x4789,0x4799,0x47A5,0x47B1,0x47BF,0x47C3,0x47CB,0x47DD,0x47E1,
0x47ED,0x47FB,0x4801,0x4807,0x480B,0x4813,0x4819,0x481D,0x4831,0x483D,0x4847,0x4855,0x4859,0x485B,0x486B,0x486D,
0x4879,0x4897,0x489B,0x48A1,0x48B9,0x48CD,0x48E5,0x48EF,0x48F7,0x4903,0x490D,0x4919,0x491F,0x492B,0x4937,0x493D,
0x4945,0x4955,0x4963,0x4969,0x496D,0x4973,0x4997,0x49AB,0x49B5,0x49D3,0x49DF,0x49E1,0x49E5,0x49E7,0x4A03,0x4A0F,
0x4A1D,0x4A23,0x4A39,0x4A41,0x4A45,0x4A57,0x4A5D,0x4A6B,0x4A7D,0x4A81,0x4A87,0x4A89,0x4A8F,0x4AB1,0x4AC3,0x4AC5,
0x4AD5,0x4ADB,0x4AED,0x4AEF,0x4B07,0x4B0B,0x4B0D,0x4B13,0x4B1F,0x4B25,0x4B31,0x4B3B,0x4B43,0x4B49,0x4B59,0x4B65,
0x4B6D,0x4B77,0x4B85,0x4BAD,0x4BB3,0x4BB5,0x4BBB,0x4BBF,0x4BCB,0x4BD9,0x4BDD,0x4BDF,0x4BE3,0x4BE5,0x4BE9,0x4BF1,
0x4BF7,0x4C01,0x4C07,0x4C0D,0x4C0F,0x4C15,0x4C1B,0x4C21,0x4C2D,0x4C33,0x4C4B,0x4C55,0x4C57,0x4C61,0x4C67,0x4C73,
0x4C79,0x4C7F,0x4C8D,0x4C93,0x4C99,0x4CCD,0x4CE1,0x4CE7,0x4CF1,0x4CF3,0x4CFD,0x4D05,0x4D0F,0x4D1B,0x4D27,0x4D29,
0x4D2F,0x4D33,0x4D41,0x4D51,0x4D59,0x4D65,0x4D6B,0x4D81,0x4D83,0x4D8D,0x4D95,0x4D9B,0x4DB1,0x4DB3,0x4DC9,0x4DCF,
0x4DD7,0x4DE1,0x4DED,0x4DF9,0x4DFB,0x4E05,0x4E0B,0x4E17,0x4E19,0x4E1D,0x4E2B,0x4E35,0x4E37,0x4E3D,0x4E4F,0x4E53,
0x4E5F,0x4E67,0x4E79,0x4E85,0x4E8B,0x4E91,0x4E95,0x4E9B,0x4EA1,0x4EAF,0x4EB3,0x4EB5,0x4EC1,0x4ECD,0x4ED1,0x4ED7,
0x4EE9,0x4EFB,0x4F07,0x4F09,0x4F19,0x4F25,0x4F2D,0x4F3F,0x4F49,0x4F63,0x4F67,0x4F6D,0x4F75,0x4F7B,0x4F81,0x4F85,
0x4F87,0x4F91,0x4FA5,0x4FA9,0x4FAF,0x4FB7,0x4FBB,0x4FCF,0x4FD9,0x4FDB,0x4FFD,0x4FFF,0x5003,0x501B,0x501D,0x5029,
0x5035,0x503F,0x5045,0x5047,0x5053,0x5071,0x5077,0x5083,0x5093,0x509F,0x50A1,0x50B7,0x50C9,0x50D5,0x50E3,0x50ED,
0x50EF,0x50FB,0x5107,0x510B,0x510D,0x5111,0x5117,0x5123,0x5125,0x5135,0x5147,0x5149,0x5171,0x5179,0x5189,0x518F,
0x5197,0x51A1,0x51A3,0x51A7,0x51B9,0x51C1,0x51CB,0x51D3,0x51DF,0x51E3,0x51F5,0x51F7,0x5209,0x5213,0x5215,0x5219,
0x521B,0x521F,0x5227,0x5243,0x5245,0x524B,0x5261,0x526D,0x5273,0x5281,0x5293,0x5297,0x529D,0x52A5,0x52AB,0x52B1,
0x52BB,0x52C3,0x52C7,0x52C9,0x52DB,0x52E5,0x52EB,0x52FF,0x5315,0x531D,0x5323,0x5341,0x5345,0x5347,0x534B,0x535D,
0x5363,0x5381,0x5383,0x5387,0x538F,0x5395,0x5399,0x539F,0x53AB,0x53B9,0x53DB,0x53E9,0x53EF,0x53F3,0x53F5,0x53FB,
0x53FF,0x540D,0x5411,0x5413,0x5419,0x5435,0x5437,0x543B,0x5441,0x5449,0x5453,0x5455,0x545F,0x5461,0x546B,0x546D,
0x5471,0x548F,0x5491,0x549D,0x54A9,0x54B3,0x54C5,0x54D1,0x54DF,0x54E9,0x54EB,0x54F7,0x54FD,0x5507,0x550D,0x551B,
0x5527,0x552B,0x5539,0x553D,0x554F,0x5551,0x555B,0x5563,0x5567,0x556F,0x5579,0x5585,0x5597,0x55A9,0x55B1,0x55B7,
0x55C9,0x55D9,0x55E7,0x55ED,0x55F3,0x55FD,0x560B,0x560F,0x5615,0x5617,0x5623,0x562F,0x5633,0x5639,0x563F,0x564B,
0x564D,0x565D,0x565F,0x566B,0x5671,0x5675,0x5683,0x5689,0x568D,0x568F,0x569B,0x56AD,0x56B1,0x56D5,0x56E7,0x56F3,
0x56FF,0x5701,0x5705,0x5707,0x570B,0x5713,0x571F,0x5723,0x5747,0x574D,0x575F,0x5761,0x576D,0x5777,0x577D,0x5789,
0x57A1,0x57A9,0x57AF,0x57B5,0x57C5,0x57D1,0x57D3,0x57E5,0x57EF,0x5803,0x580D,0x580F,0x5815,0x5827,0x582B,0x582D,
0x5855,0x585B,0x585D,0x586D,0x586F,0x5873,0x587B,0x588D,0x5897,0x58A3,0x58A9,0x58AB,0x58B5,0x58BD,0x58C1,0x58C7,
0x58D3,0x58D5,0x58DF,0x58F1,0x58F9,0x58FF,0x5903,0x5917,0x591B,0x5921,0x5945,0x594B,0x594D,0x5957,0x595D,0x5975,
0x597B,0x5989,0x5999,0x599F,0x59B1,0x59B3,0x59BD,0x59D1,0x59DB,0x59E3,0x59E9,0x59ED,0x59F3,0x59F5,0x59FF,0x5A01,
0x5A0D,0x5A11,0x5A13,0x5A17,0x5A1F,0x5A29,0x5A2F,0x5A3B,0x5A4D,0x5A5B,0x5A67,0x5A77,0x5A7F,0x5A85,0x5A95,0x5A9D,
0x5AA1,0x5AA3,0x5AA9,0x5ABB,0x5AD3,0x5AE5,0x5AEF,0x5AFB,0x5AFD,0x5B01,0x5B0F,0x5B19,0x5B1F,0x5B25,0x5B2B,0x5B3D,
0x5B49,0x5B4B,0x5B67,0x5B79,0x5B87,0x5B97,0x5BA3,0x5BB1,0x5BC9,0x5BD5,0x5BEB,0x5BF1,0x5BF3,0x5BFD,0x5C05,0x5C09,
0x5C0B,0x5C0F,0x5C1D,0x5C29,0x5C2F,0x5C33,0x5C39,0x5C47,0x5C4B,0x5C4D,0x5C51,0x5C6F,0x5C75,0x5C77,0x5C7D,0x5C87,
0x5C89,0x5CA7,0x5CBD,0x5CBF,0x5CC3,0x5CC9,0x5CD1,0x5CD7,0x5CDD,0x5CED,0x5CF9,0x5D05,0x5D0B,0x5D13,0x5D17,0x5D19,
0x5D31,0x5D3D,0x5D41,0x5D47,0x5D4F,0x5D55,0x5D5B,0x5D65,0x5D67,0x5D6D,0x5D79,0x5D95,0x5DA3,0x5DA9,0x5DAD,0x5DB9,
0x5DC1,0x5DC7,0x5DD3,0x5DD7,0x5DDD,0x5DEB,0x5DF1,0x5DFD,0x5E07,0x5E0D,0x5E13,0x5E1B,0x5E21,0x5E27,0x5E2B,0x5E2D,
0x5E31,0x5E39,0x5E45,0x5E49,0x5E57,0x5E69,0x5E73,0x5E75,0x5E85,0x5E8B,0x5E9F,0x5EA5,0x5EAF,0x5EB7,0x5EBB,0x5ED9,
0x5EFD,0x5F09,0x5F11,0x5F27,0x5F33,0x5F35,0x5F3B,0x5F47,0x5F57,0x5F5D,0x5F63,0x5F65,0x5F77,0x5F7B,0x5F95,0x5F99,
0x5FA1,0x5FB3,0x5FBD,0x5FC5,0x5FCF,0x5FD5,0x5FE3,0x5FE7,0x5FFB,0x6011,0x6023,0x602F,0x6037,0x6053,0x605F,0x6065,
0x606B,0x6073,0x6079,0x6085,0x609D,0x60AD,0x60BB,0x60BF,0x60CD,0x60D9,0x60DF,0x60E9,0x60F5,0x6109,0x610F,0x6113,
0x611B,0x612D,0x6139,0x614B,0x6155,0x6157,0x615B,0x616F,0x6179,0x6187,0x618B,0x6191,0x6193,0x619D,0x61B5,0x61C7,
0x61C9,0x61CD,0x61E1,0x61F1,0x61FF,0x6209,0x6217,0x621D,0x6221,0x6227,0x623B,0x6241,0x624B,0x6251,0x6253,0x625F,
0x6265,0x6283,0x628D,0x6295,0x629B,0x629F,0x62A5,0x62AD,0x62D5,0x62D7,0x62DB,0x62DD,0x62E9,0x62FB,0x62FF,0x6305,
0x630D,0x6317,0x631D,0x632F,0x6341,0x6343,0x634F,0x635F,0x6367,0x636D,0x6371,0x6377,0x637D,0x637F,0x63B3,0x63C1,
0x63C5,0x63D9,0x63E9,0x63EB,0x63EF,0x63F5,0x6401,0x6403,0x6409,0x6415,0x6421,0x6427,0x642B,0x6439,0x6443,0x6449,
0x644F,0x645D,0x6467,0x6475,0x6485,0x648D,0x6493,0x649F,0x64A3,0x64AB,0x64C1,0x64C7,0x64C9,0x64DB,0x64F1,0x64F7,
0x64F9,0x650B,0x6511,0x6521,0x652F,0x6539,0x653F,0x654B,0x654D,0x6553,0x6557,0x655F,0x6571,0x657D,0x658D,0x658F,
0x6593,0x65A1,0x65A5,0x65AD,0x65B9,0x65C5,0x65E3,0x65F3,0x65FB,0x65FF,0x6601,0x6607,0x661D,0x6629,0x6631,0x663B,
0x6641,0x6647,0x664D,0x665B,0x6661,0x6673,0x667D,0x6689,0x668B,0x6695,0x6697,0x669B,0x66B5,0x66B9,0x66C5,0x66CD,
0x66D1,0x66E3,0x66EB,0x66F5,0x6703,0x6713,0x6719,0x671F,0x6727,0x6731,0x6737,0x673F,0x6745,0x6751,0x675B,0x676F,
0x6779,0x6781,0x6785,0x6791,0x67AB,0x67BD,0x67C1,0x67CD,0x67DF,0x67E5,0x6803,0x6809,0x6811,0x6817,0x682D,0x6839,
};
static void process_cri_key8(const char * key8, uint16_t * out_start, uint16_t * out_mult, uint16_t * out_add) {
size_t key_size;
uint16_t start = 0, mult = 0, add = 0;
int i;
if (key8 == NULL || key8[0] == '\0')
goto end;
key_size = strlen(key8);
start = key8_primes[0x100];
mult = key8_primes[0x200];
add = key8_primes[0x300];
for (i = 0; i < key_size; i++) {
char c = key8[i];
start = key8_primes[start * key8_primes[c + 0x80] % 0x400];
mult = key8_primes[mult * key8_primes[c + 0x80] % 0x400];
add = key8_primes[add * key8_primes[c + 0x80] % 0x400];
}
end:
*out_start = start;
*out_mult = mult;
*out_add = add;
}
static void process_cri_key9(uint64_t key9, uint16_t * out_start, uint16_t * out_mult, uint16_t * out_add) {
uint16_t start = 0, mult = 0, add = 0;
/* 0 is ignored by CRI's encoder, only from 1..18446744073709551615 */
if (key9 == 0)
goto end;
key9--;
start = (int)(((key9 >> 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_*/

View File

@ -8,7 +8,7 @@
/* Included primarily for 3DO */ /* Included primarily for 3DO */
/* for reading integers inexplicably packed into 80 bit floats */ /* 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]; uint8_t buf[10];
int32_t exponent; int32_t exponent;
int32_t mantissa; int32_t mantissa;
@ -31,7 +31,7 @@ uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) {
return mantissa*((buf[0]&0x80)?-1:1); 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) { int marker_id) {
uint16_t marker_count; uint16_t marker_count;
int i; int i;
@ -173,7 +173,7 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
interleave = 1; interleave = 1;
break; break;
case 0x41445034: /* ADP4 */ case 0x41445034: /* ADP4 */
coding_type = coding_DVI_IMA; coding_type = coding_DVI_IMA_int;
/* don't know how stereo DVI is laid out */ /* don't know how stereo DVI is laid out */
if (channel_count != 1) break; if (channel_count != 1) break;
break; break;

View File

@ -1,20 +1,7 @@
#include "../vgmstream.h"
#include "meta.h" #include "meta.h"
#include "../util.h" #include "aix_streamfile.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);
/* AIX - interleaved AAX, N segments per channels [SoulCalibur IV (PS3)] */
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
@ -61,7 +48,7 @@ VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
goto fail; goto fail;
sample_rate = read_32bitBE(stream_list_offset+8,streamFile); sample_rate = read_32bitBE(stream_list_offset+8,streamFile);
if (!check_sample_rate(sample_rate)) if (sample_rate < 300 || sample_rate > 96000)
goto fail; goto fail;
samples_in_segment = calloc(segment_count,sizeof(int32_t)); samples_in_segment = calloc(segment_count,sizeof(int32_t));
@ -228,190 +215,3 @@ fail:
} }
return NULL; 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;
}

View File

@ -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_ */

View File

@ -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); sample_rate = (uint16_t)read_16bit(offset + 0x0c + 0x10*ch + 0x0a,streamFile);
codec = read_8bit(offset + 0x0c + 0x10*ch + 0x0c, streamFile); codec = read_8bit(offset + 0x0c + 0x10*ch + 0x0c, streamFile);
/* validate as all channels should repeat this */ /* validate as all channels should repeat this (when channels is even and > 2 seems
if ((awc->num_samples && awc->num_samples != num_samples) || * 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->sample_rate && awc->sample_rate != sample_rate) ||
(awc->codec && awc->codec != codec)) { (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; goto fail;
} }

View File

@ -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;
}

View File

@ -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_ */

View File

@ -3,166 +3,166 @@
/* BCSTM - Nintendo 3DS format */ /* BCSTM - Nintendo 3DS format */
VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
coding_t coding_type; coding_t coding_type;
off_t info_offset = 0, seek_offset = 0, data_offset = 0; off_t info_offset = 0, seek_offset = 0, data_offset = 0;
uint16_t temp_id; uint16_t temp_id;
int codec_number; int codec_number;
int channel_count, loop_flag; int channel_count, loop_flag;
int i, ima = 0; int i, ima = 0;
off_t start_offset; off_t start_offset;
int section_count; int section_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
if ( !check_extensions(streamFile,"bcstm") ) if ( !check_extensions(streamFile,"bcstm") )
goto fail; goto fail;
/* check header */ /* check header */
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */ if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */
goto fail; 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 (info_offset == 0) goto fail;
if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */ if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */
goto fail; 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) { /* check type details */
case 0: codec_number = read_8bit(info_offset + 0x20, streamFile);
coding_type = coding_PCM8; loop_flag = read_8bit(info_offset + 0x21, streamFile);
break; channel_count = read_8bit(info_offset + 0x22, streamFile);
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;
}
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 */ if (channel_count < 1) goto fail;
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* build the VGMSTREAM */
vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile); vgmstream = allocate_vgmstream(channel_count, loop_flag);
vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile); if (!vgmstream) goto fail;
/* 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; /* fill in the vital statistics */
if (channel_count == 1) vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile);
vgmstream->layout_type = layout_none; vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile);
else /* 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
if (ima) {
vgmstream->layout_type = layout_interleave; vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
else if (vgmstream->loop_start_sample > 10000)
vgmstream->layout_type = layout_interleave_shortblock; {
} vgmstream->loop_start_sample -= 5000;
vgmstream->meta_type = meta_CSTM; vgmstream->loop_end_sample = vgmstream->num_samples - 5000;
}
if (ima) else
vgmstream->interleave_block_size = 0x200; vgmstream->loop_end_sample = vgmstream->num_samples;
else { }
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile); else
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile); {
} vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
if (vgmstream->coding_type == coding_NGC_DSP) { }
off_t coef_offset;
off_t tempoffset = info_offset; vgmstream->coding_type = coding_type;
int foundcoef = 0; if (channel_count == 1)
int i, j; vgmstream->layout_type = layout_none;
int coef_spacing = 0x2E; else
{
while (!(foundcoef)) if (ima)
{ vgmstream->layout_type = layout_interleave;
if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102) else
{ vgmstream->layout_type = layout_interleave_shortblock;
coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset; }
foundcoef++; vgmstream->meta_type = meta_CSTM;
break;
} if (ima)
tempoffset++; 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; j<vgmstream->channels; 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; j<vgmstream->channels; 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 */ /* open the file for reading by each channel */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))

View File

@ -1,12 +1,11 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h"
/* BGW - from Final Fantasy XI (PC) music files /* BGW - from Final Fantasy XI (PC) music files */
* Some info from POLUtils */
VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; 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; int32_t loop_start;
uint8_t block_align;
off_t start_offset; off_t start_offset;
int channel_count, loop_flag = 0; int channel_count, loop_flag = 0;
@ -22,11 +21,11 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
goto fail; goto fail;
codec = read_32bitLE(0x0c,streamFile); codec = read_32bitLE(0x0c,streamFile);
filesize = read_32bitLE(0x10,streamFile); file_size = read_32bitLE(0x10,streamFile);
/*file_id = read_32bitLE(0x14,streamFile);*/ /*file_id = read_32bitLE(0x14,streamFile);*/
blocksize = read_32bitLE(0x18,streamFile); block_size = read_32bitLE(0x18,streamFile);
loop_start = read_32bitLE(0x1c,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); start_offset = read_32bitLE(0x28,streamFile);
/*0x2c: unk (vol?) */ /*0x2c: unk (vol?) */
/*0x2d: unk (0x10?) */ /*0x2d: unk (0x10?) */
@ -35,7 +34,7 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
/* check file size with header value */ /* check file size with header value */
if (filesize != get_streamfile_size(streamFile)) if (file_size != get_streamfile_size(streamFile))
goto fail; goto fail;
loop_flag = (loop_start > 0); loop_flag = (loop_start > 0);
@ -54,15 +53,46 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */ 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) { if (loop_flag) {
vgmstream->loop_start_sample = (loop_start-1) * block_align; vgmstream->loop_start_sample = (loop_start-1) * block_align;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
} }
break; 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: default:
goto fail; goto fail;
} }
@ -82,9 +112,8 @@ fail:
/* SPW (SEWave) - from PlayOnline viewer for Final Fantasy XI (PC) */ /* SPW (SEWave) - from PlayOnline viewer for Final Fantasy XI (PC) */
VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; 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; int32_t loop_start;
uint8_t block_align;
off_t start_offset; off_t start_offset;
int channel_count, loop_flag = 0; 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)) if (read_32bitLE(0x8,streamFile) != get_streamfile_size(streamFile))
goto fail; goto fail;
filesize = read_32bitLE(0x08,streamFile); file_size = read_32bitLE(0x08,streamFile);
codec = read_32bitLE(0x0c,streamFile); codec = read_32bitLE(0x0c,streamFile);
/*file_id = read_32bitLE(0x10,streamFile);*/ /*file_id = read_32bitLE(0x10,streamFile);*/
blocksize = read_32bitLE(0x14,streamFile); block_size = read_32bitLE(0x14,streamFile);
loop_start = read_32bitLE(0x18,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); start_offset = read_32bitLE(0x24,streamFile);
/*0x2c: unk (0x00?) */ /*0x2c: unk (0x00?) */
/*0x2d: unk (0x00/01?) */ /*0x2d: unk (0x00/01?) */
@ -116,7 +145,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
/*0x2c: unk (0x01 when PCM, 0x10 when VAG?) */ /*0x2c: unk (0x01 when PCM, 0x10 when VAG?) */
/* check file size with header value */ /* check file size with header value */
if (filesize != get_streamfile_size(streamFile)) if (file_size != get_streamfile_size(streamFile))
goto fail; goto fail;
loop_flag = (loop_start > 0); loop_flag = (loop_start > 0);
@ -135,7 +164,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */ 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) { if (loop_flag) {
vgmstream->loop_start_sample = (loop_start-1) * block_align;; vgmstream->loop_start_sample = (loop_start-1) * block_align;;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
@ -148,7 +177,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02; vgmstream->interleave_block_size = 0x02;
vgmstream->num_samples = blocksize; vgmstream->num_samples = block_size;
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = (loop_start-1); vgmstream->loop_start_sample = (loop_start-1);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;

View File

@ -1,243 +1,96 @@
#include "meta.h" #include "meta.h"
#include "../layout/layout.h" #include "../coding/coding.h"
#include "../util.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 * init_vgmstream_bnsf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; 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; if (!check_extensions(streamFile,"bnsf"))
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)))
{
goto fail; goto fail;
} if (read_32bitBE(0,streamFile) != 0x424E5346) /* "BNSF" */
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x424E5346) /* BNSF */
goto fail; goto fail;
/* check form */ codec = read_32bitBE(0x08,streamFile);
bnsf_form = read_32bitBE(8,streamFile);
switch (bnsf_form) /* check RIFF size (for siren22 it's full size) */
{ if (read_32bitBE(0x04,streamFile) + (codec == 0x49533232 ? 0 : 8) != get_streamfile_size(streamFile))
#ifdef VGM_USE_G7221 goto fail;
case form_IS14:
break; if (!find_chunk_be(streamFile, 0x73666d74,first_offset,0, &sfmt_chunk,NULL)) /* "sfmt" */
#endif goto fail;
#ifdef VGM_USE_G719 if (!find_chunk_be(streamFile, 0x73646174,first_offset,0, &sdat_chunk,&sdat_size)) /* "sdat" */
case form_IS22: goto fail;
RiffSizeExtra = 0; if ( find_chunk_be(streamFile, 0x6C6F6F70,first_offset,0, &loop_chunk,NULL)) { /* "loop" */
break; loop_flag = 1;
#endif loop_start = read_32bitBE(loop_chunk+0x00, streamFile);
default: loop_end = read_32bitBE(loop_chunk+0x04,streamFile);
goto fail;
} }
riff_size = read_32bitBE(4,streamFile); subcodec = read_16bitBE(sfmt_chunk+0x00,streamFile);
file_size = get_streamfile_size(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 */ start_offset = sdat_chunk;
if (file_size < riff_size+RiffSizeExtra) goto fail;
/* 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 */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = sample_rate; 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->layout_type = layout_interleave;
vgmstream->interleave_block_size = block_size/channel_count; vgmstream->interleave_block_size = block_size/channel_count;
if (loop_flag) { /* some IS14 voice files have 0x02 (Tales of Zestiria, The Idolm@ster 2); data looks normal and silent
vgmstream->loop_start_sample = loop_start; * frames decode ok but rest fails, must be some subtle decoding variation (not encryption) */
vgmstream->loop_end_sample = loop_end; if (subcodec != 0)
} goto fail;
vgmstream->meta_type = meta_BNSF;
switch (codec) {
#ifdef VGM_USE_G7221 #ifdef VGM_USE_G7221
if (coding_G7221C == coding_type) case 0x49533134: /* "IS14" */
{ vgmstream->coding_type = coding_G7221C;
int i; vgmstream->codec_data = init_g7221(vgmstream->channels, vgmstream->interleave_block_size);
g7221_codec_data *data; if (!vgmstream->codec_data) goto fail;
/* one data structure per channel */ break;
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 */
}
}
}
#endif #endif
#ifdef VGM_USE_G719 #ifdef VGM_USE_G719
if (coding_G719 == coding_type) case 0x49533232: /* "IS22" */
{ vgmstream->coding_type = coding_G719;
int i; vgmstream->codec_data = init_g719(vgmstream->channels, vgmstream->interleave_block_size);
g719_codec_data *data; if (!vgmstream->codec_data) goto fail;
/* one data structure per channel */ break;
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 */
}
}
}
#endif #endif
default:
/* open the file, set up each channel */ goto fail;
{
int i;
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset =
start_offset+i*vgmstream->interleave_block_size;
}
} }
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -1,40 +1,35 @@
#include "meta.h" #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 * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag, channel_count;
int loop_flag; /* check extension (.dvi: original, .idvi: renamed to header id) */
int channel_count; if ( !check_extensions(streamFile,"dvi,idvi") )
/* 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." */
goto fail; goto fail;
loop_flag = read_32bitLE(0x0C,streamFile); /* check header */
channel_count = read_32bitLE(0x04,streamFile); 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 */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
start_offset = 0x800;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile); 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->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; vgmstream->meta_type = meta_DC_IDVI;
/* Calculating the short block... */ /* Calculating the short block... */
@ -47,24 +42,10 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
} }
/* open the file for reading */ /* open the file for reading */
{ if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
int i; goto fail;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;

View File

@ -1,65 +1,42 @@
#include "meta.h" #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; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag, channel_count;
int loop_flag = 0; /* check extension (.pcm: original, .kcey: renamed to header id) */
int channel_count; if ( !check_extensions(streamFile,"pcm,kcey") )
/* 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." */
goto fail; 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); channel_count = read_32bitBE(0x08,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
start_offset = read_32bitBE(0x10,streamFile);
vgmstream->sample_rate = 37800; vgmstream->sample_rate = 37800;
vgmstream->coding_type = coding_EACS_IMA;
vgmstream->num_samples = read_32bitBE(0x0C,streamFile); vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
if (loop_flag) { 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->layout_type = layout_none;
vgmstream->meta_type = meta_KCEY; vgmstream->meta_type = meta_DC_KCEY;
vgmstream->get_high_nibble=1;
/* 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;i<channel_count;i++) {
vgmstream->ch[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; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;

View File

@ -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;i<channel_count;i++) {
vgmstream->ch[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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;i<channel_count;i++) {
vgmstream->ch[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_offset<get_streamfile_size(streamFile)-8);
// Reset values ...
// setting up the first header by calling the eacs_block_update sub
if(little_endian)
vgmstream->next_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;
}

View File

@ -140,7 +140,7 @@ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) {
goto fail; goto fail;
/* use header size as endianness flag */ /* 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_32bit = read_32bitBE;
read_16bit = read_16bitBE; read_16bit = read_16bitBE;
} else { } else {
@ -250,7 +250,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
} }
} }
else { else {
vgmstream->layout_type = layout_ea_blocked; vgmstream->layout_type = layout_blocked_ea_schl;
} }
if (is_bnk) if (is_bnk)
@ -311,14 +311,12 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case EA_CODEC2_LAYER2: /* MPEG Layer II, aka MP2 */ case EA_CODEC2_LAYER2: /* MPEG Layer II, aka MP2 */
case EA_CODEC2_LAYER3: { /* MPEG Layer III, aka MP3 */ 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 ? off_t mpeg_start_offset = is_bnk ?
start_offset : start_offset :
get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea); get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea);
if (!mpeg_start_offset) goto fail; 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 */ /* 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); 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; 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 */ case EA_CODEC2_EALAYER3: { /* MP3 variant */
mpeg_custom_config cfg; mpeg_custom_config cfg = {0};
off_t mpeg_start_offset = is_bnk ? off_t mpeg_start_offset = is_bnk ?
start_offset : start_offset :
get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea); get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea);
if (!mpeg_start_offset) goto fail; 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 */ /* 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); 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; 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_MT10: /* MicroTalk (10:1 compression) */
case EA_CODEC2_MT5: /* MicroTalk (5: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 */ case EA_CODEC2_ATRAC3PLUS: /* regular ATRAC3plus chunked in SCxx blocks, including RIFF header */
default: default:
VGM_LOG("EA SCHl: unknown codec2 0x%02x for platform 0x%02x\n", ea->codec2, ea->platform); 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; 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;i<vgmstream->channels;i++) {
vgmstream->ch[i].channel_start_offset = 0;
}
}
} }
else { else {
/* setup first block to update offsets */ /* setup first block to update offsets */
ea_schl_block_update(start_offset,vgmstream); block_update_ea_schl(start_offset,vgmstream);
} }

View File

@ -58,7 +58,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_EA_SCHL_fixed; vgmstream->meta_type = meta_EA_SCHL_fixed;
vgmstream->layout_type = layout_ea_blocked; vgmstream->layout_type = layout_blocked_ea_schl;
switch (ea.codec) { switch (ea.codec) {
case EA_CODEC_PCM: case EA_CODEC_PCM:
@ -66,7 +66,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
break; break;
case EA_CODEC_IMA: case EA_CODEC_IMA:
vgmstream->coding_type = coding_EACS_IMA; vgmstream->coding_type = coding_DVI_IMA; /* stereo/mono, high nibble first */
break; break;
default: default:
@ -80,7 +80,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
goto fail; goto fail;
/* setup first block to update offsets */ /* setup first block to update offsets */
ea_schl_block_update(start_offset,vgmstream); block_update_ea_schl(start_offset,vgmstream);
return vgmstream; return vgmstream;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */ /* 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, 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 /* 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. */ * 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) { else if (fsbh.mode & FSOUND_GCADPCM) {
/* FSB3: ?; FSB4: de Blob (Wii), Night at the Museum, M. Night Shyamalan Avatar: The Last Airbender */ /* FSB3: ?; FSB4: de Blob (Wii), Night at the Museum, M. Night Shyamalan Avatar: The Last Airbender */
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_interleave_byte; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x2; vgmstream->interleave_block_size = 0x2;
dsp_read_coefs_be(vgmstream, streamFile, custom_data_offset, 0x2e); 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) */ /* full channel interleave, used in short streams (ex. de Blob Wii SFXs) */
if (fsbh.numchannels > 1 && (fsbh.flags & FMOD_FSB_SOURCE_NOTINTERLEAVED)) { 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->layout_type = layout_interleave;
vgmstream->interleave_block_size = fsbh.lengthcompressedbytes / fsbh.numchannels; vgmstream->interleave_block_size = fsbh.lengthcompressedbytes / fsbh.numchannels;
} }

View File

@ -193,27 +193,22 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
goto fail; goto fail;
case 0x01: /* FMOD_SOUND_FORMAT_PCM8 [Anima - Gate of Memories (PC)] */ 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->layout_type = ChannelCount == 1 ? layout_none : layout_interleave;
vgmstream->interleave_block_size = 0x01; vgmstream->interleave_block_size = 0x01;
vgmstream->coding_type = coding_PCM8_U;
break; break;
case 0x02: /* FMOD_SOUND_FORMAT_PCM16 */ 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->coding_type = coding_PCM16LE;
vgmstream->layout_type = ChannelCount == 1 ? layout_none : layout_interleave;
vgmstream->interleave_block_size = 0x02;
break; break;
case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */ case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */
goto fail; goto fail; /* not used */
case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */ case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */
goto fail; goto fail; /* not used */
case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima - Gate of Memories (PC)] */ case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima - Gate of Memories (PC)] */
vgmstream->coding_type = coding_PCMFLOAT; vgmstream->coding_type = coding_PCMFLOAT;
@ -222,31 +217,25 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
break; break;
case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM [Sonic Boom - Fire and Ice (3DS)] */ case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM [Sonic Boom - Fire and Ice (3DS)] */
if (ChannelCount == 1) { vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
} else { vgmstream->interleave_block_size = 0x02;
vgmstream->layout_type = layout_interleave_byte;
vgmstream->interleave_block_size = 0x02;
}
dsp_read_coefs_be(vgmstream,streamFile,DSPInfoStart,0x2E); dsp_read_coefs_be(vgmstream,streamFile,DSPInfoStart,0x2E);
vgmstream->coding_type = coding_NGC_DSP;
break; break;
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */ case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */
vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX;
vgmstream->layout_type = layout_none; 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; break;
case 0x08: /* FMOD_SOUND_FORMAT_VAG */ case 0x08: /* FMOD_SOUND_FORMAT_VAG */
goto fail; goto fail; /* not used */
case 0x09: /* FMOD_SOUND_FORMAT_HEVAG */ case 0x09: /* FMOD_SOUND_FORMAT_HEVAG */
vgmstream->coding_type = coding_HEVAG;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->coding_type = coding_HEVAG;
break; break;
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
@ -270,9 +259,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case 0x0B: {/* FMOD_SOUND_FORMAT_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 */ 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); 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 #ifdef VGM_USE_VORBIS
case 0x0F: {/* FMOD_SOUND_FORMAT_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.channels = vgmstream->channels;
cfg.sample_rate = vgmstream->sample_rate; cfg.sample_rate = vgmstream->sample_rate;
cfg.setup_id = VorbisSetupId; cfg.setup_id = VorbisSetupId;

View File

@ -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_start_sample = read_32bitBE(offset+0x14, streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_interleave_byte; vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_KT_WIIBGM;
vgmstream->interleave_block_size = 0x1; vgmstream->interleave_block_size = 0x1;
vgmstream->meta_type = meta_KT_WIIBGM;
dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60); dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60);
start_offset = offset+0x800; start_offset = offset+0x800;
@ -101,7 +100,7 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t
goto fail; goto fail;
return vgmstream; return vgmstream;
fail: fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -3,6 +3,8 @@
#include "../layout/layout.h" #include "../layout/layout.h"
#include "../util.h" #include "../util.h"
/* known GENH types */ /* known GENH types */
typedef enum { typedef enum {
PSX = 0, /* PSX ADPCM */ PSX = 0, /* PSX ADPCM */
@ -28,26 +30,45 @@ typedef enum {
XMA1 = 20, /* raw XMA1 */ XMA1 = 20, /* raw XMA1 */
XMA2 = 21, /* raw XMA2 */ XMA2 = 21, /* raw XMA2 */
FFMPEG = 22, /* any headered FFmpeg format */ FFMPEG = 22, /* any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
} genh_type; } 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 */ /* GENH is an artificial "generic" header for headerless streams */
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
genh_header genh = {0};
int channel_count, loop_flag, sample_rate, interleave; coding_t coding;
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;
int i, j; int i, j;
coding_t coding;
genh_type type;
/* check extension, case insensitive */ /* check extension, case insensitive */
if (!check_extensions(streamFile,"genh")) goto fail; if (!check_extensions(streamFile,"genh")) goto fail;
@ -55,12 +76,13 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* check header magic */ /* check header magic */
if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail; if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;
channel_count = read_32bitLE(0x4,streamFile); /* process the header */
if (channel_count < 1) goto fail; if (!parse_genh(streamFile, &genh))
goto fail;
type = read_32bitLE(0x18,streamFile);
/* type to coding conversion */ /* type to coding conversion */
switch (type) { switch (genh.codec) {
case PSX: coding = coding_PSX; break; case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX; break; case XBOX: coding = coding_XBOX; break;
case NGC_DTK: coding = coding_NGC_DTK; break; case NGC_DTK: coding = coding_NGC_DTK; break;
@ -86,68 +108,27 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case ATRAC3PLUS: case ATRAC3PLUS:
case XMA1: case XMA1:
case XMA2: case XMA2:
case AC3:
case FFMPEG: coding = coding_FFmpeg; break; case FFMPEG: coding = coding_FFmpeg; break;
#endif #endif
default: default:
goto fail; 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 */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(genh.channels,genh.loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = genh.sample_rate;
vgmstream->num_samples = num_samples; vgmstream->num_samples = genh.num_samples;
vgmstream->loop_start_sample = loop_start; vgmstream->loop_start_sample = genh.loop_start_sample;
vgmstream->loop_end_sample = loop_end; vgmstream->loop_end_sample = genh.loop_end_sample;
/* codec specific */ /* codec specific */
switch (coding) { switch (coding) {
case coding_PCM8_U_int: case coding_PCM8_U_int:
vgmstream->layout_type=layout_none; vgmstream->layout_type = layout_none;
break; break;
case coding_PCM16LE: case coding_PCM16LE:
case coding_PCM16BE: case coding_PCM16BE:
@ -160,14 +141,14 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case coding_IMA: case coding_IMA:
case coding_AICA: case coding_AICA:
case coding_APPLE_IMA4: case coding_APPLE_IMA4:
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = genh.interleave;
if (channel_count > 1) if (vgmstream->channels > 1)
{ {
if (coding == coding_SDX2) { if (coding == coding_SDX2) {
coding = coding_SDX2_int; 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; vgmstream->layout_type = layout_none;
} }
else { else {
@ -179,7 +160,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
} }
/* to avoid endless loops */ /* to avoid endless loops */
if (!interleave && ( if (!genh.interleave && (
coding == coding_PSX || coding == coding_PSX ||
coding == coding_PSX_badflags || coding == coding_PSX_badflags ||
coding == coding_IMA_int || coding == coding_IMA_int ||
@ -194,64 +175,62 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* setup adpcm */ /* setup adpcm */
if (coding == coding_AICA) { if (coding == coding_AICA) {
int i; int i;
for (i=0;i<channel_count;i++) { for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].adpcm_step_index = 0x7f; vgmstream->ch[i].adpcm_step_index = 0x7f;
} }
} }
break; break;
case coding_MS_IMA: 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; vgmstream->layout_type = layout_none;
break; break;
case coding_MSADPCM: case coding_MSADPCM:
if (channel_count > 2) goto fail; if (vgmstream->channels > 2) goto fail;
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; vgmstream->layout_type = layout_none;
break; break;
case coding_XBOX: case coding_XBOX:
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
break; break;
case coding_NGC_DTK: case coding_NGC_DTK:
if (channel_count != 2) goto fail; if (vgmstream->channels != 2) goto fail;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
break; break;
case coding_NGC_DSP: case coding_NGC_DSP:
if (dsp_interleave_type == 0) { if (genh.coef_interleave_type == 0) {
if (!interleave) goto fail; if (!genh.interleave) goto fail;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = genh.interleave;
} else if (dsp_interleave_type == 1) { } else if (genh.coef_interleave_type == 1) {
if (!interleave) goto fail; if (!genh.interleave) goto fail;
vgmstream->layout_type = layout_interleave_byte; coding = coding_NGC_DSP_subint;
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = genh.interleave;
} else if (dsp_interleave_type == 2) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
} } else if (genh.coef_interleave_type == 2) {
vgmstream->layout_type = layout_none;
}// else {
// goto fail;
//}
/* get coefs */ /* get coefs */
for (i=0;i<channel_count;i++) { for (i=0;i<vgmstream->channels;i++) {
int16_t (*read_16bit)(off_t , STREAMFILE*); int16_t (*read_16bit)(off_t , STREAMFILE*) = genh.coef_big_endian ? read_16bitBE : read_16bitLE;
/* bit 1 - little endian coefs */
if ((coef_type & 2) == 0) {
read_16bit = read_16bitBE;
} else {
read_16bit = read_16bitLE;
}
/* bit 0 - split coefs (2 arrays) */ /* normal/split coefs bit flag */
if ((coef_type & 1) == 0) { if ((genh.coef_type & 1) == 0) { /* not set: normal coefs, all 16 interleaved into one array */
for (j=0;j<16;j++) { 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++) { 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]=read_16bit(genh.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+1]=read_16bit(genh.coef_splitted[i]+j*2,streamFile);
} }
} }
} }
@ -260,7 +239,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case coding_MPEG_layer3: case coding_MPEG_layer3:
vgmstream->layout_type = layout_none; 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; if (!vgmstream->codec_data) goto fail;
break; break;
@ -269,50 +248,53 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case coding_FFmpeg: { case coding_FFmpeg: {
ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_codec_data *ffmpeg_data = NULL;
if (type == FFMPEG) { if (genh.codec == FFMPEG || genh.codec == AC3) {
/* default FFmpeg */ /* 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 ( !ffmpeg_data ) goto fail;
//if (vgmstream->num_samples == 0)
// vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */
} }
else { else {
/* fake header FFmpeg */ /* fake header FFmpeg */
uint8_t buf[200]; uint8_t buf[200];
int32_t bytes; int32_t bytes;
if (type == ATRAC3) { if (genh.codec == ATRAC3) {
int block_size = interleave; int block_size = genh.interleave;
int joint_stereo; int joint_stereo;
switch(atrac3_mode) { switch(genh.codec_mode) {
case 0: joint_stereo = vgmstream->channels > 1 && interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */ 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 1: joint_stereo = 1; break; /* force joint stereo */
case 2: joint_stereo = 0; break; /* force stereo */ case 2: joint_stereo = 0; break; /* force stereo */
default: goto fail; 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) { else if (genh.codec == ATRAC3PLUS) {
int block_size = interleave; 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) { else if (genh.codec == XMA1) {
int xma_stream_mode = xma_mode == 1 ? 1 : 0; 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) { else if (genh.codec == XMA2) {
int block_size = interleave ? interleave : 2048; int block_size = genh.interleave ? genh.interleave : 2048;
int block_count = datasize / block_size; 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 { else {
goto fail; goto fail;
} }
if (bytes <= 0) 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; if ( !ffmpeg_data ) goto fail;
} }
@ -320,8 +302,8 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* force encoder delay */ /* force encoder delay */
if (skip_samples_mode && skip_samples >= 0) { if (genh.skip_samples_mode && genh.skip_samples >= 0) {
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples); ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
} }
break; break;
@ -335,7 +317,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_GENH; vgmstream->meta_type = meta_GENH;
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) if ( !vgmstream_open_stream(vgmstream,streamFile,genh.start_offset) )
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -344,3 +326,60 @@ fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; 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;
}

View File

@ -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;
}

View File

@ -155,7 +155,6 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe
f++; 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) { if (min_clip_count < 0 || clip_count < min_clip_count) {
min_clip_count = clip_count; min_clip_count = clip_count;
best_key2 = key2; 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); read_streamfile(buffer, hca_data->start, header_size, hca_data->streamfile);
end: 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_key2 = best_key2;
*out_key1 = best_key1; *out_key1 = best_key1;
free(testbuf);//free(temp); free(testbuf);//free(temp);

View File

@ -12,7 +12,7 @@ typedef struct {
*/ */
static const hcakey_info hcakey_list[] = { static const hcakey_info hcakey_list[] = {
// HCA Decoder default // CRI HCA decoder default
{9621963164387704}, // CF222F1FE0748978 {9621963164387704}, // CF222F1FE0748978
// Phantasy Star Online 2 (multi?) // Phantasy Star Online 2 (multi?)
@ -28,7 +28,13 @@ static const hcakey_info hcakey_list[] = {
// Ro-Kyu-Bu! Himitsu no Otoshimono (PSP) // Ro-Kyu-Bu! Himitsu no Otoshimono (PSP)
{2012082716}, // 0000000077EDF21C {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 {1234253142}, // 0000000049913556
// Idolm@ster Cinderella Stage (iOS/Android) // Idolm@ster Cinderella Stage (iOS/Android)
@ -99,18 +105,45 @@ static const hcakey_info hcakey_list[] = {
// World Chain (iOS/Android) // World Chain (iOS/Android)
{4892292804961027794}, // 43E4EA62B8E6C6D2 {4892292804961027794}, // 43E4EA62B8E6C6D2
// Yuyuyui (iOS/Android) *unconfirmed // Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android)
{4867249871962584729}, // 438BF1F883653699 {4867249871962584729}, // 438BF1F883653699
// Tekken Mobile (iOS/Android) // Tekken Mobile (iOS/Android)
{0xFFFFFFFFFFFFFFFF}, // {0xFFFFFFFFFFFFFFFF}, // FFFFFFFFFFFFFFFF / 18446744073709551615
// Tales of the Rays (iOS/Android) // Tales of the Rays (iOS/Android)
{9516284}, // 00000000009134FC {9516284}, // 00000000009134FC
// Skylock - Kamigami to Unmei no Itsutsuko [iOS] // Skylock - Kamigami to Unmei no Itsutsuko (iOS/Android)
{49160768297}, // 0000000B7235CB29 {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
}; };

View File

@ -38,7 +38,7 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) {
vgmstream->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile); vgmstream->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile);
vgmstream->coding_type = coding_IMA_int; vgmstream->coding_type = coding_IMA_int;
vgmstream->layout_type = layout_ivaud_blocked; vgmstream->layout_type = layout_blocked_ivaud;
vgmstream->meta_type = meta_PC_IVAUD; vgmstream->meta_type = meta_PC_IVAUD;
/* open the file for reading */ /* open the file for reading */
@ -57,7 +57,7 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) {
// to avoid troubles with "extra" samples // to avoid troubles with "extra" samples
vgmstream->num_samples=((read_32bitLE(0x60,streamFile)/2)*2); vgmstream->num_samples=((read_32bitLE(0x60,streamFile)/2)*2);
ivaud_block_update(start_offset,vgmstream); block_update_ivaud(start_offset,vgmstream);
return vgmstream; return vgmstream;

View File

@ -5,7 +5,7 @@
VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count, i; int loop_flag, channel_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
if (!check_extensions(streamFile,"xa")) if (!check_extensions(streamFile,"xa"))
@ -18,30 +18,22 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
loop_flag = 0; loop_flag = 0;
channel_count = read_16bitLE(0x0A,streamFile); channel_count = read_16bitLE(0x0A,streamFile);
start_offset = 0x18;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
start_offset = 0x18;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
vgmstream->coding_type = coding_MAXIS_XA;
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count; vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_MAXIS_XA; vgmstream->meta_type = meta_MAXIS_XA;
vgmstream->coding_type = coding_MAXIS_XA;
vgmstream->layout_type = layout_none;
/* open streams */ /* open streams */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail; 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; return vgmstream;
fail: fail:

View File

@ -15,7 +15,7 @@ VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_brstm(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); 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_ngc_str(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_vpk(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_nwa(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_eacs(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_xss(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_rws(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_fsb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_fsb(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_fsb5(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_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_bg00(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_kcey(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_dc_kcey(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ps2_rstm(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_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); 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_capdsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_xbox_matx(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); 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_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_idsp2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_idsp3(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_idsp3(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_idsp4(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_idsp4(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_ymf(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_naomi_spsd(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ps2_ass(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_wii_smp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_thp(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_nds_rrds(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_vsf_tta(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_wii_was(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_xbox_hlwav(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_p3d(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_adsc(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_adsc(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_mpds(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_psx_mgav(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(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_str2(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_b1s(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_xau(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_bar(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ffw(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_ios_psnd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps3_klbs(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_txth(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_schl_fixed(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_stm(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_pc_al2(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*/ #endif /*_META_H*/

View File

@ -45,6 +45,9 @@ VGMSTREAM * init_vgmstream_mn_str(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = 0x800; vgmstream->interleave_block_size = 0x800;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
} }
break;
default:
goto fail;
} }
vgmstream->num_samples = read_32bitLE(0x4C,streamFile); vgmstream->num_samples = read_32bitLE(0x4C,streamFile);

View File

@ -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;
}

View File

@ -15,7 +15,7 @@
#define NAME_LENGTH PATH_LIMIT #define NAME_LENGTH PATH_LIMIT
int exists(char *filename, STREAMFILE *streamfile) { static int exists(char *filename, STREAMFILE *streamfile) {
STREAMFILE * temp = STREAMFILE * temp =
streamfile->open(streamfile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); streamfile->open(streamfile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!temp) return 0; 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 */ /* 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 */ /* find directory name */
{ {
char temp_dir_name[NAME_LENGTH]; 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; if (strcasecmp("mus",filename_extension(filename))) goto fail;
/* read file name base */ /* 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); mus_offset, streamFile, &whole_line_read);
if (!whole_line_read) goto fail; if (!whole_line_read) goto fail;
mus_offset += line_bytes; mus_offset += line_bytes;
@ -140,7 +140,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) {
/*printf("name base: %s\n",name_base);*/ /*printf("name base: %s\n",name_base);*/
/* read track entry count */ /* 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); mus_offset, streamFile, &whole_line_read);
if (!whole_line_read) goto fail; if (!whole_line_read) goto fail;
if (line_buffer[0] == '\0') goto fail; if (line_buffer[0] == '\0') goto fail;
@ -184,7 +184,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) {
{ {
int fields_matched; int fields_matched;
line_bytes = 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); mus_offset, streamFile, &whole_line_read);
if (!whole_line_read) goto fail; if (!whole_line_read) goto fail;
mus_offset += line_bytes; mus_offset += line_bytes;

View File

@ -1,59 +1,42 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../coding/coding.h"
/* U-Sing (Wii) .myspd */
/* .MYSPF - from U-Sing (Wii) */
VGMSTREAM * init_vgmstream_myspd(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_myspd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; int loop_flag = 0, channel_count;
int channel_count;
int loop_flag = 0;
off_t start_offset; off_t start_offset;
size_t channel_size;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); if (!check_extensions(streamFile,"myspd"))
if (strcasecmp("myspd",filename_extension(filename))) goto fail; goto fail;
channel_count = 2; channel_count = 2;
start_offset = 0x20; start_offset = 0x20;
channel_size = read_32bitBE(0x00,streamFile);
/* check size */ /* 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; goto fail;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ vgmstream->num_samples = ima_bytes_to_samples(channel_size*channel_count, channel_count);
vgmstream->num_samples = read_32bitBE(0x0,streamFile) * 2; vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
vgmstream->sample_rate = read_32bitBE(0x4,streamFile);
vgmstream->coding_type = coding_IMA;
vgmstream->meta_type = meta_MYSPD; 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 */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
{ goto fail;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
vgmstream->ch[0].streamfile = file;
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; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;

View File

@ -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;
}

View File

@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) {
off_t start_offset; off_t start_offset;
int channel_count, loop_flag = 0; int channel_count, loop_flag = 0;
/* check extension, case insensitive */ /* check extension, case insensitive (made-up extension) */
if (!check_extensions(streamFile,"hwas")) if (!check_extensions(streamFile,"hwas"))
goto fail; goto fail;
@ -33,7 +33,7 @@ VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_NDS_HWAS; vgmstream->meta_type = meta_NDS_HWAS;
vgmstream->coding_type = coding_IMA; vgmstream->coding_type = coding_IMA_int;
vgmstream->layout_type = layout_hwas_blocked; vgmstream->layout_type = layout_hwas_blocked;
vgmstream->full_block_size = read_32bitLE(0x04,streamFile); /* usually 0x2000, 0x4000 or 0x8000 */ vgmstream->full_block_size = read_32bitLE(0x04,streamFile); /* usually 0x2000, 0x4000 or 0x8000 */

View File

@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile) {
int loop_flag; int loop_flag;
off_t start_offset; off_t start_offset;
/* check extension, case insensitive */ /* check extension, case insensitive (made-up extension) */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rrds",filename_extension(filename))) goto fail; 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->loop_end_sample = vgmstream->num_samples;
} }
vgmstream->coding_type = coding_IMA; vgmstream->coding_type = coding_IMA_int;
vgmstream->meta_type = meta_NDS_RRDS; vgmstream->meta_type = meta_NDS_RRDS;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;

View File

@ -19,11 +19,11 @@ VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) {
if (strcasecmp("strm",filename_extension(filename))) goto fail; if (strcasecmp("strm",filename_extension(filename))) goto fail;
/* check header */ /* 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; 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;

View File

@ -1,5 +1,4 @@
#include "meta.h" #include "meta.h"
#include "../util.h"
/* STRM - from Final Fantasy Tactics A2 (NDS) */ /* STRM - from Final Fantasy Tactics A2 (NDS) */
VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) { 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); loop_flag = (read_32bitLE(0x20,streamFile) !=0);
channel_count = read_32bitLE(0x24,streamFile); channel_count = read_32bitLE(0x24,streamFile);
start_offset = 0x2C;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
start_offset = 0x2C;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); 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); vgmstream->num_samples = (read_32bitLE(0x04,streamFile)-start_offset);
if (loop_flag) { vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile); vgmstream->loop_end_sample = read_32bitLE(0x28,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->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)) if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail; goto fail;

View File

@ -1214,6 +1214,7 @@ fail:
Lego Indiana Jones - The Original Adventures (Wii) Lego Indiana Jones - The Original Adventures (Wii)
Lego Indiana Jones 2 - The Adventure Continues (Wii) Lego Indiana Jones 2 - The Adventure Continues (Wii)
Lego Star Wars - The Complete Saga (Wii) Lego Star Wars - The Complete Saga (Wii)
Lego The Lord of the Rings (Wii)
The Chronicles of Narnia - Prince Caspian (Wii) */ The Chronicles of Narnia - Prince Caspian (Wii) */
VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
@ -1249,6 +1250,14 @@ VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) {
start_offset = 0xe0; 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; else goto fail;
interleave = read_32bitBE(0xc, streamFile); interleave = read_32bitBE(0xc, streamFile);
@ -2070,8 +2079,8 @@ VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = dsp_nibbles_to_samples( vgmstream->loop_end_sample = dsp_nibbles_to_samples(
ch0_header.loop_end_offset)+1; ch0_header.loop_end_offset)+1;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_interleave_byte; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x4; vgmstream->interleave_block_size = 0x4;
vgmstream->meta_type = meta_WII_NDP; 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; vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2;
/* open the file for reading */ /* open the file for reading */
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); if (!vgmstream_open_stream(vgmstream,streamFile,ch1_start))
if (!vgmstream->ch[0].streamfile) goto fail;
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;
return vgmstream; return vgmstream;
fail: fail:
/* clean up anything we may have opened */ close_vgmstream(vgmstream);
if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -2,17 +2,17 @@
#include "../util.h" #include "../util.h"
/* .dsp found in: /* .dsp found in:
Hikaru No Go 3 (NGC) Hikaru No Go 3 (NGC)
Yu-Gi-Oh! The Falsebound Kingdom (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 * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
int loop_flag; int loop_flag;
int channel_count; int channel_count;
off_t start_offset; off_t start_offset;
int i; int i;
@ -24,29 +24,29 @@ VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile))) if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile)))
goto fail; goto fail;
loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0); loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0);
channel_count = 1; channel_count = 1;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = 0xE0; start_offset = 0xE0;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x28,streamFile); vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x20,streamFile); vgmstream->num_samples = read_32bitBE(0x20,streamFile);
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_DSP_YGO; vgmstream->meta_type = meta_DSP_YGO;
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16); vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16);
vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16); vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16);
} }
// read coef stuff // read coef stuff
{ {
for (i=0;i<16;i++) { for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile);
} }
} }

View File

@ -8,63 +8,63 @@
VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileDSP = NULL; STREAMFILE * streamFileDSP = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
char filenameDSP[PATH_LIMIT]; char filenameDSP[PATH_LIMIT];
int i; int i;
int channel_count; int channel_count;
int loop_flag; int loop_flag;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("sck",filename_extension(filename))) goto fail; if (strcasecmp("sck",filename_extension(filename))) goto fail;
strcpy(filenameDSP,filename); strcpy(filenameDSP,filename);
strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp"); 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) if (read_32bitBE(0x5C,streamFile) != 0x60A94000)
goto fail; goto fail;
if (!streamFile) goto fail; if (!streamFile) goto fail;
channel_count = 2; channel_count = 2;
loop_flag = 0; loop_flag = 0;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x18,streamFile); vgmstream->sample_rate = read_32bitBE(0x18,streamFile);
vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14; vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14;
vgmstream->coding_type = coding_NGC_DSP; 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;
}
if (channel_count == 1) { if(loop_flag) {
vgmstream->layout_type = layout_none; vgmstream->loop_start_sample = 0;
} else if (channel_count == 2) { vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14;
vgmstream->layout_type = layout_interleave; }
vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile);
} 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; vgmstream->meta_type = meta_NGC_SCK_DSP;
/* open the file for reading */ /* open the file for reading */
{ {
for (i=0;i<channel_count;i++) { for (i=0;i<channel_count;i++) {
/* Not sure, i'll put a fake value here for now */ /* Not sure, i'll put a fake value here for now */
vgmstream->ch[i].streamfile = streamFile->open(streamFileDSP,filenameDSP,0x8000); vgmstream->ch[i].streamfile = streamFile->open(streamFileDSP,filenameDSP,0x8000);
vgmstream->ch[i].offset = 0; 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; int i;
for (i=0;i<16;i++) { for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x2C+i*2,streamFile); 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; return vgmstream;
/* clean up anything we may have opened */ /* clean up anything we may have opened */

View File

@ -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;
}

View File

@ -2,30 +2,61 @@
#include "../util.h" #include "../util.h"
#include "../coding/coding.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 * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag = 0, channel_count; int loop_flag = 0, channel_count;
int num_samples = 0, loop_start = 0, loop_end = 0;
off_t offset = 0;
/* check extension, case insensitive */ /* check extension, case insensitive */
if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */ if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */
goto fail; 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; goto fail;
start_offset = 0x28; start_offset = offset + 0x28;
channel_count = read_8bit(0x09,streamFile); /* assumed */ channel_count = read_8bit(offset + 0x09,streamFile); /* assumed */
/* other values in the header: no idea */ /* 0x0a: packet size if CBR?, other values: no idea */
loop_flag = (loop_end > 0); /* -1 when not set */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; 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->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 #ifdef VGM_USE_FFMPEG
{ {
uint8_t buf[0x100]; uint8_t buf[0x100];
@ -47,7 +78,8 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; 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 #else
goto fail; goto fail;

View File

@ -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;
}

View File

@ -1,5 +1,4 @@
#include "meta.h" #include "meta.h"
#include "../util.h"
/* ADP - from Balls of Steel */ /* ADP - from Balls of Steel */
VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE *streamFile) { 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->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->layout_type = layout_none;
vgmstream->meta_type = meta_BOS_ADP; vgmstream->meta_type = meta_BOS_ADP;
@ -48,45 +47,3 @@ fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; 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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;i<channel_count;i++) {
vgmstream->ch[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;
}

View File

@ -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;i<channel_count;i++) {
vgmstream->ch[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;i<channel_count;i++) {
vgmstream->ch[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;
}

View File

@ -9,17 +9,17 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
int loop_flag=0; int loop_flag=0;
int channel_count; int channel_count;
off_t start_offset; off_t start_offset;
off_t check_offset; off_t check_offset;
int32_t streamSize; int32_t streamSize;
uint8_t testBuffer[0x10]; uint8_t testBuffer[0x10];
uint8_t isPCM = 0; uint8_t isPCM = 0;
off_t readOffset = 0; off_t readOffset = 0;
off_t loopEnd = 0; off_t loopEnd = 0;
int i; int i;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -35,27 +35,27 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
goto fail; goto fail;
/* check if file is not corrupt */ /* check if file is not corrupt */
/* seems the Gran Turismo 4 ADS files are considered 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 */ /* so I changed it to adapt the stream size if that's the case */
/* instead of failing playing them at all*/ /* instead of failing playing them at all*/
streamSize = read_32bitLE(0x24,streamFile); streamSize = read_32bitLE(0x24,streamFile);
if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28)) if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28))
{ {
streamSize = get_streamfile_size(streamFile) - 0x28; streamSize = get_streamfile_size(streamFile) - 0x28;
} }
/* check loop */ /* check loop */
if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) || if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) ||
((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0))) ((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0)))
{ {
loop_flag = 0; loop_flag = 0;
} }
else else
{ {
loop_flag = 1; loop_flag = 1;
} }
channel_count=read_32bitLE(0x10,streamFile); channel_count=read_32bitLE(0x10,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
@ -70,9 +70,9 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((streamSize-0x40)/16*28)/vgmstream->channels; 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) if (read_32bitLE(0x08,streamFile)!=0x10)
{ {
vgmstream->coding_type=coding_PCM16LE; vgmstream->coding_type=coding_PCM16LE;
vgmstream->num_samples = streamSize/2/vgmstream->channels; vgmstream->num_samples = streamSize/2/vgmstream->channels;
@ -84,100 +84,100 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
/* Get loop point values */ /* Get loop point values */
if(vgmstream->loop_flag) { if(vgmstream->loop_flag) {
if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile)) if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile))
{ {
// Search for Loop Value // Search for Loop Value
readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size); readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size);
do { do {
readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
// Loop End ...
if(testBuffer[0x01]==0x01) {
if(loopEnd==0) loopEnd = readOffset-0x10;
break;
}
} 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; } while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile));
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 { vgmstream->loop_start_sample = 0;
if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) { vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28;
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile); vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28;
vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); vgmstream->loop_end_sample /=vgmstream->channels;
} else {
vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;; } else {
vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels; 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 :( */ /* don't know why, but it does happen, in ps2 too :( */
if (vgmstream->loop_end_sample > vgmstream->num_samples) if (vgmstream->loop_end_sample > vgmstream->num_samples)
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)) if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18))
{ {
start_offset=0x800; // True Fortune PS2
streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10;
for(i=0;i<0x1f6;i+=4) vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels;
{ }
if(read_32bitLE(0x28+(i*4),streamFile)!=0) else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800)
{ {
start_offset=0x28; // Hack for files with start_offset = 0x800
break; start_offset=0x800;
} }
}
}
// check if we got a real pcm (ex: Clock Tower 3) if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28))
if(vgmstream->coding_type==coding_PCM16LE) {
{ start_offset=0x800;
check_offset=start_offset;
do
{
if(read_8bit(check_offset+1,streamFile)>7)
{
isPCM=1;
break;
}
else
{
check_offset+=0x10;
}
} while (check_offset<get_streamfile_size(streamFile));
if(!isPCM) for(i=0;i<0x1f6;i+=4)
{ {
vgmstream->num_samples=(get_streamfile_size(streamFile)-start_offset)/16*28/vgmstream->channels; if(read_32bitLE(0x28+(i*4),streamFile)!=0)
vgmstream->coding_type=coding_PSX; {
} start_offset=0x28;
} break;
}
}
}
/* expect pcm format allways start @ 0x800, don't know if it's true :P */ // check if we got a real pcm (ex: Clock Tower 3)
/*if(vgmstream->coding_type == coding_PCM16LE) if(vgmstream->coding_type==coding_PCM16LE)
start_offset=0x800;*/ {
check_offset=start_offset;
do
{
if(read_8bit(check_offset+1,streamFile)>7)
{
isPCM=1;
break;
}
else
{
check_offset+=0x10;
}
} while (check_offset<get_streamfile_size(streamFile));
if(!isPCM)
{
vgmstream->num_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 */ /* open the file for reading by each channel */
{ {

Some files were not shown because too many files have changed in this diff Show More