Updated VGMStream to r1050-866-g5cc215b4.
parent
10f2ee1461
commit
16e0a006f2
|
@ -37,6 +37,40 @@
|
|||
83345A511F8AEB2800B2EAA4 /* nsw_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */; };
|
||||
83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4E1F8AEB2800B2EAA4 /* xvag.c */; };
|
||||
833A7A2E1ED11961003EC53E /* xau.c in Sources */ = {isa = PBXBuildFile; fileRef = 833A7A2D1ED11961003EC53E /* xau.c */; };
|
||||
8349A8DF1FE6251F00E26435 /* vorbis_custom_utils_vid1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8DC1FE6251E00E26435 /* vorbis_custom_utils_vid1.c */; };
|
||||
8349A8E01FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8DD1FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c */; };
|
||||
8349A8E11FE6251F00E26435 /* ea_mt_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8DE1FE6251F00E26435 /* ea_mt_decoder.c */; };
|
||||
8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E21FE6253800E26435 /* blocked_dec.c */; };
|
||||
8349A8E91FE6253900E26435 /* blocked_ea_1snh.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */; };
|
||||
8349A8EA1FE6253900E26435 /* blocked_ea_schl.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E41FE6253800E26435 /* blocked_ea_schl.c */; };
|
||||
8349A8EB1FE6253900E26435 /* blocked_ivaud.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E51FE6253800E26435 /* blocked_ivaud.c */; };
|
||||
8349A8EC1FE6253900E26435 /* blocked_vawx.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E61FE6253900E26435 /* blocked_vawx.c */; };
|
||||
8349A8ED1FE6253900E26435 /* blocked_ea_sns.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8E71FE6253900E26435 /* blocked_ea_sns.c */; };
|
||||
8349A9071FE6258200E26435 /* dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8EE1FE6257C00E26435 /* dec.c */; };
|
||||
8349A9081FE6258200E26435 /* ezw.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8EF1FE6257C00E26435 /* ezw.c */; };
|
||||
8349A9091FE6258200E26435 /* pc_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F01FE6257C00E26435 /* pc_ast.c */; };
|
||||
8349A90A1FE6258200E26435 /* sab.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F11FE6257D00E26435 /* sab.c */; };
|
||||
8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F21FE6257D00E26435 /* ps2_pcm.c */; };
|
||||
8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */; };
|
||||
8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F41FE6257D00E26435 /* ubi_sb.c */; };
|
||||
8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F51FE6257D00E26435 /* scd_pcm.c */; };
|
||||
8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F61FE6257E00E26435 /* aix_streamfile.h */; };
|
||||
8349A9101FE6258200E26435 /* ea_eaac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F71FE6257E00E26435 /* ea_eaac.c */; };
|
||||
8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F81FE6257E00E26435 /* bar_streamfile.h */; };
|
||||
8349A9121FE6258200E26435 /* vsf_tta.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F91FE6257E00E26435 /* vsf_tta.c */; };
|
||||
8349A9131FE6258200E26435 /* ngc_vid1.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FA1FE6257E00E26435 /* ngc_vid1.c */; };
|
||||
8349A9141FE6258200E26435 /* omu.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FB1FE6257F00E26435 /* omu.c */; };
|
||||
8349A9151FE6258200E26435 /* ps2_xa2_rrp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FC1FE6257F00E26435 /* ps2_xa2_rrp.c */; };
|
||||
8349A9161FE6258200E26435 /* flx.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FD1FE6257F00E26435 /* flx.c */; };
|
||||
8349A9171FE6258200E26435 /* pc_adp_otns.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */; };
|
||||
8349A9181FE6258200E26435 /* ea_1snh.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8FF1FE6258000E26435 /* ea_1snh.c */; };
|
||||
8349A9191FE6258200E26435 /* afc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9001FE6258000E26435 /* afc.c */; };
|
||||
8349A91A1FE6258200E26435 /* vxn.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9011FE6258000E26435 /* vxn.c */; };
|
||||
8349A91B1FE6258200E26435 /* adx_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A9021FE6258100E26435 /* adx_keys.h */; };
|
||||
8349A91C1FE6258200E26435 /* mogg.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9031FE6258100E26435 /* mogg.c */; };
|
||||
8349A91D1FE6258200E26435 /* aax_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A9041FE6258100E26435 /* aax_streamfile.h */; };
|
||||
8349A91E1FE6258200E26435 /* bar.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9051FE6258100E26435 /* bar.c */; };
|
||||
8349A91F1FE6258200E26435 /* naac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9061FE6258100E26435 /* naac.c */; };
|
||||
834D3A6E19F47C98001C54F6 /* g1l.c in Sources */ = {isa = PBXBuildFile; fileRef = 834D3A6D19F47C98001C54F6 /* g1l.c */; };
|
||||
8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8350270C1ED119D200C25929 /* ps3_mta2.c */; };
|
||||
835027131ED119E000C25929 /* mta2_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 835027121ED119E000C25929 /* mta2_decoder.c */; };
|
||||
|
@ -78,16 +112,12 @@
|
|||
836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0318BDC2180095E648 /* bdsp_blocked.c */; };
|
||||
836F6F4118BDC2190095E648 /* blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0418BDC2180095E648 /* blocked.c */; };
|
||||
836F6F4218BDC2190095E648 /* caf_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0518BDC2180095E648 /* caf_blocked.c */; };
|
||||
836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0618BDC2180095E648 /* de2_blocked.c */; };
|
||||
836F6F4418BDC2190095E648 /* ea_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0718BDC2180095E648 /* ea_block.c */; };
|
||||
836F6F4518BDC2190095E648 /* emff_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0818BDC2180095E648 /* emff_blocked.c */; };
|
||||
836F6F4618BDC2190095E648 /* filp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0918BDC2180095E648 /* filp_blocked.c */; };
|
||||
836F6F4718BDC2190095E648 /* gsb_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0A18BDC2180095E648 /* gsb_blocked.c */; };
|
||||
836F6F4818BDC2190095E648 /* halpst_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0B18BDC2180095E648 /* halpst_blocked.c */; };
|
||||
836F6F4918BDC2190095E648 /* ims_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0C18BDC2180095E648 /* ims_block.c */; };
|
||||
836F6F4A18BDC2190095E648 /* interleave.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0D18BDC2180095E648 /* interleave.c */; };
|
||||
836F6F4B18BDC2190095E648 /* interleave_byte.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0E18BDC2180095E648 /* interleave_byte.c */; };
|
||||
836F6F4C18BDC2190095E648 /* ivaud_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0F18BDC2180095E648 /* ivaud_layout.c */; };
|
||||
836F6F4D18BDC2190095E648 /* layout.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6E1018BDC2180095E648 /* layout.h */; };
|
||||
836F6F4F18BDC2190095E648 /* mus_acm_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1218BDC2180095E648 /* mus_acm_layout.c */; };
|
||||
836F6F5018BDC2190095E648 /* mxch_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1318BDC2180095E648 /* mxch_blocked.c */; };
|
||||
|
@ -109,7 +139,6 @@
|
|||
836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; };
|
||||
836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; };
|
||||
836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.c */; };
|
||||
836F6F6A18BDC2190095E648 /* afc_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2E18BDC2180095E648 /* afc_header.c */; };
|
||||
836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; };
|
||||
836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; };
|
||||
836F6F6D18BDC2190095E648 /* aifc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3118BDC2180095E648 /* aifc.c */; };
|
||||
|
@ -129,12 +158,10 @@
|
|||
836F6F7B18BDC2190095E648 /* dc_idvi.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3F18BDC2180095E648 /* dc_idvi.c */; };
|
||||
836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4018BDC2180095E648 /* dc_kcey.c */; };
|
||||
836F6F7D18BDC2190095E648 /* dc_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4118BDC2180095E648 /* dc_str.c */; };
|
||||
836F6F7E18BDC2190095E648 /* de2.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4218BDC2180095E648 /* de2.c */; };
|
||||
836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4318BDC2180095E648 /* dmsg_segh.c */; };
|
||||
836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4418BDC2180095E648 /* dsp_bdsp.c */; };
|
||||
836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4518BDC2180095E648 /* dsp_sth_str.c */; };
|
||||
836F6F8218BDC2190095E648 /* ea_schl.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4618BDC2180095E648 /* ea_schl.c */; };
|
||||
836F6F8318BDC2190095E648 /* ea_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4718BDC2180095E648 /* ea_old.c */; };
|
||||
836F6F8418BDC2190095E648 /* emff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4818BDC2180095E648 /* emff.c */; };
|
||||
836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4918BDC2180095E648 /* exakt_sc.c */; };
|
||||
836F6F8618BDC2190095E648 /* excitebots.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4A18BDC2180095E648 /* excitebots.c */; };
|
||||
|
@ -143,7 +170,6 @@
|
|||
836F6F8918BDC2190095E648 /* gca.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4D18BDC2180095E648 /* gca.c */; };
|
||||
836F6F8A18BDC2190095E648 /* gcsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4E18BDC2180095E648 /* gcsw.c */; };
|
||||
836F6F8B18BDC2190095E648 /* genh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4F18BDC2180095E648 /* genh.c */; };
|
||||
836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5018BDC2180095E648 /* gh3_bar.c */; };
|
||||
836F6F8D18BDC2190095E648 /* gsp_gsb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5118BDC2180095E648 /* gsp_gsb.c */; };
|
||||
836F6F8E18BDC2190095E648 /* halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5218BDC2180095E648 /* halpst.c */; };
|
||||
836F6F8F18BDC2190095E648 /* his.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5318BDC2180095E648 /* his.c */; };
|
||||
|
@ -197,8 +223,6 @@
|
|||
836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8618BDC2180095E648 /* pc_mxst.c */; };
|
||||
836F6FC318BDC2190095E648 /* pc_smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8718BDC2180095E648 /* pc_smp.c */; };
|
||||
836F6FC418BDC2190095E648 /* pc_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8818BDC2180095E648 /* pc_snds.c */; };
|
||||
836F6FC518BDC2190095E648 /* pc_sob.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8918BDC2180095E648 /* pc_sob.c */; };
|
||||
836F6FC618BDC2190095E648 /* pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8A18BDC2180095E648 /* pcm.c */; };
|
||||
836F6FC718BDC2190095E648 /* pona.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8B18BDC2180095E648 /* pona.c */; };
|
||||
836F6FC818BDC2190095E648 /* pos.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8C18BDC2180095E648 /* pos.c */; };
|
||||
836F6FC918BDC2190095E648 /* ps2_2pfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */; };
|
||||
|
@ -298,7 +322,6 @@
|
|||
836F702E18BDC2190095E648 /* sli.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF218BDC2190095E648 /* sli.c */; };
|
||||
836F702F18BDC2190095E648 /* spt_spd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF318BDC2190095E648 /* spt_spd.c */; };
|
||||
836F703018BDC2190095E648 /* sqex_scd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF418BDC2190095E648 /* sqex_scd.c */; };
|
||||
836F703118BDC2190095E648 /* ss_stream.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF518BDC2190095E648 /* ss_stream.c */; };
|
||||
836F703218BDC2190095E648 /* str_asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF618BDC2190095E648 /* str_asr.c */; };
|
||||
836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; };
|
||||
836F703418BDC2190095E648 /* stx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF818BDC2190095E648 /* stx.c */; };
|
||||
|
@ -378,7 +401,6 @@
|
|||
839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21DF1F2EDAF000EE54D7 /* vorbis_custom_utils_sk.c */; };
|
||||
839E21EB1F2EDB0600EE54D7 /* sk_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */; };
|
||||
83A3F0741E3AD8B900D6A794 /* formats.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F0711E3AD8B900D6A794 /* formats.c */; };
|
||||
83A3F0751E3AD8B900D6A794 /* formats.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0721E3AD8B900D6A794 /* formats.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */; };
|
||||
83A5F75F198DF021009AF94C /* bfwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A5F75E198DF021009AF94C /* bfwav.c */; };
|
||||
83AA5D161F6E2F600020821C /* ea_xa_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */; };
|
||||
|
@ -387,10 +409,8 @@
|
|||
83AA5D191F6E2F600020821C /* ea_xas_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D151F6E2F600020821C /* ea_xas_decoder.c */; };
|
||||
83AA5D1D1F6E2F800020821C /* blocked_vgs.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */; };
|
||||
83AA5D1E1F6E2F800020821C /* blocked_awc.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */; };
|
||||
83AA5D1F1F6E2F800020821C /* ea_sns_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D1C1F6E2F7F0020821C /* ea_sns_blocked.c */; };
|
||||
83AA5D241F6E2F9C0020821C /* awc.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D201F6E2F9B0020821C /* awc.c */; };
|
||||
83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */ = {isa = PBXBuildFile; fileRef = 83AA5D211F6E2F9C0020821C /* hca_keys.h */; };
|
||||
83AA5D261F6E2F9C0020821C /* ea_snu.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D221F6E2F9C0020821C /* ea_snu.c */; };
|
||||
83AA5D271F6E2F9C0020821C /* stm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AA5D231F6E2F9C0020821C /* stm.c */; };
|
||||
83AB8C751E8072A100086084 /* nub_vag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C731E8072A100086084 /* nub_vag.c */; };
|
||||
83AB8C761E8072A100086084 /* x360_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C741E8072A100086084 /* x360_ast.c */; };
|
||||
|
@ -543,6 +563,40 @@
|
|||
83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nsw_opus.c; sourceTree = "<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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -586,16 +640,12 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -617,7 +667,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -637,12 +686,10 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -651,7 +698,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -705,8 +751,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -806,7 +850,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -893,10 +935,8 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -1038,7 +1078,6 @@
|
|||
836F6DFF18BDC2180095E648 /* layout */,
|
||||
836F6E2718BDC2180095E648 /* meta */,
|
||||
83A3F0711E3AD8B900D6A794 /* formats.c */,
|
||||
83A3F0721E3AD8B900D6A794 /* formats.h */,
|
||||
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */,
|
||||
836F6F1718BDC2190095E648 /* streamfile.c */,
|
||||
836F6F1818BDC2190095E648 /* streamfile.h */,
|
||||
|
@ -1054,6 +1093,9 @@
|
|||
836F6DDF18BDC2180095E648 /* coding */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8349A8DE1FE6251F00E26435 /* ea_mt_decoder.c */,
|
||||
8349A8DD1FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c */,
|
||||
8349A8DC1FE6251E00E26435 /* vorbis_custom_utils_vid1.c */,
|
||||
83345A491F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c */,
|
||||
8374EE361F787AB500033E90 /* ffmpeg_decoder_utils_ea_xma.c */,
|
||||
8374EE3D1F787AB600033E90 /* ffmpeg_decoder_utils.c */,
|
||||
|
@ -1116,9 +1158,14 @@
|
|||
836F6DFF18BDC2180095E648 /* layout */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8349A8E21FE6253800E26435 /* blocked_dec.c */,
|
||||
8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */,
|
||||
8349A8E41FE6253800E26435 /* blocked_ea_schl.c */,
|
||||
8349A8E71FE6253900E26435 /* blocked_ea_sns.c */,
|
||||
8349A8E51FE6253800E26435 /* blocked_ivaud.c */,
|
||||
8349A8E61FE6253900E26435 /* blocked_vawx.c */,
|
||||
83AA5D1B1F6E2F7F0020821C /* blocked_awc.c */,
|
||||
83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */,
|
||||
83AA5D1C1F6E2F7F0020821C /* ea_sns_blocked.c */,
|
||||
830165A11F256BF400CA0941 /* hwas_blocked.c */,
|
||||
831BD1201EEE1D2A00198540 /* rws_blocked.c */,
|
||||
836F6E0018BDC2180095E648 /* aax_layout.c */,
|
||||
|
@ -1127,16 +1174,12 @@
|
|||
836F6E0318BDC2180095E648 /* bdsp_blocked.c */,
|
||||
836F6E0418BDC2180095E648 /* blocked.c */,
|
||||
836F6E0518BDC2180095E648 /* caf_blocked.c */,
|
||||
836F6E0618BDC2180095E648 /* de2_blocked.c */,
|
||||
836F6E0718BDC2180095E648 /* ea_block.c */,
|
||||
836F6E0818BDC2180095E648 /* emff_blocked.c */,
|
||||
836F6E0918BDC2180095E648 /* filp_blocked.c */,
|
||||
836F6E0A18BDC2180095E648 /* gsb_blocked.c */,
|
||||
836F6E0B18BDC2180095E648 /* halpst_blocked.c */,
|
||||
836F6E0C18BDC2180095E648 /* ims_block.c */,
|
||||
836F6E0D18BDC2180095E648 /* interleave.c */,
|
||||
836F6E0E18BDC2180095E648 /* interleave_byte.c */,
|
||||
836F6E0F18BDC2180095E648 /* ivaud_layout.c */,
|
||||
836F6E1018BDC2180095E648 /* layout.h */,
|
||||
836F6E1218BDC2180095E648 /* mus_acm_layout.c */,
|
||||
836F6E1318BDC2180095E648 /* mxch_blocked.c */,
|
||||
|
@ -1161,12 +1204,36 @@
|
|||
836F6E2718BDC2180095E648 /* meta */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8349A9041FE6258100E26435 /* aax_streamfile.h */,
|
||||
8349A9021FE6258100E26435 /* adx_keys.h */,
|
||||
8349A9001FE6258000E26435 /* afc.c */,
|
||||
8349A8F61FE6257E00E26435 /* aix_streamfile.h */,
|
||||
8349A8F81FE6257E00E26435 /* bar_streamfile.h */,
|
||||
8349A9051FE6258100E26435 /* bar.c */,
|
||||
8349A8EE1FE6257C00E26435 /* dec.c */,
|
||||
8349A8FF1FE6258000E26435 /* ea_1snh.c */,
|
||||
8349A8F71FE6257E00E26435 /* ea_eaac.c */,
|
||||
8349A8EF1FE6257C00E26435 /* ezw.c */,
|
||||
8349A8FD1FE6257F00E26435 /* flx.c */,
|
||||
8349A9031FE6258100E26435 /* mogg.c */,
|
||||
8349A9061FE6258100E26435 /* naac.c */,
|
||||
8349A8FA1FE6257E00E26435 /* ngc_vid1.c */,
|
||||
8349A8FB1FE6257F00E26435 /* omu.c */,
|
||||
8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */,
|
||||
8349A8F01FE6257C00E26435 /* pc_ast.c */,
|
||||
8349A8F21FE6257D00E26435 /* ps2_pcm.c */,
|
||||
8349A8FC1FE6257F00E26435 /* ps2_xa2_rrp.c */,
|
||||
8349A8F11FE6257D00E26435 /* sab.c */,
|
||||
8349A8F51FE6257D00E26435 /* scd_pcm.c */,
|
||||
8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */,
|
||||
8349A8F41FE6257D00E26435 /* ubi_sb.c */,
|
||||
8349A8F91FE6257E00E26435 /* vsf_tta.c */,
|
||||
8349A9011FE6258000E26435 /* vxn.c */,
|
||||
83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */,
|
||||
83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */,
|
||||
83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */,
|
||||
83345A4E1F8AEB2800B2EAA4 /* xvag.c */,
|
||||
83AA5D201F6E2F9B0020821C /* awc.c */,
|
||||
83AA5D221F6E2F9C0020821C /* ea_snu.c */,
|
||||
83AA5D211F6E2F9C0020821C /* hca_keys.h */,
|
||||
83AA5D231F6E2F9C0020821C /* stm.c */,
|
||||
839E21EA1F2EDB0500EE54D7 /* sk_aud.c */,
|
||||
|
@ -1212,7 +1279,6 @@
|
|||
836F6E2A18BDC2180095E648 /* aax.c */,
|
||||
836F6E2B18BDC2180095E648 /* acm.c */,
|
||||
836F6E2C18BDC2180095E648 /* ads.c */,
|
||||
836F6E2E18BDC2180095E648 /* afc_header.c */,
|
||||
836F6E2F18BDC2180095E648 /* agsc.c */,
|
||||
836F6E3018BDC2180095E648 /* ahx.c */,
|
||||
836F6E3118BDC2180095E648 /* aifc.c */,
|
||||
|
@ -1232,12 +1298,10 @@
|
|||
836F6E3F18BDC2180095E648 /* dc_idvi.c */,
|
||||
836F6E4018BDC2180095E648 /* dc_kcey.c */,
|
||||
836F6E4118BDC2180095E648 /* dc_str.c */,
|
||||
836F6E4218BDC2180095E648 /* de2.c */,
|
||||
836F6E4318BDC2180095E648 /* dmsg_segh.c */,
|
||||
836F6E4418BDC2180095E648 /* dsp_bdsp.c */,
|
||||
836F6E4518BDC2180095E648 /* dsp_sth_str.c */,
|
||||
836F6E4618BDC2180095E648 /* ea_schl.c */,
|
||||
836F6E4718BDC2180095E648 /* ea_old.c */,
|
||||
836F6E4818BDC2180095E648 /* emff.c */,
|
||||
836F6E4918BDC2180095E648 /* exakt_sc.c */,
|
||||
836F6E4A18BDC2180095E648 /* excitebots.c */,
|
||||
|
@ -1246,7 +1310,6 @@
|
|||
836F6E4D18BDC2180095E648 /* gca.c */,
|
||||
836F6E4E18BDC2180095E648 /* gcsw.c */,
|
||||
836F6E4F18BDC2180095E648 /* genh.c */,
|
||||
836F6E5018BDC2180095E648 /* gh3_bar.c */,
|
||||
836F6E5118BDC2180095E648 /* gsp_gsb.c */,
|
||||
836F6E5218BDC2180095E648 /* halpst.c */,
|
||||
836F6E5318BDC2180095E648 /* his.c */,
|
||||
|
@ -1300,8 +1363,6 @@
|
|||
836F6E8618BDC2180095E648 /* pc_mxst.c */,
|
||||
836F6E8718BDC2180095E648 /* pc_smp.c */,
|
||||
836F6E8818BDC2180095E648 /* pc_snds.c */,
|
||||
836F6E8918BDC2180095E648 /* pc_sob.c */,
|
||||
836F6E8A18BDC2180095E648 /* pcm.c */,
|
||||
836F6E8B18BDC2180095E648 /* pona.c */,
|
||||
836F6E8C18BDC2180095E648 /* pos.c */,
|
||||
836F6E8D18BDC2180095E648 /* ps2_2pfs.c */,
|
||||
|
@ -1401,7 +1462,6 @@
|
|||
836F6EF218BDC2190095E648 /* sli.c */,
|
||||
836F6EF318BDC2190095E648 /* spt_spd.c */,
|
||||
836F6EF418BDC2190095E648 /* sqex_scd.c */,
|
||||
836F6EF518BDC2190095E648 /* ss_stream.c */,
|
||||
836F6EF618BDC2190095E648 /* str_asr.c */,
|
||||
836F6EF718BDC2190095E648 /* str_snds.c */,
|
||||
836F6EF818BDC2190095E648 /* stx.c */,
|
||||
|
@ -1475,12 +1535,14 @@
|
|||
836F705518BDC2190095E648 /* streamtypes.h in Headers */,
|
||||
836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */,
|
||||
836F6F3518BDC2190095E648 /* nwa_decoder.h in Headers */,
|
||||
8349A91D1FE6258200E26435 /* aax_streamfile.h in Headers */,
|
||||
8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */,
|
||||
8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */,
|
||||
836F6F2718BDC2190095E648 /* g72x_state.h in Headers */,
|
||||
839E21E01F2EDAF100EE54D7 /* vorbis_custom_data_fsb.h in Headers */,
|
||||
836F705418BDC2190095E648 /* streamfile.h in Headers */,
|
||||
8374EE401F787AB600033E90 /* ffmpeg_decoder_utils.h in Headers */,
|
||||
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */,
|
||||
83A3F0751E3AD8B900D6A794 /* formats.h in Headers */,
|
||||
8323894B1D22419B00482226 /* clHCA.h in Headers */,
|
||||
839E21E81F2EDAF100EE54D7 /* mpeg_decoder.h in Headers */,
|
||||
839E21E51F2EDAF100EE54D7 /* vorbis_custom_decoder.h in Headers */,
|
||||
|
@ -1489,6 +1551,8 @@
|
|||
48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */,
|
||||
836F705718BDC2190095E648 /* util.h in Headers */,
|
||||
836F6F9A18BDC2190095E648 /* meta.h in Headers */,
|
||||
8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */,
|
||||
8349A91B1FE6258200E26435 /* adx_keys.h in Headers */,
|
||||
836F6F4D18BDC2190095E648 /* layout.h in Headers */,
|
||||
83AA5D251F6E2F9C0020821C /* hca_keys.h in Headers */,
|
||||
836F6F2318BDC2190095E648 /* coding.h in Headers */,
|
||||
|
@ -1641,6 +1705,7 @@
|
|||
files = (
|
||||
839E21E21F2EDAF100EE54D7 /* vorbis_custom_utils_wwise.c in Sources */,
|
||||
83E56BA51F2EE3520026BC60 /* vorbis_custom_utils_ogl.c in Sources */,
|
||||
8349A9071FE6258200E26435 /* dec.c in Sources */,
|
||||
839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */,
|
||||
839E21E41F2EDAF100EE54D7 /* vorbis_custom_utils_fsb.c in Sources */,
|
||||
839E21E11F2EDAF100EE54D7 /* vorbis_custom_decoder.c in Sources */,
|
||||
|
@ -1652,8 +1717,10 @@
|
|||
8301659C1F256BD000CA0941 /* nds_strm_ffta2.c in Sources */,
|
||||
83CAB8E31F0B0755001BC993 /* pc_xa30.c in Sources */,
|
||||
83CAB8E21F0B0752001BC993 /* wii_04sw.c in Sources */,
|
||||
8349A8DF1FE6251F00E26435 /* vorbis_custom_utils_vid1.c in Sources */,
|
||||
839B54571EEE1DA000048A2D /* rws_blocked.c in Sources */,
|
||||
839B54521EEE1D9600048A2D /* ngc_ulw.c in Sources */,
|
||||
8349A8E01FE6251F00E26435 /* ffmpeg_decoder_utils_bgw_atrac3.c in Sources */,
|
||||
836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */,
|
||||
836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */,
|
||||
836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */,
|
||||
|
@ -1664,7 +1731,6 @@
|
|||
836F6F7418BDC2190095E648 /* bgw.c in Sources */,
|
||||
836F6F7218BDC2190095E648 /* baf.c in Sources */,
|
||||
83F5F8831908D0A400C8E65F /* fsb5.c in Sources */,
|
||||
836F6F4B18BDC2190095E648 /* interleave_byte.c in Sources */,
|
||||
836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */,
|
||||
836F700C18BDC2190095E648 /* ps2_wb.c in Sources */,
|
||||
836F6F7D18BDC2190095E648 /* dc_str.c in Sources */,
|
||||
|
@ -1678,6 +1744,7 @@
|
|||
836F6F9B18BDC2190095E648 /* mn_str.c in Sources */,
|
||||
836F6F5918BDC2190095E648 /* tra_blocked.c in Sources */,
|
||||
836F6F9F18BDC2190095E648 /* musc.c in Sources */,
|
||||
8349A9121FE6258200E26435 /* vsf_tta.c in Sources */,
|
||||
836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */,
|
||||
836F6FA118BDC2190095E648 /* myspd.c in Sources */,
|
||||
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */,
|
||||
|
@ -1691,6 +1758,7 @@
|
|||
83299FD01E7660C7003A3242 /* bik.c in Sources */,
|
||||
836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */,
|
||||
836F6FBB18BDC2190095E648 /* ngca.c in Sources */,
|
||||
8349A91E1FE6258200E26435 /* bar.c in Sources */,
|
||||
836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */,
|
||||
832389521D224C0800482226 /* hca_decoder.c in Sources */,
|
||||
836F6F9418BDC2190095E648 /* ivb.c in Sources */,
|
||||
|
@ -1700,21 +1768,27 @@
|
|||
836F6F2218BDC2190095E648 /* at3_decoder.c in Sources */,
|
||||
83EDE5D91A70951A005F5D84 /* btsnd.c in Sources */,
|
||||
836F6FFC18BDC2190095E648 /* ps2_ster.c in Sources */,
|
||||
8349A9171FE6258200E26435 /* pc_adp_otns.c in Sources */,
|
||||
836F701E18BDC2190095E648 /* redspark.c in Sources */,
|
||||
836F6FA018BDC2190095E648 /* musx.c in Sources */,
|
||||
836F705818BDC2190095E648 /* vgmstream.c in Sources */,
|
||||
8349A90A1FE6258200E26435 /* sab.c in Sources */,
|
||||
836F6F6818BDC2190095E648 /* ads.c in Sources */,
|
||||
83AB8C761E8072A100086084 /* x360_ast.c in Sources */,
|
||||
836F6F8B18BDC2190095E648 /* genh.c in Sources */,
|
||||
8349A8EA1FE6253900E26435 /* blocked_ea_schl.c in Sources */,
|
||||
836F705118BDC2190095E648 /* zsd.c in Sources */,
|
||||
8349A91F1FE6258200E26435 /* naac.c in Sources */,
|
||||
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */,
|
||||
836F703C18BDC2190095E648 /* wii_bns.c in Sources */,
|
||||
835027131ED119E000C25929 /* mta2_decoder.c in Sources */,
|
||||
836F6FA718BDC2190095E648 /* nds_strm.c in Sources */,
|
||||
8349A91A1FE6258200E26435 /* vxn.c in Sources */,
|
||||
8349A8EB1FE6253900E26435 /* blocked_ivaud.c in Sources */,
|
||||
83A3F0741E3AD8B900D6A794 /* formats.c in Sources */,
|
||||
836F6F6E18BDC2190095E648 /* aix.c in Sources */,
|
||||
836F703118BDC2190095E648 /* ss_stream.c in Sources */,
|
||||
836F6F8718BDC2190095E648 /* ffw.c in Sources */,
|
||||
8349A9141FE6258200E26435 /* omu.c in Sources */,
|
||||
836F6FE418BDC2190095E648 /* ps2_leg.c in Sources */,
|
||||
836F705618BDC2190095E648 /* util.c in Sources */,
|
||||
836F703618BDC2190095E648 /* thp.c in Sources */,
|
||||
|
@ -1745,16 +1819,17 @@
|
|||
836F6F6518BDC2190095E648 /* 2dx9.c in Sources */,
|
||||
836F700818BDC2190095E648 /* ps2_vms.c in Sources */,
|
||||
836F702418BDC2190095E648 /* rwsd.c in Sources */,
|
||||
836F6F7E18BDC2190095E648 /* de2.c in Sources */,
|
||||
836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */,
|
||||
836F6F6618BDC2190095E648 /* aax.c in Sources */,
|
||||
836F6F4C18BDC2190095E648 /* ivaud_layout.c in Sources */,
|
||||
836F6FD618BDC2190095E648 /* ps2_exst.c in Sources */,
|
||||
836F6F6718BDC2190095E648 /* acm.c in Sources */,
|
||||
836F6F8A18BDC2190095E648 /* gcsw.c in Sources */,
|
||||
836F6F9C18BDC2190095E648 /* mp4.c in Sources */,
|
||||
8349A9101FE6258200E26435 /* ea_eaac.c in Sources */,
|
||||
836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */,
|
||||
8349A8ED1FE6253900E26435 /* blocked_ea_sns.c in Sources */,
|
||||
836F6F6F18BDC2190095E648 /* akb.c in Sources */,
|
||||
8349A9181FE6258200E26435 /* ea_1snh.c in Sources */,
|
||||
836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */,
|
||||
83709E071ECBC1A4005C03D3 /* mss.c in Sources */,
|
||||
836F6F8F18BDC2190095E648 /* his.c in Sources */,
|
||||
|
@ -1762,7 +1837,6 @@
|
|||
836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */,
|
||||
836F6FCB18BDC2190095E648 /* ps2_ads.c in Sources */,
|
||||
836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */,
|
||||
83AA5D261F6E2F9C0020821C /* ea_snu.c in Sources */,
|
||||
83AA5D171F6E2F600020821C /* mpeg_custom_utils_ealayer3.c in Sources */,
|
||||
83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */,
|
||||
836F704C18BDC2190095E648 /* xbox_xvas.c in Sources */,
|
||||
|
@ -1775,16 +1849,15 @@
|
|||
836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */,
|
||||
836F6F7918BDC2190095E648 /* dc_asd.c in Sources */,
|
||||
836F6FC118BDC2190095E648 /* pc_adp.c in Sources */,
|
||||
836F6F8318BDC2190095E648 /* ea_old.c in Sources */,
|
||||
836F701A18BDC2190095E648 /* psx_fag.c in Sources */,
|
||||
836F703B18BDC2190095E648 /* vsf.c in Sources */,
|
||||
836F6F3D18BDC2190095E648 /* aax_layout.c in Sources */,
|
||||
83AA5D1F1F6E2F800020821C /* ea_sns_blocked.c in Sources */,
|
||||
836F6F8218BDC2190095E648 /* ea_schl.c in Sources */,
|
||||
836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */,
|
||||
836F6F7318BDC2190095E648 /* bcstm.c in Sources */,
|
||||
83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */,
|
||||
836F704018BDC2190095E648 /* wii_sng.c in Sources */,
|
||||
8349A9131FE6258200E26435 /* ngc_vid1.c in Sources */,
|
||||
8350C0551E071881009E0A93 /* xma.c in Sources */,
|
||||
836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */,
|
||||
836F704218BDC2190095E648 /* wii_sts.c in Sources */,
|
||||
|
@ -1799,7 +1872,6 @@
|
|||
836F702B18BDC2190095E648 /* sdt.c in Sources */,
|
||||
836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */,
|
||||
836F702C18BDC2190095E648 /* seg.c in Sources */,
|
||||
836F6F6A18BDC2190095E648 /* afc_header.c in Sources */,
|
||||
836F700918BDC2190095E648 /* ps2_voi.c in Sources */,
|
||||
836F6F3E18BDC2190095E648 /* aix_layout.c in Sources */,
|
||||
836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */,
|
||||
|
@ -1814,6 +1886,7 @@
|
|||
836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */,
|
||||
836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */,
|
||||
836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */,
|
||||
8349A8EC1FE6253900E26435 /* blocked_vawx.c in Sources */,
|
||||
836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */,
|
||||
836F700418BDC2190095E648 /* ps2_vas.c in Sources */,
|
||||
836F6F9818BDC2190095E648 /* mattel_hyperscan.c in Sources */,
|
||||
|
@ -1822,7 +1895,7 @@
|
|||
83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */,
|
||||
836F6F6D18BDC2190095E648 /* aifc.c in Sources */,
|
||||
836F702218BDC2190095E648 /* rsd.c in Sources */,
|
||||
836F6FC618BDC2190095E648 /* pcm.c in Sources */,
|
||||
8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */,
|
||||
83345A501F8AEB2800B2EAA4 /* pc_al2.c in Sources */,
|
||||
836F702518BDC2190095E648 /* rwx.c in Sources */,
|
||||
836F6F3A18BDC2190095E648 /* sdx2_decoder.c in Sources */,
|
||||
|
@ -1851,6 +1924,7 @@
|
|||
836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */,
|
||||
836F6F5118BDC2190095E648 /* nolayout.c in Sources */,
|
||||
83AA5D241F6E2F9C0020821C /* awc.c in Sources */,
|
||||
8349A8E91FE6253900E26435 /* blocked_ea_1snh.c in Sources */,
|
||||
836F702918BDC2190095E648 /* sat_sap.c in Sources */,
|
||||
836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */,
|
||||
831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */,
|
||||
|
@ -1869,11 +1943,13 @@
|
|||
83709E061ECBC1A4005C03D3 /* mc3.c in Sources */,
|
||||
831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */,
|
||||
836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */,
|
||||
8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */,
|
||||
836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */,
|
||||
836F6F4A18BDC2190095E648 /* interleave.c in Sources */,
|
||||
83EDE5D81A70951A005F5D84 /* mca.c in Sources */,
|
||||
831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */,
|
||||
838BDB6C1D3AFAB10022CA6F /* ffmpeg_decoder.c in Sources */,
|
||||
8349A8E11FE6251F00E26435 /* ea_mt_decoder.c in Sources */,
|
||||
836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */,
|
||||
836F702F18BDC2190095E648 /* spt_spd.c in Sources */,
|
||||
836F704618BDC2190095E648 /* x360_tra.c in Sources */,
|
||||
|
@ -1882,7 +1958,9 @@
|
|||
834D3A6E19F47C98001C54F6 /* g1l.c in Sources */,
|
||||
836F6FC318BDC2190095E648 /* pc_smp.c in Sources */,
|
||||
836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */,
|
||||
8349A9091FE6258200E26435 /* pc_ast.c in Sources */,
|
||||
836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */,
|
||||
8349A91C1FE6258200E26435 /* mogg.c in Sources */,
|
||||
836F703D18BDC2190095E648 /* wii_mus.c in Sources */,
|
||||
836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */,
|
||||
831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */,
|
||||
|
@ -1901,14 +1979,16 @@
|
|||
836F6F7718BDC2190095E648 /* capdsp.c in Sources */,
|
||||
836F6FB018BDC2190095E648 /* ngc_dsp_ygo.c in Sources */,
|
||||
836F703318BDC2190095E648 /* str_snds.c in Sources */,
|
||||
8349A9191FE6258200E26435 /* afc.c in Sources */,
|
||||
836F703718BDC2190095E648 /* tun.c in Sources */,
|
||||
836F700B18BDC2190095E648 /* ps2_wad.c in Sources */,
|
||||
8349A9161FE6258200E26435 /* flx.c in Sources */,
|
||||
831BA61E1EAC61A500CF89B0 /* vawx.c in Sources */,
|
||||
836F702A18BDC2190095E648 /* sd9.c in Sources */,
|
||||
836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */,
|
||||
836F6F4418BDC2190095E648 /* ea_block.c in Sources */,
|
||||
836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */,
|
||||
836F6FF618BDC2190095E648 /* ps2_sfs.c in Sources */,
|
||||
8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */,
|
||||
836F6F9518BDC2190095E648 /* kraw.c in Sources */,
|
||||
836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */,
|
||||
83709E051ECBC1A4005C03D3 /* gtd.c in Sources */,
|
||||
|
@ -1926,8 +2006,8 @@
|
|||
836F700318BDC2190095E648 /* ps2_vag.c in Sources */,
|
||||
836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */,
|
||||
831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */,
|
||||
836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */,
|
||||
836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */,
|
||||
8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */,
|
||||
831BA6181EAC61A500CF89B0 /* adx.c in Sources */,
|
||||
836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */,
|
||||
836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */,
|
||||
|
@ -1937,6 +2017,7 @@
|
|||
836F6F4918BDC2190095E648 /* ims_block.c in Sources */,
|
||||
836F6F7518BDC2190095E648 /* bnsf.c in Sources */,
|
||||
836F704318BDC2190095E648 /* wpd.c in Sources */,
|
||||
8349A9081FE6258200E26435 /* ezw.c in Sources */,
|
||||
836F6FE118BDC2190095E648 /* ps2_jstm.c in Sources */,
|
||||
836F6FD918BDC2190095E648 /* ps2_gcm.c in Sources */,
|
||||
836F6F8E18BDC2190095E648 /* halpst.c in Sources */,
|
||||
|
@ -1959,7 +2040,6 @@
|
|||
836F700718BDC2190095E648 /* ps2_vgv.c in Sources */,
|
||||
836F704F18BDC2190095E648 /* xwb.c in Sources */,
|
||||
8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */,
|
||||
836F6FC518BDC2190095E648 /* pc_sob.c in Sources */,
|
||||
836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */,
|
||||
836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */,
|
||||
836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */,
|
||||
|
@ -1983,6 +2063,7 @@
|
|||
836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */,
|
||||
836F6F9218BDC2190095E648 /* ish_isd.c in Sources */,
|
||||
836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */,
|
||||
8349A9151FE6258200E26435 /* ps2_xa2_rrp.c in Sources */,
|
||||
836F703518BDC2190095E648 /* svs.c in Sources */,
|
||||
836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */,
|
||||
836F6F9D18BDC2190095E648 /* msvp.c in Sources */,
|
||||
|
@ -1990,7 +2071,6 @@
|
|||
836F705018BDC2190095E648 /* ydsp.c in Sources */,
|
||||
836F702718BDC2190095E648 /* sat_baka.c in Sources */,
|
||||
83345A4A1F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c in Sources */,
|
||||
836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */,
|
||||
836F704B18BDC2190095E648 /* xbox_xmu.c in Sources */,
|
||||
832389501D2246C300482226 /* hca.c in Sources */,
|
||||
836F701B18BDC2190095E648 /* psx_gms.c in Sources */,
|
||||
|
|
|
@ -18,11 +18,10 @@ void g72x_init_state(struct g72x_state *state_ptr);
|
|||
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_xbox_ima_int(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_eacs_ima(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first);
|
||||
void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
@ -32,12 +31,14 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
|
|||
void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
|
||||
size_t ima_bytes_to_samples(size_t bytes, int channels);
|
||||
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset);
|
||||
|
||||
/* ngc_dsp_decoder */
|
||||
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem);
|
||||
void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave);
|
||||
size_t dsp_bytes_to_samples(size_t bytes, int channels);
|
||||
int32_t dsp_nibbles_to_samples(int32_t nibbles);
|
||||
void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
|
||||
|
@ -78,7 +79,8 @@ size_t ps_bytes_to_samples(size_t bytes, int channels);
|
|||
|
||||
/* xa_decoder */
|
||||
void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void init_get_high_nibble(VGMSTREAM * vgmstream);
|
||||
void xa_init_get_high_nibble(VGMSTREAM * vgmstream);
|
||||
size_t xa_bytes_to_samples(size_t bytes, int channels, int is_blocked);
|
||||
|
||||
/* ea_xa_decoder */
|
||||
void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
@ -133,6 +135,14 @@ void decode_mta2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
|||
/* mc3_decoder */
|
||||
void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
||||
/* ea_mt_decoder*/
|
||||
ea_mt_codec_data *init_ea_mt(int channel_count, int type);
|
||||
void decode_ea_mt(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void reset_ea_mt(VGMSTREAM * vgmstream);
|
||||
void flush_ea_mt(VGMSTREAM *vgmstream);
|
||||
void seek_ea_mt(VGMSTREAM * vgmstream, int32_t num_sample);
|
||||
void free_ea_mt(ea_mt_codec_data *data);
|
||||
|
||||
/* hca_decoder */
|
||||
void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
void reset_hca(VGMSTREAM *vgmstream);
|
||||
|
@ -167,11 +177,11 @@ void free_mpeg(mpeg_codec_data *data);
|
|||
void flush_mpeg(mpeg_codec_data * data);
|
||||
|
||||
long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data);
|
||||
void mpeg_set_error_logging(mpeg_codec_data * data, int enable);
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_G7221
|
||||
/* g7221_decoder */
|
||||
g7221_codec_data *init_g7221(int channel_count, int frame_size);
|
||||
void decode_g7221(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
||||
void reset_g7221(VGMSTREAM *vgmstream);
|
||||
void free_g7221(VGMSTREAM *vgmstream);
|
||||
|
@ -179,6 +189,7 @@ void free_g7221(VGMSTREAM *vgmstream);
|
|||
|
||||
#ifdef VGM_USE_G719
|
||||
/* g719_decoder */
|
||||
g719_codec_data *init_g719(int channel_count, int frame_size);
|
||||
void decode_g719(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
||||
void reset_g719(VGMSTREAM *vgmstream);
|
||||
void free_g719(VGMSTREAM *vgmstream);
|
||||
|
@ -265,4 +276,19 @@ void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * cha
|
|||
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
|
||||
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
|
||||
|
||||
|
||||
|
||||
/* An internal struct to pass around and simulate a bitstream. */
|
||||
typedef enum { BITSTREAM_MSF, BITSTREAM_VORBIS } vgm_bitstream_t;
|
||||
typedef struct {
|
||||
uint8_t * buf; /* buffer to read/write*/
|
||||
size_t bufsize; /* max size of the buffer */
|
||||
off_t b_off; /* current offset in bits inside the buffer */
|
||||
off_t info_offset; /* for logging */
|
||||
vgm_bitstream_t mode; /* read/write modes */
|
||||
} vgm_bitstream;
|
||||
|
||||
int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value);
|
||||
int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value);
|
||||
|
||||
#endif /*_CODING_H*/
|
||||
|
|
|
@ -835,3 +835,149 @@ size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) {
|
|||
* so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */
|
||||
return (bytes / full_block_align) * 2048;
|
||||
}
|
||||
|
||||
|
||||
/* ******************************************** */
|
||||
/* BITSTREAM */
|
||||
/* ******************************************** */
|
||||
|
||||
|
||||
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
|
||||
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
|
||||
static int r_bits_vorbis(vgm_bitstream * ib, int num_bits, uint32_t * value) {
|
||||
off_t off, pos;
|
||||
int i, bit_buf, bit_val;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
|
||||
|
||||
*value = 0; /* set all bits to 0 */
|
||||
off = ib->b_off / 8; /* byte offset */
|
||||
pos = ib->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
|
||||
bit_val = (1U << i); /* bit to set in value */
|
||||
|
||||
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
|
||||
*value |= bit_val; /* set bit */
|
||||
|
||||
pos++; /* new byte starts */
|
||||
if (pos%8 == 0) {
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
ib->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
|
||||
* (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/
|
||||
static int w_bits_vorbis(vgm_bitstream * ob, int num_bits, uint32_t value) {
|
||||
off_t off, pos;
|
||||
int i, bit_val, bit_buf;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail;
|
||||
|
||||
|
||||
off = ob->b_off / 8; /* byte offset */
|
||||
pos = ob->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_val = (1U << i); /* bit check for value */
|
||||
bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */
|
||||
|
||||
if (value & bit_val) /* is bit in val set? */
|
||||
ob->buf[off] |= bit_buf; /* set bit */
|
||||
else
|
||||
ob->buf[off] &= ~bit_buf; /* unset bit */
|
||||
|
||||
pos++; /* new byte starts */
|
||||
if (pos%8 == 0) {
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
ob->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */
|
||||
static int r_bits_msf(vgm_bitstream * ib, int num_bits, uint32_t * value) {
|
||||
off_t off, pos;
|
||||
int i, bit_buf, bit_val;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
|
||||
|
||||
*value = 0; /* set all bits to 0 */
|
||||
off = ib->b_off / 8; /* byte offset */
|
||||
pos = ib->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */
|
||||
bit_val = (1U << (num_bits-1-i)); /* bit to set in value */
|
||||
|
||||
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
|
||||
*value |= bit_val; /* set bit */
|
||||
|
||||
pos++;
|
||||
if (pos%8 == 0) { /* new byte starts */
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
ib->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */
|
||||
static int w_bits_msf(vgm_bitstream * ob, int num_bits, uint32_t value) {
|
||||
off_t off, pos;
|
||||
int i, bit_val, bit_buf;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail;
|
||||
|
||||
|
||||
off = ob->b_off / 8; /* byte offset */
|
||||
pos = ob->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_val = (1U << (num_bits-1-i)); /* bit check for value */
|
||||
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */
|
||||
|
||||
if (value & bit_val) /* is bit in val set? */
|
||||
ob->buf[off] |= bit_buf; /* set bit */
|
||||
else
|
||||
ob->buf[off] &= ~bit_buf; /* unset bit */
|
||||
|
||||
pos++;
|
||||
if (pos%8 == 0) { /* new byte starts */
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
ob->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value) {
|
||||
if (ib->mode == BITSTREAM_VORBIS)
|
||||
return r_bits_vorbis(ib,num_bits,value);
|
||||
else
|
||||
return r_bits_msf(ib,num_bits,value);
|
||||
}
|
||||
int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value) {
|
||||
if (ob->mode == BITSTREAM_VORBIS)
|
||||
return w_bits_vorbis(ob,num_bits,value);
|
||||
else
|
||||
return w_bits_msf(ob,num_bits,value);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -29,59 +29,57 @@ static const int EA_XA_TABLE[20] = {
|
|||
0, -1, -3, -4
|
||||
};
|
||||
|
||||
/* EA XA v2; like ea_xa_int but with "PCM samples" flag and doesn't add 128 on expand or clamp (pre-adjusted by the encoder?) */
|
||||
/* EA XA v2 (always mono); like ea_xa_int but with "PCM samples" flag and doesn't add 128 on expand or clamp (pre-adjusted by the encoder?) */
|
||||
void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
|
||||
uint8_t frame_info;
|
||||
int32_t sample_count;
|
||||
int32_t coef1, coef2;
|
||||
int i, shift;
|
||||
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
|
||||
int i, sample_count, shift;
|
||||
|
||||
first_sample = first_sample%28;
|
||||
int pcm_frame_size = 0x01 + 2*0x02 + 28*0x02;
|
||||
int xa_frame_size = 0x0f;
|
||||
int frame_samples = 28;
|
||||
first_sample = first_sample % frame_samples;
|
||||
|
||||
/* header */
|
||||
frame_info = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||
channel_offset++;
|
||||
frame_info = read_8bit(stream->offset,stream->streamfile);
|
||||
|
||||
if (frame_info == 0xEE) { /* PCM frame (used in later revisions), samples always BE */
|
||||
stream->adpcm_history1_32 = read_16bitBE(stream->offset+channel_offset+0x00,stream->streamfile);
|
||||
stream->adpcm_history2_32 = read_16bitBE(stream->offset+channel_offset+0x02,stream->streamfile);
|
||||
channel_offset += 4;
|
||||
stream->adpcm_history1_32 = read_16bitBE(stream->offset + 0x01 + 0x00,stream->streamfile);
|
||||
stream->adpcm_history2_32 = read_16bitBE(stream->offset + 0x01 + 0x02,stream->streamfile);
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
outbuf[sample_count] = read_16bitBE(stream->offset+channel_offset,stream->streamfile);
|
||||
channel_offset+=2;
|
||||
outbuf[sample_count] = read_16bitBE(stream->offset + 0x01 + 2*0x02 + i*0x02,stream->streamfile);
|
||||
}
|
||||
|
||||
/* Only increment offset on complete frame */
|
||||
if (channel_offset-stream->channel_start_offset == (2*28)+5)
|
||||
stream->channel_start_offset += (2*28)+5;
|
||||
|
||||
} else { /* ADPCM frame */
|
||||
/* only increment offset on complete frame */
|
||||
if (i == frame_samples)
|
||||
stream->offset += pcm_frame_size;
|
||||
}
|
||||
else { /* ADPCM frame */
|
||||
coef1 = EA_XA_TABLE[(frame_info >> 4) + 0];
|
||||
coef2 = EA_XA_TABLE[(frame_info >> 4) + 4];
|
||||
shift = (frame_info & 0x0F) + 8;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
uint8_t sample_byte, sample_nibble;
|
||||
int32_t sample;
|
||||
off_t byte_offset = (stream->offset + channel_offset + i/2);
|
||||
int32_t new_sample;
|
||||
off_t byte_offset = (stream->offset + 0x01 + i/2);
|
||||
int nibble_shift = (!(i&1)) ? 4 : 0; /* high nibble first */
|
||||
|
||||
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
|
||||
sample_nibble = (!(i%2) ? sample_byte >> 4 : sample_byte & 0x0F); /* i=even > high nibble */
|
||||
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32) >> 8;
|
||||
sample = clamp16(sample);
|
||||
sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
|
||||
new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32) >> 8;
|
||||
new_sample = clamp16(new_sample);
|
||||
|
||||
outbuf[sample_count] = sample;
|
||||
outbuf[sample_count] = new_sample;
|
||||
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||
stream->adpcm_history1_32 = sample;
|
||||
stream->adpcm_history1_32 = new_sample;
|
||||
}
|
||||
channel_offset += i/2;
|
||||
|
||||
/* Only increment offset on complete frame */
|
||||
if (channel_offset - stream->channel_start_offset == 0x0F)
|
||||
stream->channel_start_offset += 0x0F;
|
||||
/* only increment offset on complete frame */
|
||||
if (i == frame_samples)
|
||||
stream->offset += xa_frame_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,43 +88,42 @@ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing
|
|||
uint8_t frame_info;
|
||||
int32_t coef1, coef2;
|
||||
int i, sample_count, shift;
|
||||
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
|
||||
int hn = (channel==0); /* high nibble marker for stereo subinterleave, ch0/L=high nibble, ch1/R=low nibble */
|
||||
|
||||
first_sample = first_sample % 28;
|
||||
int frame_size = 0x1e;
|
||||
int frame_samples = 28;
|
||||
first_sample = first_sample % frame_samples;
|
||||
|
||||
/* header (coefs ch0+ch1 + shift ch0+ch1) */
|
||||
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||
channel_offset++;
|
||||
frame_info = read_8bit(stream->offset+0x00,stream->streamfile);
|
||||
coef1 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 0];
|
||||
coef2 = EA_XA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 4];
|
||||
shift = (frame_info & 0x0F) + 8;
|
||||
|
||||
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||
channel_offset++;
|
||||
frame_info = read_8bit(stream->offset+0x01,stream->streamfile);
|
||||
shift = (hn ? frame_info >> 4 : frame_info & 0x0F) + 8;
|
||||
|
||||
/* samples */
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
uint8_t sample_byte, sample_nibble;
|
||||
int32_t sample;
|
||||
off_t byte_offset = (stream->offset + channel_offset + i);
|
||||
int32_t new_sample;
|
||||
off_t byte_offset = (stream->offset + 0x02 + i);
|
||||
int nibble_shift = (hn ? 4 : 0); /* high nibble first */
|
||||
|
||||
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
|
||||
sample_nibble = (hn ? sample_byte >> 4 : sample_byte & 0x0F);
|
||||
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
|
||||
sample = clamp16(sample);
|
||||
sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
|
||||
new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
|
||||
new_sample = clamp16(new_sample);
|
||||
|
||||
outbuf[sample_count] = sample;
|
||||
outbuf[sample_count] = new_sample;
|
||||
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||
stream->adpcm_history1_32 = sample;
|
||||
stream->adpcm_history1_32 = new_sample;
|
||||
}
|
||||
channel_offset += i;
|
||||
|
||||
/* Only increment offset on complete frame */
|
||||
if(channel_offset - stream->channel_start_offset == 0x1E)
|
||||
stream->channel_start_offset += 0x1E;
|
||||
/* only increment offset on complete frame */
|
||||
if (i == frame_samples)
|
||||
stream->offset += frame_size;
|
||||
}
|
||||
|
||||
/* EA-XA v1 mono/interleave */
|
||||
|
@ -134,13 +131,13 @@ void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa
|
|||
uint8_t frame_info;
|
||||
int32_t coef1, coef2;
|
||||
int i, sample_count, shift;
|
||||
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
|
||||
|
||||
first_sample = first_sample % 28;
|
||||
int frame_size = 0x0f;
|
||||
int frame_samples = 28;
|
||||
first_sample = first_sample % frame_samples;
|
||||
|
||||
/* header (coefs+shift ch0) */
|
||||
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||
channel_offset++;
|
||||
frame_info = read_8bit(stream->offset,stream->streamfile);
|
||||
coef1 = EA_XA_TABLE[(frame_info >> 4) + 0];
|
||||
coef2 = EA_XA_TABLE[(frame_info >> 4) + 4];
|
||||
shift = (frame_info & 0x0F) + 8;
|
||||
|
@ -148,39 +145,38 @@ void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa
|
|||
/* samples */
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
uint8_t sample_byte, sample_nibble;
|
||||
int32_t sample;
|
||||
off_t byte_offset = (stream->offset + channel_offset + i/2);
|
||||
int32_t new_sample;
|
||||
off_t byte_offset = (stream->offset + 0x01 + i/2);
|
||||
int nibble_shift = (!(i&1)) ? 4 : 0; /* high nibble first */
|
||||
|
||||
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
|
||||
sample_nibble = (!(i%2) ? sample_byte >> 4 : sample_byte & 0x0F); /* i=even > high nibble */
|
||||
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
|
||||
sample = clamp16(sample);
|
||||
sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
|
||||
new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
|
||||
new_sample = clamp16(new_sample);
|
||||
|
||||
outbuf[sample_count] = sample;
|
||||
outbuf[sample_count] = new_sample;
|
||||
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||
stream->adpcm_history1_32 = sample;
|
||||
stream->adpcm_history1_32 = new_sample;
|
||||
}
|
||||
channel_offset += i/2;
|
||||
|
||||
/* Only increment offset on complete frame */
|
||||
if(channel_offset - stream->channel_start_offset == 0x0F)
|
||||
stream->channel_start_offset += 0x0F;
|
||||
/* only increment offset on complete frame */
|
||||
if (i == frame_samples)
|
||||
stream->offset += frame_size;
|
||||
}
|
||||
|
||||
/* Maxis EA-XA v1 (mono+stereo), differing slightly in the header layout in stereo mode */
|
||||
/* Maxis EA-XA v1 (mono+stereo) with byte-interleave layout in stereo mode */
|
||||
void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
uint8_t frame_info;
|
||||
int32_t coef1, coef2;
|
||||
int i, sample_count, shift;
|
||||
off_t channel_offset = stream->channel_start_offset;
|
||||
int frame_size = channelspacing * 15; /* mono samples have a frame of 15, stereo files have frames of 30 */
|
||||
|
||||
first_sample = first_sample % 28;
|
||||
int frame_size = 0x0f * channelspacing; /* varies in mono/stereo */
|
||||
int frame_samples = 28;
|
||||
first_sample = first_sample % frame_samples;
|
||||
|
||||
/* header (coefs+shift ch0 + coefs+shift ch1) */
|
||||
frame_info = read_8bit(channel_offset,stream->streamfile);
|
||||
channel_offset += channelspacing;
|
||||
frame_info = read_8bit(stream->offset + channel,stream->streamfile);
|
||||
coef1 = EA_XA_TABLE[(frame_info >> 4) + 0];
|
||||
coef2 = EA_XA_TABLE[(frame_info >> 4) + 4];
|
||||
shift = (frame_info & 0x0F) + 8;
|
||||
|
@ -188,27 +184,22 @@ void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac
|
|||
/* samples */
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
uint8_t sample_byte, sample_nibble;
|
||||
int32_t sample;
|
||||
off_t byte_offset = (stream->offset + channel_offset);
|
||||
int32_t new_sample;
|
||||
off_t byte_offset = (stream->offset + 0x01*channelspacing + (channelspacing == 2 ? i/2 + channel + (i/2)*0x01 : i/2));
|
||||
int nibble_shift = (!(i&1)) ? 4 : 0; /* high nibble first */
|
||||
|
||||
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
|
||||
sample_nibble = (i&1) ? sample_byte & 0x0F : sample_byte >> 4;
|
||||
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
|
||||
sample = clamp16(sample);
|
||||
sample_nibble = (sample_byte >> nibble_shift) & 0x0F;
|
||||
new_sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
new_sample = (new_sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
|
||||
new_sample = clamp16(new_sample);
|
||||
|
||||
outbuf[sample_count] = sample;
|
||||
outbuf[sample_count] = new_sample;
|
||||
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||
stream->adpcm_history1_32 = sample;
|
||||
|
||||
if(i&1)
|
||||
stream->offset+=channelspacing;
|
||||
stream->adpcm_history1_32 = new_sample;
|
||||
}
|
||||
channel_offset+=i;
|
||||
|
||||
/* Only increment offset on complete frame */
|
||||
if (channel_offset - stream->channel_start_offset == frame_size) {
|
||||
stream->channel_start_offset += frame_size;
|
||||
stream->offset=0;
|
||||
}
|
||||
/* only increment offset on complete frame */
|
||||
if (i == frame_samples)
|
||||
stream->offset += frame_size;
|
||||
}
|
||||
|
|
|
@ -98,6 +98,8 @@ static void convert_audio(sample *outbuf, const uint8_t *inbuf, int sampleCount,
|
|||
* Fortunately seek_frame_generic can use an index to find the correct position. This function reads the
|
||||
* first frame/packet and sets up index to timestamp 0. This ensures faulty demuxers will seek to 0 correctly.
|
||||
* Some formats may not seek to 0 even with this, though.
|
||||
*
|
||||
* todo: some formats don't work with the current index values
|
||||
*/
|
||||
static int init_seek(ffmpeg_codec_data * data) {
|
||||
int ret, ts_index, found_first = 0;
|
||||
|
@ -220,6 +222,7 @@ static int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size) {
|
|||
switch(data->config.type) {
|
||||
case FFMPEG_EA_XMA: ret = ffmpeg_custom_read_eaxma(data, buf, buf_size); break;
|
||||
case FFMPEG_SWITCH_OPUS: ret = ffmpeg_custom_read_switch_opus(data, buf, buf_size); break;
|
||||
case FFMPEG_BGW_ATRAC3: ret = ffmpeg_custom_read_bgw_atrac3(data, buf, buf_size); break;
|
||||
//case FFMPEG_EA_SCHL: ret = ffmpeg_custom_read_ea_schl(data, buf, buf_size); break;
|
||||
//case FFMPEG_SFH: ret = ffmpeg_custom_read_sfh(data, buf, buf_size); break;
|
||||
default: ret = ffmpeg_custom_read_standard(data, buf, buf_size); break;
|
||||
|
@ -228,6 +231,7 @@ static int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size) {
|
|||
//data->real_offset = ; /* must be updated in function */
|
||||
|
||||
//;VGM_LOG("AVIO read done: ret=%x, r_off=%"PRIx64", v_off=%"PRIx64"\n", ret + max_to_copy, data->real_offset, data->virtual_offset);fflush(stdout);
|
||||
//;VGM_LOGB((buf - max_to_copy),ret + max_to_copy,0);
|
||||
return ret + max_to_copy;
|
||||
}
|
||||
|
||||
|
@ -287,6 +291,7 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) {
|
|||
switch(data->config.type) {
|
||||
case FFMPEG_EA_XMA: offset = ffmpeg_custom_seek_eaxma(data, offset); break;
|
||||
case FFMPEG_SWITCH_OPUS: offset = ffmpeg_custom_seek_switch_opus(data, offset); break;
|
||||
case FFMPEG_BGW_ATRAC3: offset = ffmpeg_custom_seek_bgw_atrac3(data, offset); break;
|
||||
//case FFMPEG_EA_SCHL: offset = ffmpeg_custom_seek_ea_schl(data, offset); break;
|
||||
//case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break;
|
||||
default: offset = ffmpeg_custom_seek_standard(data, offset); break;
|
||||
|
@ -304,6 +309,7 @@ static int64_t ffmpeg_size(ffmpeg_codec_data * data) {
|
|||
switch(data->config.type) {
|
||||
case FFMPEG_EA_XMA: bytes = ffmpeg_custom_size_eaxma(data); break;
|
||||
case FFMPEG_SWITCH_OPUS: bytes = ffmpeg_custom_size_switch_opus(data); break;
|
||||
case FFMPEG_BGW_ATRAC3: bytes = ffmpeg_custom_size_bgw_atrac3(data); break;
|
||||
//case FFMPEG_EA_SCHL: bytes = ffmpeg_custom_size_ea_schl(data); break;
|
||||
//case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break;
|
||||
default: bytes = ffmpeg_custom_size_standard(data); break;
|
||||
|
@ -800,6 +806,9 @@ void free_ffmpeg(ffmpeg_codec_data *data) {
|
|||
close_streamfile(data->streamfile);
|
||||
data->streamfile = NULL;
|
||||
}
|
||||
if (data->config.key) {
|
||||
free(data->config.key);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,9 @@ int ffmpeg_custom_read_standard(ffmpeg_codec_data *data, uint8_t *buf, int buf_s
|
|||
}
|
||||
|
||||
int64_t ffmpeg_custom_seek_standard(ffmpeg_codec_data *data, int64_t virtual_offset) {
|
||||
data->real_offset = data->real_start + (virtual_offset - data->header_size);
|
||||
int64_t seek_virtual_offset = virtual_offset - data->header_size;
|
||||
|
||||
data->real_offset = data->real_start + seek_virtual_offset;
|
||||
return virtual_offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,10 @@ int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int bu
|
|||
int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset);
|
||||
int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data);
|
||||
|
||||
int ffmpeg_custom_read_bgw_atrac3(ffmpeg_codec_data *data, uint8_t *buf, int buf_size);
|
||||
int64_t ffmpeg_custom_seek_bgw_atrac3(ffmpeg_codec_data *data, int64_t virtual_offset);
|
||||
int64_t ffmpeg_custom_size_bgw_atrac3(ffmpeg_codec_data *data);
|
||||
|
||||
//int ffmpeg_custom_read_ea_schl(ffmpeg_codec_data *data, uint8_t *buf, int buf_size);
|
||||
//int64_t ffmpeg_custom_seek_ea_schl(ffmpeg_codec_data *data, int64_t virtual_offset);
|
||||
//int64_t ffmpeg_custom_size_ea_schl(ffmpeg_codec_data *data);
|
||||
|
|
|
@ -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
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
|
||||
#define EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK 3 /* only seen up to 3 (Dante's Inferno) */
|
||||
#define EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK 4 /* normally max 3 (Dante's Inferno), ~14 (1 stream) in Burnout Paradise */
|
||||
#define EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK 4 /* XMA2 max is 8ch = 4 * 2ch */
|
||||
#define EAXMA_XMA_PACKET_SIZE 0x800
|
||||
#define EAXMA_XMA_BUFFER_SIZE (EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK * EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK * EAXMA_XMA_PACKET_SIZE)
|
||||
|
@ -48,7 +48,8 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size
|
|||
if (max_packets == 0) goto fail;
|
||||
|
||||
if (max_packets * num_streams * EAXMA_XMA_PACKET_SIZE > EAXMA_XMA_BUFFER_SIZE) {
|
||||
VGM_LOG("EA XMA: block too big at %lx\n", (off_t)real_offset);
|
||||
VGM_LOG("EA XMA: block too big (%i * %i * 0x%x = 0x%x vs max 0x%x) at %lx\n",
|
||||
max_packets,num_streams,EAXMA_XMA_PACKET_SIZE, max_packets*num_streams*EAXMA_XMA_PACKET_SIZE, EAXMA_XMA_BUFFER_SIZE,(off_t)real_offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -134,12 +135,13 @@ fail:
|
|||
|
||||
int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset) {
|
||||
int64_t real_offset, virtual_base;
|
||||
int64_t current_virtual_offset = data->virtual_offset;
|
||||
int64_t current_virtual_offset = data->virtual_offset - data->header_size;
|
||||
int64_t seek_virtual_offset = virtual_offset - data->header_size;
|
||||
|
||||
/* Find SNS block start closest to offset. ie. virtual_offset 0x1A10 could mean SNS blocks
|
||||
* of 0x456+0x820 padded to 0x800+0x1000 (base) + 0x210 (extra for reads), thus real_offset = 0xC76 */
|
||||
|
||||
if (virtual_offset > current_virtual_offset) { /* seek after current: start from current block */
|
||||
if (seek_virtual_offset > current_virtual_offset) { /* seek after current: start from current block */
|
||||
real_offset = data->real_offset;
|
||||
virtual_base = data->virtual_base;
|
||||
}
|
||||
|
@ -150,7 +152,7 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset
|
|||
|
||||
|
||||
/* find target block */
|
||||
while (virtual_base < virtual_offset) {
|
||||
while (virtual_base < seek_virtual_offset) {
|
||||
size_t data_size, extra_size = 0;
|
||||
size_t block_size = read_32bitBE(real_offset, data->streamfile);
|
||||
|
||||
|
@ -159,7 +161,7 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset
|
|||
extra_size = EAXMA_XMA_PACKET_SIZE - (data_size % EAXMA_XMA_PACKET_SIZE);
|
||||
|
||||
/* stop if virtual_offset lands inside current block */
|
||||
if (data_size + extra_size > virtual_offset)
|
||||
if (data_size + extra_size > seek_virtual_offset)
|
||||
break;
|
||||
|
||||
real_offset += (block_size & 0x00FFFFFF);
|
||||
|
|
|
@ -101,10 +101,11 @@ int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int bu
|
|||
int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset) {
|
||||
int64_t real_offset, virtual_base;
|
||||
int64_t current_virtual_offset = data->virtual_offset;
|
||||
int64_t seek_virtual_offset = virtual_offset - data->header_size;
|
||||
|
||||
/* find Wwise block start closest to offset; a 0x1E8 block expands to 0x1D + 0x1E0 (oggs + data) */
|
||||
|
||||
if (virtual_offset > current_virtual_offset) { /* seek after current: start from current block */
|
||||
if (seek_virtual_offset > current_virtual_offset) { /* seek after current: start from current block */
|
||||
real_offset = data->real_offset;
|
||||
virtual_base = data->virtual_base;
|
||||
}
|
||||
|
@ -117,14 +118,14 @@ int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_
|
|||
|
||||
|
||||
/* find target block */
|
||||
while (virtual_base < virtual_offset) {
|
||||
while (virtual_base < seek_virtual_offset) {
|
||||
size_t extra_size;
|
||||
size_t data_size = read_32bitBE(real_offset, data->streamfile);
|
||||
|
||||
extra_size = 0x1b + (int)(data_size / 0xFF + 1); /* OggS page: base size + lacing values */
|
||||
|
||||
/* stop if virtual_offset lands inside current block */
|
||||
if (data_size + extra_size > virtual_offset)
|
||||
if (data_size + extra_size > seek_virtual_offset)
|
||||
break;
|
||||
|
||||
real_offset += 0x04 + 0x04 + data_size;
|
||||
|
@ -332,8 +333,8 @@ fail:
|
|||
static size_t make_opus_comment(uint8_t * buf, int buf_size) {
|
||||
size_t comment_size;
|
||||
int vendor_string_length, user_comment_0_length;
|
||||
char * vendor_string = "vgmstream";
|
||||
char * user_comment_0_string = "vgmstream Opus converter";
|
||||
const char * vendor_string = "vgmstream";
|
||||
const char * user_comment_0_string = "vgmstream Opus converter";
|
||||
vendor_string_length = strlen(vendor_string);
|
||||
user_comment_0_length = strlen(user_comment_0_string);
|
||||
|
||||
|
|
|
@ -4,6 +4,31 @@
|
|||
#ifdef VGM_USE_G719
|
||||
#include "../stack_alloc.h"
|
||||
|
||||
g719_codec_data *init_g719(int channel_count, int frame_size) {
|
||||
int i;
|
||||
g719_codec_data *data = NULL;
|
||||
|
||||
data = calloc(channel_count, sizeof(g719_codec_data)); /* one decoder per channel */
|
||||
if (!data) goto fail;
|
||||
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
data[i].handle = g719_init(frame_size); /* Siren 22 == 22khz bandwidth */
|
||||
if (!data[i].handle) goto fail;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
fail:
|
||||
if (data) {
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
g719_free(data[i].handle);
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void decode_g719(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
|
||||
g719_codec_data *data = vgmstream->codec_data;
|
||||
|
|
|
@ -121,7 +121,7 @@ g72x_init_state(
|
|||
* computes the estimated signal from 6-zero predictor.
|
||||
*
|
||||
*/
|
||||
int
|
||||
static int
|
||||
predictor_zero(
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
|
@ -139,7 +139,7 @@ predictor_zero(
|
|||
* computes the estimated signal from 2-pole predictor.
|
||||
*
|
||||
*/
|
||||
int
|
||||
static int
|
||||
predictor_pole(
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
|
@ -152,7 +152,7 @@ predictor_pole(
|
|||
* computes the quantization step size of the adaptive quantizer.
|
||||
*
|
||||
*/
|
||||
int
|
||||
static int
|
||||
step_size(
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
|
@ -181,7 +181,7 @@ step_size(
|
|||
* codeword 'i' and quantization step size scale factor 'y'.
|
||||
* Multiplication is performed in log base 2 domain as addition.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
reconstruct(
|
||||
int sign, /* 0 for non-negative value */
|
||||
int dqln, /* G.72x codeword */
|
||||
|
@ -210,7 +210,7 @@ reconstruct(
|
|||
*
|
||||
* updates the state variables for each output code
|
||||
*/
|
||||
void
|
||||
static void
|
||||
update(
|
||||
/*int code_size,*/ /* distinguish 723_40 with others */
|
||||
int y, /* quantizer step size */
|
||||
|
@ -427,7 +427,7 @@ static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
|
|||
* returns the resulting linear PCM, A-law or u-law value.
|
||||
* return -1 for unknown out_coding value.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
g721_decoder(
|
||||
int i,
|
||||
struct g72x_state *state_ptr)
|
||||
|
|
|
@ -3,6 +3,32 @@
|
|||
|
||||
#ifdef VGM_USE_G7221
|
||||
|
||||
g7221_codec_data * init_g7221(int channel_count, int frame_size) {
|
||||
int i;
|
||||
g7221_codec_data *data = NULL;
|
||||
|
||||
data = calloc(channel_count, sizeof(g7221_codec_data)); /* one decoder per channel */
|
||||
if (!data) goto fail;
|
||||
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
data[i].handle = g7221_init(frame_size, 14000); /* Siren 14 == 14khz bandwidth */
|
||||
if (!data[i].handle) goto fail;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
fail:
|
||||
if (data) {
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
g7221_free(data[i].handle);
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void decode_g7221(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
|
||||
g7221_codec_data *data = vgmstream->codec_data;
|
||||
|
|
|
@ -7,17 +7,18 @@
|
|||
*
|
||||
* All IMAs are mostly the same with these variations:
|
||||
* - interleave: blocks and channels are handled externally (layouts) or internally (mixed channels)
|
||||
* - block header: none (external), normal (4 bytes of history 16b + step 16b) or others; per channel/global
|
||||
* - block header: none (external), normal (4 bytes of history 16b + step 8b + reserved 8b) or others; per channel/global
|
||||
* - expand type: ms-ima style or others; low or high nibble first
|
||||
*
|
||||
* todo:
|
||||
* MS IMAs have the last sample of the prev block in the block header. In Microsoft implementation, the header sample
|
||||
* MS IMAs have the last sample of the prev block in the block header. In Microsoft's implementation, the header sample
|
||||
* is written first and last sample is skipped (since they match). vgmstream ignores the header sample and
|
||||
* writes the last one instead. This means the very first sample in the first header in a stream is incorrectly skipped.
|
||||
* Header step should be 8 bit.
|
||||
* Officially defined in "Microsoft Multimedia Standards Update" doc (RIFFNEW.pdf).
|
||||
*/
|
||||
|
||||
static const int32_t ADPCMTable[89] =
|
||||
{
|
||||
static const int ADPCMTable[89] = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
16, 17, 19, 21, 23, 25, 28, 31,
|
||||
34, 37, 41, 45, 50, 55, 60, 66,
|
||||
|
@ -32,48 +33,32 @@ static const int32_t ADPCMTable[89] =
|
|||
32767
|
||||
};
|
||||
|
||||
static const int IMA_IndexTable[16] =
|
||||
{
|
||||
static const int IMA_IndexTable[16] = {
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
-1, -1, -1, -1, 2, 4, 6, 8
|
||||
};
|
||||
|
||||
|
||||
/* Original IMA */
|
||||
static void ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
/* Standard IMA (most common) */
|
||||
static void std_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
//"original" ima nibble expansion
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_decoded = *hist1 << 3;
|
||||
step = ADPCMTable[*step_index];
|
||||
delta = step * (sample_nibble & 7) * 2 + step;
|
||||
if (sample_nibble & 8)
|
||||
sample_decoded -= delta;
|
||||
else
|
||||
sample_decoded += delta;
|
||||
/* calculate diff = [signed] (step / 8) + (step / 4) + (step / 2) + (step) [when code = 4+2+1]
|
||||
* simplified through math, using bitwise ops to avoid rounding:
|
||||
* diff = (code + 1/2) * (step / 4)
|
||||
* > diff = (step * nibble / 4) + (step / 8)
|
||||
* > diff = (((step * nibble) + (step / 2)) / 4) */
|
||||
|
||||
*hist1 = clamp16(sample_decoded >> 3);
|
||||
*step_index += IMA_IndexTable[sample_nibble];
|
||||
if (*step_index < 0) *step_index=0;
|
||||
if (*step_index > 88) *step_index=88;
|
||||
}
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; /* ADPCM code */
|
||||
sample_decoded = *hist1; /* predictor value */
|
||||
step = ADPCMTable[*step_index]; /* current step */
|
||||
|
||||
/* Microsoft's IMA (most common) */
|
||||
static void ms_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_decoded = *hist1;
|
||||
step = ADPCMTable[*step_index];
|
||||
delta = step >> 3;
|
||||
if (sample_nibble & 1) delta += step >> 2;
|
||||
if (sample_nibble & 2) delta += step >> 1;
|
||||
if (sample_nibble & 4) delta += step;
|
||||
if (sample_nibble & 8)
|
||||
sample_decoded -= delta;
|
||||
else
|
||||
sample_decoded += delta;
|
||||
if (sample_nibble & 8) delta = -delta;
|
||||
sample_decoded += delta;
|
||||
|
||||
*hist1 = clamp16(sample_decoded);
|
||||
*step_index += IMA_IndexTable[sample_nibble];
|
||||
|
@ -81,21 +66,20 @@ static void ms_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, i
|
|||
if (*step_index > 88) *step_index=88;
|
||||
}
|
||||
|
||||
/* Apple's MS IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend) */
|
||||
static void ms_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int16_t * hist1, int32_t * step_index) {
|
||||
/* Apple's IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend?) */
|
||||
static void std_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int16_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_decoded = *hist1;
|
||||
step = ADPCMTable[*step_index];
|
||||
|
||||
delta = step >> 3;
|
||||
if (sample_nibble & 1) delta += step >> 2;
|
||||
if (sample_nibble & 2) delta += step >> 1;
|
||||
if (sample_nibble & 4) delta += step;
|
||||
if (sample_nibble & 8)
|
||||
sample_decoded -= delta;
|
||||
else
|
||||
sample_decoded += delta;
|
||||
if (sample_nibble & 8) delta = -delta;
|
||||
sample_decoded += delta;
|
||||
|
||||
*hist1 = clamp16(sample_decoded); //no need for this actually
|
||||
*step_index += IMA_IndexTable[sample_nibble];
|
||||
|
@ -103,40 +87,61 @@ static void ms_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset
|
|||
if (*step_index > 88) *step_index=88;
|
||||
}
|
||||
|
||||
/* update step_index before doing current sample */
|
||||
/* 3DS IMA (Mario Golf, Mario Tennis; maybe other Camelot games) */
|
||||
static void n3ds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_decoded = *hist1;
|
||||
step = ADPCMTable[*step_index];
|
||||
|
||||
sample_decoded = sample_decoded << 3;
|
||||
delta = step * (sample_nibble & 7) * 2 + step; /* custom */
|
||||
if (sample_nibble & 8) delta = -delta;
|
||||
sample_decoded += delta;
|
||||
sample_decoded = sample_decoded >> 3;
|
||||
|
||||
*hist1 = clamp16(sample_decoded);
|
||||
*step_index += IMA_IndexTable[sample_nibble];
|
||||
if (*step_index < 0) *step_index=0;
|
||||
if (*step_index > 88) *step_index=88;
|
||||
}
|
||||
|
||||
/* The Incredibles PC, updates step_index before doing current sample */
|
||||
static void snds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_decoded = *hist1;
|
||||
|
||||
*step_index += IMA_IndexTable[sample_nibble];
|
||||
if (*step_index < 0) *step_index=0;
|
||||
if (*step_index > 88) *step_index=88;
|
||||
|
||||
step = ADPCMTable[*step_index];
|
||||
delta = (sample_nibble & 7) * step / 4 + step / 8;
|
||||
|
||||
delta = (sample_nibble & 7) * step / 4 + step / 8; /* standard IMA */
|
||||
if (sample_nibble & 8) delta = -delta;
|
||||
sample_decoded = *hist1 + delta;
|
||||
sample_decoded += delta;
|
||||
|
||||
*hist1 = clamp16(sample_decoded);
|
||||
}
|
||||
|
||||
/* algorithm by aluigi, unsure if it's a known IMA variation */
|
||||
/* Omikron: The Nomad Soul, algorithm by aluigi */
|
||||
static void otns_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_decoded = *hist1;
|
||||
step = ADPCMTable[*step_index];
|
||||
|
||||
delta = 0;
|
||||
if(sample_nibble & 4) delta = step << 2;
|
||||
if(sample_nibble & 2) delta += step << 1;
|
||||
if(sample_nibble & 1) delta += step;
|
||||
delta >>= 2;
|
||||
if(sample_nibble & 8)
|
||||
sample_decoded -= delta;
|
||||
else
|
||||
sample_decoded += delta;
|
||||
if (sample_nibble & 8) delta = -delta;
|
||||
sample_decoded += delta;
|
||||
|
||||
*hist1 = clamp16(sample_decoded);
|
||||
*step_index += IMA_IndexTable[sample_nibble];
|
||||
|
@ -144,283 +149,53 @@ static void otns_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset,
|
|||
if (*step_index > 88) *step_index=88;
|
||||
}
|
||||
|
||||
/* Ubisoft games, algorithm by Zench (https://bitbucket.org/Zenchreal/decubisnd) */
|
||||
static void ubi_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_decoded = *hist1;
|
||||
step = ADPCMTable[*step_index];
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16?
|
||||
int step_index = stream->adpcm_step_index;
|
||||
delta = (((sample_nibble & 7) * 2 + 1) * step) >> 3; /* custom */
|
||||
if (sample_nibble & 8) delta = -delta;
|
||||
sample_decoded += delta;
|
||||
|
||||
//external interleave
|
||||
|
||||
//normal header
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset;
|
||||
|
||||
hist1 = read_16bitLE(header_offset,stream->streamfile);
|
||||
step_index = read_16bitLE(header_offset+2,stream->streamfile);
|
||||
|
||||
//todo clip step_index?
|
||||
}
|
||||
|
||||
for (i=first_sample,sample_count=0; 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;
|
||||
*hist1 = clamp16(sample_decoded);
|
||||
*step_index += IMA_IndexTable[sample_nibble];
|
||||
if (*step_index < 0) *step_index=0;
|
||||
if (*step_index > 88) *step_index=88;
|
||||
}
|
||||
|
||||
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
/* ************************************ */
|
||||
/* DVI/IMA */
|
||||
/* ************************************ */
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_16;//todo unneeded 16?
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
//external interleave
|
||||
|
||||
//normal header
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset;
|
||||
|
||||
hist1 = read_16bitLE(header_offset,stream->streamfile);
|
||||
step_index = read_8bit(header_offset+2,stream->streamfile); //todo use 8bit in all MS IMA?
|
||||
|
||||
//todo clip step_index?
|
||||
}
|
||||
|
||||
for (i=first_sample,sample_count=0; 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) {
|
||||
/* Standard DVI/IMA ADPCM (as in, ADPCM recommended by the IMA using Intel/DVI's implementation).
|
||||
* Configurable: stereo or mono/interleave nibbles, and high or low nibble first.
|
||||
* For vgmstream, low nibble is called "IMA ADPCM" and high nibble is "DVI IMA ADPCM" (same thing though). */
|
||||
void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first) {
|
||||
int i, sample_count = 0;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
//internal interleave (0x24 size), mono
|
||||
int block_samples = (0x24 - 0x4) * 2; /* block size - header, 2 samples per byte */
|
||||
first_sample = first_sample % block_samples;
|
||||
/* external interleave */
|
||||
|
||||
//normal header
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset;
|
||||
/* no header (external setup), pre-clamp for wrong values */
|
||||
if (step_index < 0) step_index=0;
|
||||
if (step_index > 88) step_index=88;
|
||||
|
||||
hist1 = read_16bitLE(header_offset,stream->streamfile);
|
||||
step_index = read_16bitLE(header_offset+2,stream->streamfile);
|
||||
if (step_index < 0) step_index=0;
|
||||
if (step_index > 88) step_index=88;
|
||||
/* decode nibbles */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) {
|
||||
off_t byte_offset = is_stereo ?
|
||||
stream->offset + i : /* stereo: one nibble per channel */
|
||||
stream->offset + i/2; /* mono: consecutive nibbles */
|
||||
int nibble_shift = is_high_first ?
|
||||
is_stereo ? (!(channel&1) ? 4:0) : (!(i&1) ? 4:0) : /* even = high, odd = low */
|
||||
is_stereo ? (!(channel&1) ? 0:4) : (!(i&1) ? 0:4); /* even = low, odd = high */
|
||||
|
||||
//must write history from header as last nibble/sample in block is almost always 0 / not encoded
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count += channelspacing;
|
||||
first_sample += 1;
|
||||
samples_to_do -= 1;
|
||||
}
|
||||
|
||||
for (i=first_sample; i < first_sample + samples_to_do; i++) { /* first_sample + samples_to_do should be block_samples at most */
|
||||
off_t byte_offset = stream->offset + 4 + (i-1)/2;
|
||||
int nibble_shift = ((i-1)&1?4:0); //low nibble first
|
||||
|
||||
//last nibble/sample in block is ignored (next header sample contains it)
|
||||
if (i < block_samples) {
|
||||
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count+=channelspacing;
|
||||
}
|
||||
}
|
||||
|
||||
//internal interleave: increment offset on complete frame; layout test so it works in full mono
|
||||
// (EA SCHl, internally moves offset) or full interleave (XBOX ADS, externally moves offset in layout)
|
||||
if (i == block_samples && vgmstream->layout_type != layout_interleave)
|
||||
stream->offset += 0x24; /*full mono */
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
//external interleave
|
||||
|
||||
//no header
|
||||
|
||||
for (i=first_sample,sample_count=0; 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);
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
}
|
||||
|
||||
|
@ -428,35 +203,7 @@ void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
|||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
/* basically DVI stereo (high=L + low=R nibbles) and DVI mono (high=L, low=L) all-in-one, can be simplified/removed */
|
||||
void decode_eacs_ima(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);//todo pass externally for consistency
|
||||
int i, sample_count;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
//external interleave
|
||||
|
||||
//no header
|
||||
|
||||
for (i=first_sample,sample_count=0; 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) {
|
||||
void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
|
@ -470,7 +217,7 @@ void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
|||
off_t byte_offset = stream->offset + i/2;
|
||||
int nibble_shift = (i&1?4:0); //low nibble order
|
||||
|
||||
ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
n3ds_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
}
|
||||
|
||||
|
@ -478,38 +225,6 @@ void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
|||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
|
||||
int16_t hist1 = stream->adpcm_history1_16;//todo unneeded 16?
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
off_t packet_offset = stream->offset + first_sample/64*34;
|
||||
|
||||
//semi-internal interleave //todo what
|
||||
int block_samples = 64;
|
||||
first_sample = first_sample % block_samples;
|
||||
|
||||
//2-byte header
|
||||
if (first_sample == 0) {
|
||||
hist1 = (int16_t)((uint16_t)read_16bitBE(packet_offset,stream->streamfile) & 0xff80);
|
||||
step_index = read_8bit(packet_offset+1,stream->streamfile) & 0x7f;
|
||||
|
||||
//todo no clamp
|
||||
}
|
||||
|
||||
for (i=first_sample,sample_count=0; 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) {
|
||||
int i, sample_count;
|
||||
|
||||
|
@ -556,6 +271,300 @@ void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
|
|||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
/* ************************************ */
|
||||
/* MS IMA */
|
||||
/* ************************************ */
|
||||
|
||||
/* IMA with frames with header and custom sizes */
|
||||
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
|
||||
int i, sample_count;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
//internal interleave (configurable size), mixed channels (4 byte per ch)
|
||||
int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels;
|
||||
first_sample = first_sample % block_samples;
|
||||
|
||||
//normal header (per channel)
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset + 4*channel;
|
||||
|
||||
hist1 = read_16bitLE(header_offset,stream->streamfile);
|
||||
step_index = read_8bit(header_offset+2,stream->streamfile);
|
||||
if (step_index < 0) step_index=0;
|
||||
if (step_index > 88) step_index=88;
|
||||
}
|
||||
|
||||
for (i=first_sample,sample_count=0; 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) {
|
||||
int i, sample_count;
|
||||
|
||||
|
@ -581,7 +590,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
|
|||
off_t byte_offset = stream->offset + 4*vgmstream->channels + 2*channel + i/4*2*vgmstream->channels + (i%4)/2;//2-byte per channel
|
||||
int nibble_shift = (i&1?4:0); //low nibble first
|
||||
|
||||
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
}
|
||||
|
||||
|
@ -626,7 +635,7 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample *
|
|||
|
||||
//last nibble/sample in block is ignored (next header sample contains it)
|
||||
if (i < block_samples) {
|
||||
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count+=channelspacing;
|
||||
//todo atenuation: apparently from hcs's analysis Wwise IMA decodes nibbles slightly different, reducing dbs
|
||||
|
@ -667,7 +676,7 @@ void decode_ref_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * ou
|
|||
off_t byte_offset = stream->offset + 4*vgmstream->channels + block_channel_size*channel + i/2;
|
||||
int nibble_shift = (i&1?4:0); //low nibble first
|
||||
|
||||
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
}
|
||||
|
||||
|
@ -702,7 +711,7 @@ void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
|||
off_t byte_offset = stream->offset + 4 + i/2;
|
||||
int nibble_shift = (i&1?4:0); //low nibble first
|
||||
|
||||
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
}
|
||||
|
||||
|
@ -714,6 +723,67 @@ void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
|||
}
|
||||
|
||||
|
||||
/* DVI stereo/mono with some mini header and sample output */
|
||||
void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int i, sample_count = 0;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
//internal interleave
|
||||
|
||||
//header in the beginning of the stream
|
||||
if (stream->channel_start_offset == stream->offset) {
|
||||
int version, big_endian, header_samples, max_samples_to_do;
|
||||
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
||||
off_t offset = stream->offset;
|
||||
|
||||
/* header fields mostly unknown (vary a lot or look like flags),
|
||||
* 0x07 0x06 = major/minor tool version?, 0x0c: stereo flag? */
|
||||
version = read_8bit(offset + 0x00, stream->streamfile);
|
||||
big_endian = version < 5; //todo and sb.big_endian?
|
||||
read_16bit = big_endian ? read_16bitBE : read_16bitLE;
|
||||
|
||||
header_samples = read_16bit(offset + 0x0E, stream->streamfile); /* always 10 (per channel) */
|
||||
hist1 = read_16bit(offset + 0x10 + channel*0x04,stream->streamfile);
|
||||
step_index = read_8bit(offset + 0x12 + channel*0x04,stream->streamfile);
|
||||
offset += 0x10 + 0x08 + 0x04; //todo v6 has extra 0x08?
|
||||
|
||||
/* write PCM samples, must be written to match header's num_samples (hist mustn't) */
|
||||
max_samples_to_do = ((samples_to_do > header_samples) ? header_samples : samples_to_do);
|
||||
for (i = first_sample; i < max_samples_to_do; i++, sample_count += channelspacing) {
|
||||
outbuf[sample_count] = read_16bit(offset + channel*sizeof(sample) + i*channelspacing*sizeof(sample),stream->streamfile);
|
||||
first_sample++;
|
||||
samples_to_do--;
|
||||
}
|
||||
|
||||
/* header done */
|
||||
if (i == header_samples) {
|
||||
stream->offset = offset + header_samples*channelspacing*sizeof(sample);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
first_sample -= 10; //todo fix hack (needed to adjust nibble offset below)
|
||||
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) {
|
||||
off_t byte_offset = channelspacing == 1 ?
|
||||
stream->offset + i/2 : /* mono mode */
|
||||
stream->offset + i; /* stereo mode */
|
||||
int nibble_shift = channelspacing == 1 ?
|
||||
(!(i%2) ? 4:0) : /* mono mode (high first) */
|
||||
(channel==0 ? 4:0); /* stereo mode (high=L,low=R) */
|
||||
|
||||
ubi_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1); /* all samples are written */
|
||||
}
|
||||
|
||||
//external interleave
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
|
||||
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) {
|
||||
/* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
|
||||
|
@ -724,3 +794,19 @@ size_t ima_bytes_to_samples(size_t bytes, int channels) {
|
|||
/* 2 samples per byte (2 nibbles) in stereo or mono config */
|
||||
return bytes / channels * 2;
|
||||
}
|
||||
|
||||
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset) {
|
||||
int version, big_endian, header_samples;
|
||||
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
||||
size_t header_size = 0;
|
||||
|
||||
version = read_8bit(offset + 0x00, streamFile);
|
||||
big_endian = version < 5; //todo and sb.big_endian?
|
||||
read_16bit = big_endian ? read_16bitBE : read_16bitLE;
|
||||
|
||||
header_samples = read_16bit(offset + 0x0E, streamFile); /* always 10 (per channel) */
|
||||
header_size += 0x10 + 0x04 * channels + 0x04; //todo v6 has extra 0x08?
|
||||
header_size += header_samples * channels * sizeof(sample);
|
||||
|
||||
return header_samples + ima_bytes_to_samples(bytes - header_size, channels);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
|
|||
{
|
||||
int current_data_size = info.frame_size;
|
||||
int current_padding = 0;
|
||||
if (info.layer == 3 && data->config.fsb_padding) { /* FSB padding for Layer III */
|
||||
/* FSB padding for Layer III or multichannel Layer II */
|
||||
if ((info.layer == 3 && data->config.fsb_padding) || data->config.fsb_padding == 16) {
|
||||
current_padding = (current_data_size % data->config.fsb_padding)
|
||||
? data->config.fsb_padding - (current_data_size % data->config.fsb_padding)
|
||||
: 0;
|
||||
|
@ -59,7 +60,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
|
|||
case MPEG_STANDARD:
|
||||
case MPEG_AHX:
|
||||
case MPEG_EA:
|
||||
if (data->channels_per_frame != data->config.channels)
|
||||
if (info.channels != data->config.channels)
|
||||
goto fail; /* no multichannel expected */
|
||||
break;
|
||||
|
||||
|
@ -70,6 +71,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
|
|||
|
||||
//todo: test more: this improves the output, but seems formats aren't usually prepared
|
||||
// (and/or the num_samples includes all possible samples in file, so by discarding some it'll reach EOF)
|
||||
// FSBs (with FMOD DLLs) don't seem to need it, even when files contain garbage at the beginning
|
||||
#if 0
|
||||
/* set encoder delay (samples to skip at the beginning of a stream) if needed, which varies with encoder used */
|
||||
switch(data->type) {
|
||||
|
@ -87,7 +89,8 @@ fail:
|
|||
|
||||
|
||||
/* writes data to the buffer and moves offsets */
|
||||
int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data) {
|
||||
int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) {
|
||||
mpeg_custom_stream *ms = data->streams[num_stream];
|
||||
mpeg_frame_info info;
|
||||
size_t current_data_size = 0;
|
||||
size_t current_padding = 0;
|
||||
|
@ -108,9 +111,9 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
|
|||
goto fail;
|
||||
current_data_size = info.frame_size;
|
||||
|
||||
/* get FSB padding for Layer III (Layer II doesn't use it, and Layer I doesn't seem to be supported) */
|
||||
/* Padding sometimes contains garbage like the next frame header so we can't feed it to mpg123 or it gets confused. */
|
||||
if (info.layer == 3 && data->config.fsb_padding) {
|
||||
/* get FSB padding for Layer III or multichannel Layer II (Layer I doesn't seem to be supported)
|
||||
* Padding sometimes contains garbage like the next frame header so we can't feed it to mpg123 or it gets confused. */
|
||||
if ((info.layer == 3 && data->config.fsb_padding) || data->config.fsb_padding == 16) {
|
||||
current_padding = (current_data_size % data->config.fsb_padding)
|
||||
? data->config.fsb_padding - (current_data_size % data->config.fsb_padding)
|
||||
: 0;
|
||||
|
@ -135,14 +138,14 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
|
|||
current_data_size = info.frame_size;
|
||||
break;
|
||||
}
|
||||
if (!current_data_size || current_data_size > data->buffer_size) {
|
||||
if (!current_data_size || current_data_size > ms->buffer_size) {
|
||||
VGM_LOG("MPEG: incorrect data_size 0x%x\n", current_data_size);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* read single frame */
|
||||
data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset, current_data_size, stream->streamfile);
|
||||
ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset, current_data_size, stream->streamfile);
|
||||
|
||||
|
||||
/* update offsets */
|
||||
|
@ -233,6 +236,7 @@ int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info *
|
|||
case 384: info->frame_size = (12l * info->bit_rate * 1000l / info->sample_rate + padding) * 4; break;
|
||||
case 576: info->frame_size = (72l * info->bit_rate * 1000l / info->sample_rate + padding); break;
|
||||
case 1152: info->frame_size = (144l * info->bit_rate * 1000l / info->sample_rate + padding); break;
|
||||
default: goto fail;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
#ifdef VGM_USE_MPEG
|
||||
#define MPEG_AHX_EXPECTED_FRAME_SIZE 0x414
|
||||
|
||||
static int ahx_decrypt_type08(mpeg_codec_data *data);
|
||||
static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config);
|
||||
|
||||
/* writes data to the buffer and moves offsets, transforming AHX frames as needed */
|
||||
int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data) {
|
||||
int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) {
|
||||
/* 0xFFF5E0C0 header: frame size 0x414 (160kbps, 22050Hz) but they actually are much shorter */
|
||||
mpeg_custom_stream *ms = data->streams[num_stream];
|
||||
size_t current_data_size = 0;
|
||||
size_t file_size = get_streamfile_size(stream->streamfile);
|
||||
|
||||
|
@ -33,22 +34,22 @@ int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data)
|
|||
next_offset++;
|
||||
}
|
||||
}
|
||||
if (!current_data_size || current_data_size > data->buffer_size || current_data_size > MPEG_AHX_EXPECTED_FRAME_SIZE) {
|
||||
if (!current_data_size || current_data_size > ms->buffer_size || current_data_size > MPEG_AHX_EXPECTED_FRAME_SIZE) {
|
||||
VGM_LOG("MPEG AHX: incorrect data_size 0x%x\n", current_data_size);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* 0-fill up to expected size to keep mpg123 happy */
|
||||
data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset,current_data_size,stream->streamfile);
|
||||
memset(data->buffer + data->bytes_in_buffer,0, MPEG_AHX_EXPECTED_FRAME_SIZE - data->bytes_in_buffer);
|
||||
data->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE;
|
||||
ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset,current_data_size,stream->streamfile);
|
||||
memset(ms->buffer + ms->bytes_in_buffer,0, MPEG_AHX_EXPECTED_FRAME_SIZE - ms->bytes_in_buffer);
|
||||
ms->bytes_in_buffer = MPEG_AHX_EXPECTED_FRAME_SIZE;
|
||||
|
||||
|
||||
/* decrypt if needed */
|
||||
switch(data->config.encryption) {
|
||||
case 0x00: break;
|
||||
case 0x08: ahx_decrypt_type08(data); break;
|
||||
case 0x08: ahx_decrypt_type08(ms->buffer, &data->config); break;
|
||||
default:
|
||||
VGM_LOG("MPEG AHX: unknown encryption 0x%x\n", data->config.encryption);
|
||||
break; /* garbled frame */
|
||||
|
@ -66,7 +67,7 @@ fail:
|
|||
}
|
||||
|
||||
/* Decrypts an AHX type 0x08 (keystring) encrypted frame. Algorithm by Thealexbarney */
|
||||
static int ahx_decrypt_type08(mpeg_codec_data *data) {
|
||||
static int ahx_decrypt_type08(uint8_t * buffer, mpeg_custom_config *config) {
|
||||
int i, index, encrypted_bits;
|
||||
uint32_t value;
|
||||
uint16_t current_key;
|
||||
|
@ -78,18 +79,18 @@ static int ahx_decrypt_type08(mpeg_codec_data *data) {
|
|||
|
||||
/* read 2b from a bitstream offset to decrypt, and use it as an index to get the key.
|
||||
* AHX encrypted bitstream starts at 107b (0x0d*8+3), every frame, and seem to always use index 2 */
|
||||
value = (uint32_t)get_32bitBE(data->buffer + 0x0d);
|
||||
value = (uint32_t)get_32bitBE(buffer + 0x0d);
|
||||
index = (value >> (32-3-2)) & 0x03;
|
||||
switch(index) {
|
||||
case 0: current_key = 0; break;
|
||||
case 1: current_key = data->config.cri_key1; break;
|
||||
case 2: current_key = data->config.cri_key2; break;
|
||||
case 3: current_key = data->config.cri_key3; break;
|
||||
case 1: current_key = config->cri_key1; break;
|
||||
case 2: current_key = config->cri_key2; break;
|
||||
case 3: current_key = config->cri_key3; break;
|
||||
default: goto fail;
|
||||
}
|
||||
|
||||
/* AHX for DC: 16b, normal: 6b (no idea, probably some Layer II field) */
|
||||
encrypted_bits = data->config.cri_type == 0x10 ? 16 : 6;
|
||||
encrypted_bits = config->cri_type == 0x10 ? 16 : 6;
|
||||
|
||||
/* decrypt next bitstream 2b pairs, up to 16b (max key size):
|
||||
* - read 2b from bitstream (from higher to lower)
|
||||
|
@ -101,7 +102,7 @@ static int ahx_decrypt_type08(mpeg_codec_data *data) {
|
|||
}
|
||||
|
||||
/* write output */
|
||||
put_32bitBE(data->buffer + 0x0d, value);
|
||||
put_32bitBE(buffer + 0x0d, value);
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
|
|
|
@ -170,7 +170,7 @@ int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data,
|
|||
goto fail;
|
||||
current_data_size = info.frame_size;
|
||||
|
||||
data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset, current_data_size, stream->streamfile);
|
||||
ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset, current_data_size, stream->streamfile);
|
||||
|
||||
stream->offset += current_data_size;
|
||||
|
||||
|
|
|
@ -7,11 +7,12 @@
|
|||
* with regular MPEG data and optional PCM blocks. We transform EA-frames to MPEG-frames on the fly
|
||||
* and manually fill the sample PCM sample buffer.
|
||||
*
|
||||
* Layer III MPEG1 uses two granules (data chunks) per frame, while MPEG2/2.5 ("LSF mode") only one. EA-frames
|
||||
* contain one granule, so to reconstruct one MPEG-frame we need two EA-frames (MPEG1) or one (MPEG2).
|
||||
* Layer III MPEG1 uses two granules (data chunks) per frame, while MPEG2/2.5 ("LSF mode") only one.
|
||||
* EA-frames contain one granule, so to reconstruct one MPEG-frame we need two EA-frames (MPEG1) or
|
||||
* one (MPEG2). This is only for our decoder, real EALayer3 would decode EA-frames directly.
|
||||
* EALayer v1 and v2 differ in part of the header, but are mostly the same.
|
||||
*
|
||||
* Reverse engineering: https://bitbucket.org/Zenchreal/ealayer3 (ealayer3.exe decoder)
|
||||
* Reverse engineering by Zench: https://bitbucket.org/Zenchreal/ealayer3 (ealayer3.exe decoder)
|
||||
* Reference: https://www.mp3-tech.org/programmer/docs/mp3_theory.pdf
|
||||
* https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/mpegaudiodec_template.c#L1306
|
||||
*/
|
||||
|
@ -24,27 +25,20 @@
|
|||
#define EALAYER3_MAX_GRANULES 2
|
||||
#define EALAYER3_MAX_CHANNELS 2
|
||||
|
||||
/* helper to simulate a bitstream */
|
||||
typedef struct {
|
||||
uint8_t * buf; /* buffer to read/write*/
|
||||
size_t bufsize; /* max size of the buffer */
|
||||
off_t b_off; /* current offset in bits inside the buffer */
|
||||
off_t offset; /* info only */
|
||||
} ealayer3_bitstream;
|
||||
|
||||
/* parsed info from a single EALayer3 frame */
|
||||
typedef struct {
|
||||
/* EALayer3 v1 header */
|
||||
uint32_t v1_pcm_flag;
|
||||
uint32_t v1_pcm_decode_discard;
|
||||
uint32_t v1_pcm_number;
|
||||
uint32_t v1_pcm_unknown;
|
||||
|
||||
/* EALayer3 v2 header */
|
||||
uint32_t v2_extended_flag;
|
||||
uint32_t v2_stereo_flag;
|
||||
uint32_t v2_unknown; /* unused? */
|
||||
uint32_t v2_frame_size; /* full size including headers and pcm block */
|
||||
uint32_t v2_mode; /* BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3 */
|
||||
uint32_t v2_mode; /* discard mode */
|
||||
uint32_t v2_mode_value; /* samples to use depending on mode */
|
||||
uint32_t v2_pcm_number;
|
||||
uint32_t v2_common_size; /* common header+data size; can be zero */
|
||||
|
@ -79,32 +73,26 @@ typedef struct {
|
|||
} ealayer3_frame_info;
|
||||
|
||||
|
||||
static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf);
|
||||
static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame);
|
||||
static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf);
|
||||
static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf);
|
||||
static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os);
|
||||
static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf);
|
||||
static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b);
|
||||
static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf);
|
||||
static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf);
|
||||
static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os);
|
||||
static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf);
|
||||
|
||||
static int r_bits(ealayer3_bitstream * iw, int num_bits, uint32_t * value);
|
||||
static int w_bits(ealayer3_bitstream * ow, int num_bits, uint32_t value);
|
||||
|
||||
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start);
|
||||
|
||||
/* **************************************************************************** */
|
||||
/* EXTERNAL API */
|
||||
/* **************************************************************************** */
|
||||
|
||||
/* init codec from a EALayer3 frame */
|
||||
/* init codec from an EALayer3 frame */
|
||||
int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type) {
|
||||
int ok;
|
||||
ealayer3_frame_info eaf;
|
||||
ealayer3_bitstream is;
|
||||
vgm_bitstream is = {0};
|
||||
uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE];
|
||||
|
||||
//;VGM_LOG("EAFRAME: EALayer3 init at %lx\n", start_offset);
|
||||
|
||||
if (data->type == MPEG_EAL32P || data->type == MPEG_EAL32S)
|
||||
goto fail; /* untested */
|
||||
//;VGM_LOG("init at %lx\n", start_offset);
|
||||
|
||||
/* get first frame for info */
|
||||
{
|
||||
|
@ -115,20 +103,12 @@ int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset,
|
|||
ok = ealayer3_parse_frame(data, &is, &eaf);
|
||||
if (!ok) goto fail;
|
||||
}
|
||||
|
||||
;VGM_ASSERT(!eaf.mpeg1, "MPEG EAL3: mpeg2 found at 0x%lx\n", start_offset);
|
||||
VGM_ASSERT(!eaf.mpeg1, "MPEG EAL3: mpeg2 found at 0x%lx\n", start_offset); /* untested */
|
||||
|
||||
*coding_type = coding_MPEG_ealayer3;
|
||||
data->channels_per_frame = eaf.channels;
|
||||
data->samples_per_frame = eaf.mpeg1 ? 1152 : 576;
|
||||
|
||||
/* extra checks */
|
||||
if (!data->channels_per_frame || data->config.channels != data->channels_per_frame){
|
||||
VGM_LOG("MPEG EAL3: unknown %i multichannel layout\n", data->config.channels);
|
||||
goto fail; /* unknown layout */
|
||||
}
|
||||
|
||||
|
||||
/* encoder delay: EALayer3 handles this while decoding (skips samples as writes PCM blocks) */
|
||||
|
||||
return 1;
|
||||
|
@ -138,15 +118,20 @@ fail:
|
|||
|
||||
/* writes data to the buffer and moves offsets, transforming EALayer3 frames */
|
||||
int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream) {
|
||||
int ok;
|
||||
off_t current_offset = stream->offset;
|
||||
mpeg_custom_stream *ms = data->streams[num_stream];
|
||||
int ok, granule_found;
|
||||
off_t info_offset = stream->offset;
|
||||
|
||||
ealayer3_frame_info eaf_0, eaf_1;
|
||||
ealayer3_bitstream is_0, is_1, os;
|
||||
vgm_bitstream is_0 = {0}, is_1 = {0}, os = {0};
|
||||
uint8_t ibuf_0[EALAYER3_EA_FRAME_BUFFER_SIZE], ibuf_1[EALAYER3_EA_FRAME_BUFFER_SIZE];
|
||||
|
||||
/* read first frame/granule */
|
||||
{
|
||||
/* read first frame/granule, or PCM-only frame (found alone at the end of SCHl streams) */
|
||||
{
|
||||
//;VGM_LOG("s%i: get granule0 at %lx\n", num_stream,stream->offset);
|
||||
if (!ealayer3_skip_data(stream, data, num_stream, 1))
|
||||
goto fail;
|
||||
|
||||
is_0.buf = ibuf_0;
|
||||
is_0.bufsize = read_streamfile(ibuf_0,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
|
||||
is_0.b_off = 0;
|
||||
|
@ -158,51 +143,54 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
|
|||
if (!ok) goto fail;
|
||||
|
||||
stream->offset += eaf_0.eaframe_size;
|
||||
}
|
||||
//;VGM_LOG("s%i: get granule0 done at %lx (eaf_size=%x, common_size=%x)\n", num_stream,stream->offset, eaf_0.eaframe_size, eaf_0.common_size);
|
||||
|
||||
/* get second frame/granule */
|
||||
if (eaf_0.mpeg1) {
|
||||
int granule1_found;
|
||||
do {
|
||||
is_1.buf = ibuf_1;
|
||||
is_1.bufsize = read_streamfile(ibuf_1,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
|
||||
is_1.b_off = 0;
|
||||
if (!ealayer3_skip_data(stream, data, num_stream, 0))
|
||||
goto fail;
|
||||
|
||||
ok = ealayer3_parse_frame(data, &is_1, &eaf_1);
|
||||
if (!ok) goto fail;
|
||||
}
|
||||
|
||||
ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_1);
|
||||
if (!ok) goto fail;
|
||||
/* get second frame/granule (MPEG1 only) if first granule was found */
|
||||
granule_found = 0;
|
||||
while (eaf_0.common_size && eaf_0.mpeg1 && !granule_found) {
|
||||
//;VGM_LOG("s%i: get granule1 at %lx\n", num_stream,stream->offset);
|
||||
if (!ealayer3_skip_data(stream, data, num_stream, 1))
|
||||
goto fail;
|
||||
|
||||
stream->offset += eaf_1.eaframe_size;
|
||||
is_1.buf = ibuf_1;
|
||||
is_1.bufsize = read_streamfile(ibuf_1,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
|
||||
is_1.b_off = 0;
|
||||
|
||||
ok = ealayer3_parse_frame(data, &is_1, &eaf_1);
|
||||
if (!ok) goto fail;
|
||||
|
||||
/* in V1 sometimes there is a PCM block between two granules, try next */
|
||||
if (eaf_1.v1_pcm_flag == 0xEE)
|
||||
granule1_found = 0;
|
||||
else
|
||||
granule1_found = 1; /* assume it does (bad infinite loops) */
|
||||
}
|
||||
while(!granule1_found);
|
||||
}
|
||||
else {
|
||||
memset(&eaf_1, 0, sizeof(ealayer3_frame_info));
|
||||
ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_1);
|
||||
if (!ok) goto fail;
|
||||
|
||||
stream->offset += eaf_1.eaframe_size;
|
||||
//;VGM_LOG("s%i: get granule0 done at %lx (eaf_size=%x, common_size=%x)\n", num_stream,stream->offset, eaf_0.eaframe_size, eaf_0.common_size);
|
||||
|
||||
if (!ealayer3_skip_data(stream, data, num_stream, 0))
|
||||
goto fail;
|
||||
|
||||
/* in V1a there may be PCM-only frames between granules so read until next one (or parse fails) */
|
||||
if (eaf_1.common_size > 0)
|
||||
granule_found = 1;
|
||||
}
|
||||
|
||||
/* rebuild EALayer frame to MPEG frame */
|
||||
{
|
||||
os.buf = data->buffer;
|
||||
os.bufsize = data->buffer_size;
|
||||
os.buf = ms->buffer;
|
||||
os.bufsize = ms->buffer_size;
|
||||
os.b_off = 0;
|
||||
os.offset = current_offset;
|
||||
os.info_offset = info_offset;
|
||||
|
||||
ok = ealayer3_rebuild_mpeg_frame(&is_0, &eaf_0, &is_1, &eaf_1, &os);
|
||||
if (!ok) goto fail;
|
||||
|
||||
data->bytes_in_buffer = os.b_off / 8; /* wrote full MPEG frame, hopefully */
|
||||
ms->bytes_in_buffer = os.b_off / 8; /* wrote full MPEG frame, hopefully */
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
|
@ -213,31 +201,29 @@ fail:
|
|||
/* INTERNAL HELPERS */
|
||||
/* **************************************************************************** */
|
||||
|
||||
static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf) {
|
||||
static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf) {
|
||||
int ok;
|
||||
|
||||
/* make sure as there is re-parsing in loops */
|
||||
memset(eaf, 0, sizeof(ealayer3_frame_info));
|
||||
|
||||
switch(data->type) {
|
||||
case MPEG_EAL31: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame); break;
|
||||
case MPEG_EAL31: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame, 0); break;
|
||||
case MPEG_EAL31b: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame, 1); break;
|
||||
case MPEG_EAL32P:
|
||||
case MPEG_EAL32S: ok = ealayer3_parse_frame_v2(is, eaf); break;
|
||||
default: goto fail;
|
||||
}
|
||||
if (!ok) goto fail;
|
||||
|
||||
|
||||
//;VGM_LOG("EAFRAME: v=%i, ch=%i, sr=%i, index=%i / pre=%x, common=%x, pcm=%x, eaframe=%x\n", eaf->version, eaf->channels, eaf->sample_rate, eaf->granule_index, eaf->pre_size, eaf->common_size, eaf->pcm_size, eaf->eaframe_size);
|
||||
//if (data->type==MPEG_EAL31) VGM_LOG("EAFRAME v1: pcm=%x, unk=%x, number=%x\n", eaf->v1_pcm_flag, eaf->v1_pcm_unknown, eaf->v1_pcm_number);
|
||||
//else VGM_LOG("EAFRAME v2: stereo=%x, unk=%x, fs=%x, mode=%x, val=%x, number=%x, size=%x\n", eaf->v2_stereo_flag, eaf->v2_unknown, eaf->v2_frame_size, eaf->v2_mode, eaf->v2_mode_value, eaf->v2_pcm_number, eaf->v2_common_size);
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame) {
|
||||
/* read V1"a" (in SCHl) and V1"b" (in SNS) EALayer3 frame */
|
||||
static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b) {
|
||||
int ok;
|
||||
|
||||
/* read EA-frame V1 header */
|
||||
|
@ -249,25 +235,30 @@ static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info *
|
|||
VGM_LOG("MPEG EAL3 v1: header not 0x00 or 0xEE\n");
|
||||
goto fail; /* wrong offset? */
|
||||
}
|
||||
if (eaf->v1_pcm_flag == 0xEE && !channels_per_frame) {
|
||||
VGM_LOG("MPEG EAL3 v1: PCM block in first frame\n");
|
||||
goto fail; /* must know from a prev frame */
|
||||
}
|
||||
|
||||
/* read EA-frame common header (v1a PCM blocks don't have EA-frames, while v1b do) */
|
||||
if (is_v1b || eaf->v1_pcm_flag == 0x00) {
|
||||
ok = ealayer3_parse_frame_common(is, eaf);
|
||||
if (!ok) goto fail;
|
||||
}
|
||||
|
||||
/* check PCM block */
|
||||
if (eaf->v1_pcm_flag == 0xEE) {
|
||||
r_bits(is, 16,&eaf->v1_pcm_decode_discard); /* samples to discard of the next decoded (not PCM block) samples */
|
||||
r_bits(is, 16,&eaf->v1_pcm_number); /* number of PCM samples, can be 0 */
|
||||
|
||||
if (!channels_per_frame) {
|
||||
VGM_LOG("MPEG EAL3 v1: PCM block as first frame\n");
|
||||
goto fail; /* must know from a prev frame */
|
||||
}
|
||||
|
||||
eaf->pre_size += 2+2; /* 16b+16b */
|
||||
eaf->pcm_size = (2*eaf->v1_pcm_number * channels_per_frame);
|
||||
}
|
||||
else {
|
||||
/* read EA-frame common header */
|
||||
ok = ealayer3_parse_frame_common(is, eaf);
|
||||
if (!ok) goto fail;
|
||||
|
||||
if (is_v1b) { /* extra 32b in v1b */
|
||||
r_bits(is, 32,&eaf->v1_pcm_unknown);
|
||||
eaf->pre_size += 4; /* 32b */
|
||||
VGM_ASSERT(eaf->v1_pcm_unknown != 0, "EA EAL3 v1: v1_pcm_unknown not 0\n");
|
||||
}
|
||||
}
|
||||
|
||||
eaf->eaframe_size = eaf->pre_size + eaf->common_size + eaf->pcm_size;
|
||||
|
@ -277,8 +268,9 @@ fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf) {
|
||||
/* read V2"PCM" and V2"Spike" EALayer3 frame (exactly the same but V2P seems to have bigger
|
||||
* PCM blocks and maybe smaller frames) */
|
||||
static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf) {
|
||||
int ok;
|
||||
|
||||
/* read EA-frame V2 header */
|
||||
|
@ -286,7 +278,7 @@ static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info *
|
|||
r_bits(is, 1,&eaf->v2_stereo_flag);
|
||||
r_bits(is, 2,&eaf->v2_unknown);
|
||||
r_bits(is, 12,&eaf->v2_frame_size);
|
||||
|
||||
|
||||
eaf->pre_size = 2; /* 16b */
|
||||
|
||||
if (eaf->v2_extended_flag) {
|
||||
|
@ -294,25 +286,24 @@ static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info *
|
|||
r_bits(is, 10,&eaf->v2_mode_value);
|
||||
r_bits(is, 10,&eaf->v2_pcm_number);
|
||||
r_bits(is, 10,&eaf->v2_common_size);
|
||||
|
||||
|
||||
eaf->pre_size += 4; /* 32b */
|
||||
}
|
||||
|
||||
/* read EA-frame common header */
|
||||
ok = ealayer3_parse_frame_common(is, eaf);
|
||||
if (!ok) goto fail;
|
||||
|
||||
//todo maybe v2 frames can be PCM-only like v1
|
||||
if (!eaf->channels) {
|
||||
VGM_LOG("MPEG EAL3: v2 frame with no channel number");
|
||||
goto fail;
|
||||
if (!eaf->v2_extended_flag || (eaf->v2_extended_flag && eaf->v2_common_size)) {
|
||||
ok = ealayer3_parse_frame_common(is, eaf);
|
||||
if (!ok) goto fail;
|
||||
}
|
||||
VGM_ASSERT(eaf->v2_extended_flag && eaf->v2_common_size == 0, "EA EAL3: v2 empty frame\n"); /* seen in V2S */
|
||||
VGM_ASSERT(eaf->v2_extended_flag && eaf->v2_mode_value > 0, "EA EAL3: v2_mode=%x with 0x%x\n", eaf->v2_mode, eaf->v2_mode_value);
|
||||
//VGM_ASSERT(eaf->v2_pcm_number > 0, "EA EAL3: v2_pcm_number 0x%x\n", eaf->v2_pcm_number);
|
||||
|
||||
eaf->pcm_size = (2*eaf->v2_pcm_number * eaf->channels);
|
||||
|
||||
eaf->eaframe_size = eaf->pre_size + eaf->common_size + eaf->pcm_size;
|
||||
|
||||
if(eaf->v2_frame_size != eaf->eaframe_size) {
|
||||
if (eaf->v2_frame_size != eaf->eaframe_size) {
|
||||
VGM_LOG("MPEG EAL3: different v2 frame size vs calculated (0x%x vs 0x%x)\n", eaf->v2_frame_size, eaf->eaframe_size);
|
||||
goto fail;
|
||||
}
|
||||
|
@ -324,8 +315,8 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
/* Parses a EALayer3 frame (common part) */
|
||||
static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf) {
|
||||
/* parses an EALayer3 frame (common part) */
|
||||
static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf) {
|
||||
/* index tables */
|
||||
static const int versions[4] = { /* MPEG 2.5 */ 3, /* reserved */ -1, /* MPEG 2 */ 2, /* MPEG 1 */ 1 };
|
||||
static const int sample_rates[4][4] = { /* [version_index][sample rate index] */
|
||||
|
@ -393,9 +384,11 @@ static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_in
|
|||
for (i = 0; i < eaf->channels; i++) { /* data size (can be 0, meaning a micro EA-frame) */
|
||||
eaf->data_size_b += eaf->main_data_size[i];
|
||||
}
|
||||
is->b_off += eaf->data_size_b;
|
||||
|
||||
if ((eaf->base_size_b+eaf->data_size_b) % 8) /* aligned to closest 8b */
|
||||
eaf->padding_size_b = 8 - ((eaf->base_size_b+eaf->data_size_b) % 8);
|
||||
is->b_off += eaf->padding_size_b;
|
||||
|
||||
eaf->common_size = (eaf->base_size_b + eaf->data_size_b + eaf->padding_size_b)/8;
|
||||
|
||||
|
@ -406,36 +399,46 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
/* Converts a EALAYER3 frame to a standard MPEG frame from pre-parsed info */
|
||||
static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os) {
|
||||
/* converts an EALAYER3 frame to a standard MPEG frame from pre-parsed info */
|
||||
static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os) {
|
||||
uint32_t c = 0;
|
||||
int i,j;
|
||||
int expected_bitrate_index, expected_frame_size;
|
||||
|
||||
if (!eaf_0->common_size && !eaf_1->common_size)
|
||||
return 1; /* empty frames, PCM block only */
|
||||
|
||||
/* get bitrate: use max bitrate (320/160) to simplify calcs for now (but some EA-frames use bit reservoir) */
|
||||
expected_bitrate_index = 0x0E;
|
||||
if (eaf_0->mpeg1) { /* 44100=0x414, 48000=0x3C0, 32000=0x5A0 */
|
||||
expected_frame_size = 144l * 320 * 1000l / eaf_0->sample_rate;
|
||||
} else { /* 22050=0x20A, 24000=0x1E0, 16000=0x2D0, 11025=0x414, 12000=0x3C0, 8000=0x5A0 */
|
||||
expected_frame_size = 72l * 160 * 1000l / eaf_0->sample_rate;
|
||||
}
|
||||
/* ignore PCM-only frames */
|
||||
if (!eaf_0->common_size)
|
||||
return 1;
|
||||
|
||||
/* extra checks */
|
||||
if (eaf_0->mpeg1) {
|
||||
if (!eaf_1
|
||||
|| eaf_0->mpeg1 != eaf_1->mpeg1
|
||||
|| eaf_0->version != eaf_1->version
|
||||
|| eaf_0->granule_index == eaf_1->granule_index
|
||||
|| !eaf_0->common_size || !eaf_1->common_size) {
|
||||
VGM_LOG("MPEG EAL3: EA-frames for MPEG1 don't match at 0x%lx\n", os->offset);
|
||||
goto fail;
|
||||
}
|
||||
if (eaf_0->mpeg1 && (!eaf_1
|
||||
|| eaf_0->mpeg1 != eaf_1->mpeg1
|
||||
|| eaf_0->version != eaf_1->version
|
||||
|| eaf_0->granule_index == eaf_1->granule_index
|
||||
|| !eaf_0->common_size || !eaf_1->common_size)) {
|
||||
VGM_LOG("MPEG EAL3: EA-frames for MPEG1 don't match at 0x%lx\n", os->info_offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* get bitrate: use "free format" (bigger bitrate) to avoid the need of bit reservoir
|
||||
* this feature is in the spec but some decoders may not support it
|
||||
* (free format detection is broken in some MP3 in mpg123 < 1.25.8 but works ok) */
|
||||
expected_bitrate_index = 0x00;
|
||||
if (eaf_0->mpeg1) {
|
||||
expected_frame_size = 144l * (320*2) * 1000l / eaf_0->sample_rate;
|
||||
} else {
|
||||
expected_frame_size = 72l * (160*2) * 1000l / eaf_0->sample_rate;
|
||||
}
|
||||
#if 0
|
||||
/* this uses max official bitrate (320/160) but some frames need more = complex bit reservoir */
|
||||
expected_bitrate_index = 0x0E;
|
||||
if (eaf_0->mpeg1) { /* 320: 44100=0x414, 48000=0x3C0, 32000=0x5A0 */
|
||||
expected_frame_size = 144l * 320 * 1000l / eaf_0->sample_rate;
|
||||
} else { /* 160: 22050=0x20A, 24000=0x1E0, 16000=0x2D0, 11025=0x414, 12000=0x3C0, 8000=0x5A0 */
|
||||
expected_frame_size = 72l * 160 * 1000l / eaf_0->sample_rate;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* write MPEG1/2 frame header */
|
||||
w_bits(os, 11, 0x7FF); /* sync */
|
||||
w_bits(os, 2, eaf_0->version_index);
|
||||
|
@ -521,12 +524,8 @@ static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_
|
|||
|
||||
|
||||
if (os->b_off/8 > expected_frame_size) {
|
||||
VGM_LOG("MPEG EAL3: written 0x%lx but expected less than 0x%x at 0x%lx\n", os->b_off/8, expected_frame_size, os->offset);
|
||||
//todo bit reservoir! (doesn't seem to affect the output too much)
|
||||
|
||||
//;VGM_LOG("EAFRAME: F0 v=%i, ch=%i, sr=%i, index=%i / pre=%x, common=%x, pcm=%x, eaframe=%x\n", eaf_0->version, eaf_0->channels, eaf_0->sample_rate, eaf_0->granule_index, eaf_0->pre_size, eaf_0->common_size, eaf_0->pcm_size, eaf_0->eaframe_size);
|
||||
//;VGM_LOG("EAFRAME: F1 v=%i, ch=%i, sr=%i, index=%i / pre=%x, common=%x, pcm=%x, eaframe=%x\n", eaf_1->version, eaf_1->channels, eaf_1->sample_rate, eaf_1->granule_index, eaf_1->pre_size, eaf_1->common_size, eaf_1->pcm_size, eaf_1->eaframe_size);
|
||||
//;VGM_LOGB(os->buf, os->b_off/8, 0);
|
||||
/* bit reservoir! shouldn't happen with free bitrate, otherwise it's hard to fix as needs complex buffering/calcs */
|
||||
VGM_LOG("MPEG EAL3: written 0x%lx but expected less than 0x%x at 0x%lx\n", os->b_off/8, expected_frame_size, os->info_offset);
|
||||
}
|
||||
else {
|
||||
/* fill ancillary data (ignored) */
|
||||
|
@ -541,7 +540,9 @@ fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* write PCM block directly to sample buffer (EALayer3 seems to use this as a prefectch of sorts) */
|
||||
/* write PCM block directly to sample buffer and setup decode discard (EALayer3 seems to use this as a prefetch of sorts).
|
||||
* Meant to be written inmediatedly, as those PCM are parts that can be found after 1 decoded frame.
|
||||
* (ex. EA-frame_gr0, PCM-frame_0, EA-frame_gr1, PCM-frame_1 actually writes PCM-frame_0+1, decode of EA-frame_gr0+1 + discard part */
|
||||
static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf) {
|
||||
mpeg_custom_stream *ms = data->streams[num_stream];
|
||||
size_t bytes_filled;
|
||||
|
@ -552,13 +553,12 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
|
|||
|
||||
bytes_filled = sizeof(sample)*ms->samples_filled*data->channels_per_frame;
|
||||
if (bytes_filled + eaf->pcm_size > ms->output_buffer_size) {
|
||||
VGM_LOG("MPEG EAL3: can't fill the sample buffer with 0x%x\n", eaf->pcm_size);
|
||||
goto fail;
|
||||
VGM_LOG("MPEG EAL3: can't fill the sample buffer with 0x%x\n", eaf->pcm_size);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (eaf->v1_pcm_number) {
|
||||
//;VGM_LOG("pcm discard = %i, number = %i at 0x%lx\n", eaf->v1_pcm_decode_discard, eaf->v1_pcm_number, stream->offset);
|
||||
VGM_ASSERT(eaf->v1_pcm_decode_discard > 576, "MPEG EAL3: big discard %i at 0x%lx\n", eaf->v1_pcm_decode_discard, stream->offset);
|
||||
VGM_ASSERT(eaf->v1_pcm_number > 0x100, "MPEG EAL3: big samples %i at 0x%lx\n", eaf->v1_pcm_number, stream->offset);
|
||||
|
||||
|
@ -576,95 +576,98 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
|
|||
|
||||
//todo should also discard v1_pcm_number, but block layout samples may be exhausted and won't move (maybe new block if offset = new offset detected)
|
||||
/* special meanings */
|
||||
if (decode_to_discard == 576)
|
||||
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number;
|
||||
|
||||
if (data->type == MPEG_EAL31) {
|
||||
if (decode_to_discard == 576)
|
||||
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number;
|
||||
}
|
||||
else {
|
||||
if (decode_to_discard == 0) /* seems ok? */
|
||||
decode_to_discard += data->samples_per_frame;//+ eaf->v1_pcm_number;
|
||||
else if (decode_to_discard == 576) /* untested */
|
||||
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number;
|
||||
}
|
||||
ms->decode_to_discard += decode_to_discard;
|
||||
}
|
||||
}
|
||||
|
||||
if (eaf->v2_extended_flag) {
|
||||
|
||||
if (eaf->v2_pcm_number) {
|
||||
/* read + write PCM block samples (always BE) */
|
||||
for (i = 0; i < eaf->v2_pcm_number * data->channels_per_frame; i++) {
|
||||
off_t pcm_offset = stream->offset + eaf->pre_size + eaf->common_size + sizeof(sample)*i;
|
||||
int16_t pcm_sample = read_16bitBE(pcm_offset,stream->streamfile);
|
||||
put_16bitLE(ms->output_buffer + bytes_filled + sizeof(sample)*i, pcm_sample);
|
||||
}
|
||||
ms->samples_filled += eaf->v2_pcm_number;
|
||||
}
|
||||
|
||||
/* todo V2 (id7 only?) supposed skip modes:
|
||||
* BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3
|
||||
*
|
||||
* AB00CCCC CCCCCCCC if A is set: DDEEEEEE EEEEFFFF FFFFFFGG GGGGGGGG
|
||||
* D = mode:
|
||||
* E = bytes to discard (mode == 0) or skip (mode == 1 or 2) before outputting the uncompressed samples
|
||||
* (when mode == 3 this is ignored)
|
||||
* F = number of uncompressed sample frames
|
||||
* G = MPEG granule size (can be zero)
|
||||
*
|
||||
* if 0: 576 - E if G == 0 then F
|
||||
* if 1: 576 if G == 0 then F
|
||||
* if 2: 576 if G == 0 then F * 2
|
||||
* if 3: 576
|
||||
*/
|
||||
#if 0
|
||||
/* todo supposed skip modes (only seen 0x00):
|
||||
*
|
||||
* AB00CCCC CCCCCCCC if A is set: DDEEEEEE EEEEFFFF FFFFFFGG GGGGGGGG
|
||||
* D = BLOCKOFFSETMODE: IGNORE = 0x0, PRESERVE = 0x1, MUTE = 0x2, MAX = 0x3
|
||||
* E = samples to discard (mode == 0) or skip (mode == 1 or 2) before outputting the uncompressed samples
|
||||
* (when mode == 3 this is ignored)
|
||||
* F = number of uncompressed sample frames (pcm block)
|
||||
* G = MPEG granule size (can be zero)
|
||||
*
|
||||
* if 0: 576 - E if G == 0 then F
|
||||
* if 1: 576 if G == 0 then F
|
||||
* if 2: 576 if G == 0 then F * 2
|
||||
* if 3: 576
|
||||
*/
|
||||
|
||||
/* modify decoded samples depending on flag */
|
||||
if (eaf->v2_mode == 0x00) {
|
||||
size_t decode_to_discard = eaf->v2_mode_value;
|
||||
|
||||
if (decode_to_discard == 576)
|
||||
decode_to_discard = data->samples_per_frame;//+ eaf->v2_pcm_number;
|
||||
|
||||
ms->decode_to_discard += decode_to_discard;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ********************************************* */
|
||||
|
||||
/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */
|
||||
static int r_bits(ealayer3_bitstream * is, int num_bits, uint32_t * value) {
|
||||
off_t off, pos;
|
||||
int i, bit_buf, bit_val;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || is->b_off + num_bits > is->bufsize*8) goto fail;
|
||||
/* Skip EA-frames from other streams for multichannel (interleaved 1 EA-frame per stream).
|
||||
* Due to EALayer3 being in blocks and other complexities (we can't go past a block) all
|
||||
* streams's offsets should start in the first stream's EA-frame.
|
||||
*
|
||||
* So to properly read one MPEG-frame from a stream we need to:
|
||||
* - skip one EA-frame per previous streams until offset is in current stream's EA-frame
|
||||
* (ie. 1st stream skips 0, 2nd stream skips 1, 3rd stream skips 2)
|
||||
* - read EA-frame (granule0)
|
||||
* - skip one EA-frame per following streams until offset is in first stream's EA-frame
|
||||
* (ie. 1st stream skips 2, 2nd stream skips 1, 3rd stream skips 0)
|
||||
* - repeat again for granule1
|
||||
*/
|
||||
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start) {
|
||||
int ok, i;
|
||||
ealayer3_frame_info eaf;
|
||||
vgm_bitstream is = {0};
|
||||
uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE];
|
||||
int skips = at_start ? num_stream : data->streams_size - 1 - num_stream;
|
||||
|
||||
*value = 0; /* set all bits to 0 */
|
||||
off = is->b_off / 8; /* byte offset */
|
||||
pos = is->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */
|
||||
bit_val = (1U << (num_bits-1-i)); /* bit to set in value */
|
||||
|
||||
if (is->buf[off] & bit_buf) /* is bit in buf set? */
|
||||
*value |= bit_val; /* set bit */
|
||||
for (i = 0; i < skips; i++) {
|
||||
is.buf = ibuf;
|
||||
is.bufsize = read_streamfile(ibuf,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
|
||||
is.b_off = 0;
|
||||
|
||||
pos++;
|
||||
if (pos%8 == 0) { /* new byte starts */
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
ok = ealayer3_parse_frame(data, &is, &eaf);
|
||||
if (!ok) goto fail;
|
||||
|
||||
stream->offset += eaf.eaframe_size;
|
||||
}
|
||||
//;VGM_LOG("s%i: skipped %i frames, now at %lx\n", num_stream,skips,stream->offset);
|
||||
|
||||
is->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */
|
||||
static int w_bits(ealayer3_bitstream * os, int num_bits, uint32_t value) {
|
||||
off_t off, pos;
|
||||
int i, bit_val, bit_buf;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || os->b_off + num_bits > os->bufsize*8) goto fail;
|
||||
|
||||
|
||||
off = os->b_off / 8; /* byte offset */
|
||||
pos = os->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_val = (1U << (num_bits-1-i)); /* bit check for value */
|
||||
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */
|
||||
|
||||
if (value & bit_val) /* is bit in val set? */
|
||||
os->buf[off] |= bit_buf; /* set bit */
|
||||
else
|
||||
os->buf[off] &= ~bit_buf; /* unset bit */
|
||||
|
||||
pos++;
|
||||
if (pos%8 == 0) { /* new byte starts */
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
os->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
|
|
|
@ -10,10 +10,9 @@
|
|||
* - don't force channel param and get them from frame headers for some types (for MPEG_STANDARD)
|
||||
* - in case of streams like 2ch+1ch+1ch+2ch (not seen) use one stream per channel and advance streams as channels are done
|
||||
* - validate of channels between streams
|
||||
* - fsb garbage in the first frames
|
||||
*/
|
||||
|
||||
#define MPEG_DATA_BUFFER_SIZE 0x1000 /* at least one MPEG frame (max ~0x5A1) */
|
||||
#define MPEG_DATA_BUFFER_SIZE 0x1000 /* at least one MPEG frame (max ~0x5A1 plus some more in case of free bitrate) */
|
||||
|
||||
static mpg123_handle * init_mpg123_handle();
|
||||
static void decode_mpeg_standard(VGMSTREAMCHANNEL *stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
|
||||
|
@ -101,6 +100,8 @@ mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset
|
|||
if (channels_per_frame != channels)
|
||||
goto fail;
|
||||
|
||||
/* copy current as open_feed may invalidate until data is fed */
|
||||
memcpy(&data->mi, &mi, sizeof(struct mpg123_frameinfo));
|
||||
|
||||
/* reinit, to ignore the reading done */
|
||||
mpg123_open_feed(main_m);
|
||||
|
@ -123,11 +124,6 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start
|
|||
data = calloc(1,sizeof(mpeg_codec_data));
|
||||
if (!data) goto fail;
|
||||
|
||||
data->buffer_size = MPEG_DATA_BUFFER_SIZE;
|
||||
data->buffer = calloc(sizeof(uint8_t), data->buffer_size);
|
||||
if (!data->buffer) goto fail;
|
||||
|
||||
|
||||
/* keep around to decode */
|
||||
data->custom = 1;
|
||||
data->type = type;
|
||||
|
@ -137,6 +133,7 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start
|
|||
/* init per subtype */
|
||||
switch(data->type) {
|
||||
case MPEG_EAL31:
|
||||
case MPEG_EAL31b:
|
||||
case MPEG_EAL32P:
|
||||
case MPEG_EAL32S: ok = mpeg_custom_setup_init_ealayer3(streamFile, start_offset, data, coding_type); break;
|
||||
case MPEG_AWC: ok = mpeg_custom_setup_init_awc(streamFile, start_offset, data, coding_type); break;
|
||||
|
@ -161,6 +158,11 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start
|
|||
data->streams[i]->output_buffer_size = sizeof(sample) * data->channels_per_frame * data->samples_per_frame;
|
||||
data->streams[i]->output_buffer = calloc(data->streams[i]->output_buffer_size, sizeof(uint8_t));
|
||||
if (!data->streams[i]->output_buffer) goto fail;
|
||||
|
||||
/* one per stream as sometimes mpg123 can't read the whole buffer in one pass */
|
||||
data->streams[i]->buffer_size = MPEG_DATA_BUFFER_SIZE;
|
||||
data->streams[i]->buffer = calloc(sizeof(uint8_t), data->streams[i]->buffer_size);
|
||||
if (!data->streams[i]->buffer) goto fail;
|
||||
}
|
||||
|
||||
|
||||
|
@ -238,7 +240,7 @@ static void decode_mpeg_standard(VGMSTREAMCHANNEL *stream, mpeg_codec_data * dat
|
|||
|
||||
/* end of stream, fill rest with 0s */
|
||||
if (!data->bytes_in_buffer) {
|
||||
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * channels * sizeof(sample));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -367,7 +369,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
|
|||
int rc, ok;
|
||||
mpeg_custom_stream *ms = data->streams[num_stream];
|
||||
|
||||
//;VGM_LOG("MPEG: decode stream%i @ 0x%08lx (filled=%i, used=%i)\n", num_stream, stream->offset, ms->samples_filled, ms->samples_used);
|
||||
//;VGM_LOG("MPEG: decode stream%i @ 0x%08lx (filled=%i, used=%i, buffer_full=%i)\n", num_stream, stream->offset, ms->samples_filled, ms->samples_used, ms->buffer_full);
|
||||
|
||||
/* wait until samples are depleted, so buffers don't grow too big */
|
||||
if (ms->samples_filled - ms->samples_used > 0) {
|
||||
|
@ -379,58 +381,47 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
|
|||
ms->samples_used = 0;
|
||||
|
||||
/* extra EOF check for edge cases when the caller tries to read more samples than possible */
|
||||
if (!data->buffer_full && stream->offset >= stream_size) {
|
||||
if (!ms->buffer_full && stream->offset >= stream_size) {
|
||||
VGM_LOG("MPEG: EOF found but more data is requested\n");
|
||||
goto decode_fail;
|
||||
}
|
||||
|
||||
|
||||
/* read more raw data (could fill the sample buffer too in some cases, namely EALayer3) */
|
||||
if (!data->buffer_full) {
|
||||
if (!ms->buffer_full) {
|
||||
//;VGM_LOG("MPEG: reading more raw data\n");
|
||||
switch(data->type) {
|
||||
case MPEG_EAL31:
|
||||
case MPEG_EAL31b:
|
||||
case MPEG_EAL32P:
|
||||
case MPEG_EAL32S: ok = mpeg_custom_parse_frame_ealayer3(stream, data, num_stream); break;
|
||||
case MPEG_AHX: ok = mpeg_custom_parse_frame_ahx(stream, data); break;
|
||||
case MPEG_AHX: ok = mpeg_custom_parse_frame_ahx(stream, data, num_stream); break;
|
||||
case MPEG_AWC: ok = mpeg_custom_parse_frame_awc(stream, data, num_stream); break;
|
||||
default: ok = mpeg_custom_parse_frame_default(stream, data); break;
|
||||
default: ok = mpeg_custom_parse_frame_default(stream, data, num_stream); break;
|
||||
}
|
||||
if (!ok) {
|
||||
VGM_LOG("MPEG: cannot parse frame @ around %lx\n",stream->offset);
|
||||
goto decode_fail; /* mpg123 could resync but custom MPEGs wouldn't need that */
|
||||
}
|
||||
//;VGM_LOG("MPEG: read results: bytes_in_buffer=0x%x, new offset=%lx\n", data->bytes_in_buffer, stream->offset);
|
||||
//;VGM_LOG("MPEG: read results: bytes_in_buffer=0x%x, new offset=%lx\n", ms->bytes_in_buffer, stream->offset);
|
||||
|
||||
/* parse frame may not touch the buffer (only move offset, or fill the sample buffer) */
|
||||
if (data->bytes_in_buffer) {
|
||||
data->buffer_full = 1;
|
||||
data->buffer_used = 0;
|
||||
if (ms->bytes_in_buffer) {
|
||||
ms->buffer_full = 1;
|
||||
ms->buffer_used = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
//FSB sometimes has garbage in the first frames, not sure why/when, no apparent patern
|
||||
if (data->custom_type == MPEG_FSB && stream->offset == stream->channel_start_offset) { /* first frame */
|
||||
VGM_LOG("MPEG: skip first frame @ %x - %x\n", stream->offset, stream->channel_start_offset);
|
||||
|
||||
data->buffer_full = 0;
|
||||
memset(data->stream_buffer, 0, data->stream_buffer_size);
|
||||
bytes_done = data->stream_buffer_size;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bytes_filled = sizeof(sample)*ms->samples_filled*data->channels_per_frame;
|
||||
/* feed new raw data to the decoder if needed, copy decoded results to frame buffer output */
|
||||
if (!data->buffer_used) {
|
||||
//;VGM_LOG("MPEG: feed new data and get samples \n");
|
||||
if (!ms->buffer_used) {
|
||||
//;VGM_LOG("MPEG: feed new data and get samples\n");
|
||||
rc = mpg123_decode(ms->m,
|
||||
data->buffer, data->bytes_in_buffer,
|
||||
ms->buffer, ms->bytes_in_buffer,
|
||||
(unsigned char*)ms->output_buffer + bytes_filled, ms->output_buffer_size - bytes_filled,
|
||||
&bytes_done);
|
||||
data->buffer_used = 1;
|
||||
ms->buffer_used = 1;
|
||||
}
|
||||
else {
|
||||
//;VGM_LOG("MPEG: get samples from old data\n");
|
||||
|
@ -460,11 +451,12 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
|
|||
/* not enough raw data, set flag to request more next time
|
||||
* (but only with empty mpg123 buffer, EA blocks wait for all samples decoded before advancing blocks) */
|
||||
if (!bytes_done && rc == MPG123_NEED_MORE) {
|
||||
//;VGM_LOG("MPEG: need more raw data to get samples (bytest_done=%x)\n", bytes_done);
|
||||
data->buffer_full = 0;
|
||||
//;VGM_LOG("MPEG: need more raw data to get samples (bytes_done=%x)\n", bytes_done);
|
||||
ms->buffer_full = 0;
|
||||
}
|
||||
|
||||
|
||||
//;VGM_LOG("MPEG: stream samples now=%i, filled=%i)\n\n", ms->samples_filled, samples_filled);
|
||||
return;
|
||||
|
||||
decode_fail:
|
||||
|
@ -490,6 +482,7 @@ void free_mpeg(mpeg_codec_data *data) {
|
|||
int i;
|
||||
for (i=0; i < data->streams_size; i++) {
|
||||
mpg123_delete(data->streams[i]->m);
|
||||
free(data->streams[i]->buffer);
|
||||
free(data->streams[i]->output_buffer);
|
||||
free(data->streams[i]);
|
||||
}
|
||||
|
@ -537,6 +530,8 @@ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) {
|
|||
/* seek multistream */
|
||||
if (!data->custom) {
|
||||
mpg123_feedseek(data->m, num_sample,SEEK_SET,&input_offset);
|
||||
|
||||
/* force first offset as discard-looping needs to start from the beginning */
|
||||
if (vgmstream->loop_ch)
|
||||
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset + input_offset;
|
||||
}
|
||||
|
@ -548,7 +543,10 @@ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) {
|
|||
data->streams[i]->samples_filled = 0;
|
||||
data->streams[i]->samples_used = 0;
|
||||
data->streams[i]->decode_to_discard = 0;
|
||||
data->streams[i]->buffer_full = 0;
|
||||
data->streams[i]->buffer_used = 0;
|
||||
|
||||
/* force first offset as discard-looping needs to start from the beginning */
|
||||
if (vgmstream->loop_ch)
|
||||
vgmstream->loop_ch[i].offset = vgmstream->loop_ch[i].channel_start_offset;
|
||||
}
|
||||
|
@ -579,6 +577,9 @@ void flush_mpeg(mpeg_codec_data * data) {
|
|||
data->streams[i]->samples_filled = 0;
|
||||
data->streams[i]->samples_used = 0;
|
||||
data->streams[i]->decode_to_discard = 0;
|
||||
data->streams[i]->bytes_in_buffer = 0;
|
||||
data->streams[i]->buffer_full = 0;
|
||||
data->streams[i]->buffer_used = 0;
|
||||
}
|
||||
|
||||
data->samples_to_discard = data->skip_samples; /* initial delay */
|
||||
|
@ -592,23 +593,20 @@ void flush_mpeg(mpeg_codec_data * data) {
|
|||
long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data) {
|
||||
/* if not found just return 0 and expect to fail (if used for num_samples) */
|
||||
if (!data->custom) {
|
||||
struct mpg123_frameinfo mi;
|
||||
mpg123_handle *m = data->m;
|
||||
|
||||
if (m == NULL || MPG123_OK != mpg123_info(m, &mi))
|
||||
return 0;
|
||||
|
||||
/* We would need to read all VBR frames headers to count samples */
|
||||
if (mi.vbr != MPG123_CBR) //maybe abr_rate could be used to get an approx
|
||||
if (data->mi.vbr != MPG123_CBR) { //maybe abr_rate could be used to get an approx
|
||||
VGM_LOG("MPEG: vbr mp3 can't do bytes_to_samples\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t)bytes * mi.rate * 8 / (mi.bitrate * 1000);
|
||||
return (int64_t)bytes * data->mi.rate * 8 / (data->mi.bitrate * 1000);
|
||||
}
|
||||
else {
|
||||
return 0; /* a bit too complex for what is worth */
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* disables/enables stderr output, for MPEG known to contain recoverable errors */
|
||||
void mpeg_set_error_logging(mpeg_codec_data * data, int enable) {
|
||||
if (!data->custom) {
|
||||
|
@ -621,5 +619,5 @@ void mpeg_set_error_logging(mpeg_codec_data * data, int enable) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _MPEG_DECODER_H_
|
||||
|
||||
#include "../vgmstream.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* used by mpeg_decoder.c, but scattered in other .c files */
|
||||
#ifdef VGM_USE_MPEG
|
||||
|
@ -21,8 +22,8 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
|
|||
int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type);
|
||||
int mpeg_custom_setup_init_awc(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type);
|
||||
|
||||
int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data);
|
||||
int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data);
|
||||
int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream);
|
||||
int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream);
|
||||
int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream);
|
||||
int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream);
|
||||
|
||||
|
|
|
@ -37,13 +37,11 @@ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
|||
}
|
||||
|
||||
/* read from memory rather than a file */
|
||||
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) {
|
||||
static void decode_ngc_dsp_subint_internal(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) {
|
||||
int i=first_sample;
|
||||
int32_t sample_count;
|
||||
|
||||
int framesin = first_sample/14;
|
||||
|
||||
int8_t header = mem[framesin*8];
|
||||
int8_t header = mem[0];
|
||||
int32_t scale = 1 << (header & 0xf);
|
||||
int coef_index = (header >> 4) & 0xf;
|
||||
int32_t hist1 = stream->adpcm_history1_16;
|
||||
|
@ -54,7 +52,7 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
|
|||
first_sample = first_sample%14;
|
||||
|
||||
for (i=first_sample,sample_count=0; 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((
|
||||
(((i&1?
|
||||
|
@ -72,6 +70,27 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
|
|||
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
|
||||
* variants don't have a proper sample count, so we (who are interested
|
||||
|
|
|
@ -50,6 +50,7 @@ vorbis_custom_codec_data * init_vorbis_custom_codec_data(STREAMFILE *streamFile,
|
|||
case VORBIS_WWISE: ok = vorbis_custom_setup_init_wwise(streamFile, start_offset, data); break;
|
||||
case VORBIS_OGL: ok = vorbis_custom_setup_init_ogl(streamFile, start_offset, data); break;
|
||||
case VORBIS_SK: ok = vorbis_custom_setup_init_sk(streamFile, start_offset, data); break;
|
||||
case VORBIS_VID1: ok = vorbis_custom_setup_init_vid1(streamFile, start_offset, data); break;
|
||||
default: goto fail;
|
||||
}
|
||||
if(!ok) goto fail;
|
||||
|
@ -131,6 +132,7 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample
|
|||
case VORBIS_WWISE: ok = vorbis_custom_parse_packet_wwise(stream, data); break;
|
||||
case VORBIS_OGL: ok = vorbis_custom_parse_packet_ogl(stream, data); break;
|
||||
case VORBIS_SK: ok = vorbis_custom_parse_packet_sk(stream, data); break;
|
||||
case VORBIS_VID1: ok = vorbis_custom_parse_packet_vid1(stream, data); break;
|
||||
default: goto decode_fail;
|
||||
}
|
||||
if(!ok) {
|
||||
|
@ -142,8 +144,9 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample
|
|||
/* parse the fake ogg packet into a logical vorbis block */
|
||||
rc = vorbis_synthesis(&data->vb,&data->op);
|
||||
if (rc == OV_ENOTAUDIO) {
|
||||
VGM_LOG("Vorbis: not an audio packet @ %lx\n",stream->offset);
|
||||
continue; /* not tested */
|
||||
VGM_LOG("Vorbis: not an audio packet (size=0x%x) @ %lx\n",(size_t)data->op.bytes,stream->offset);
|
||||
//VGM_LOGB(data->op.packet, (size_t)data->op.bytes,0);
|
||||
continue; /* seems ok? */
|
||||
} else if (rc != 0) {
|
||||
VGM_LOG("Vorbis: cannot parse Vorbis block @ %lx\n",stream->offset);
|
||||
goto decode_fail;
|
||||
|
@ -164,7 +167,7 @@ void decode_vorbis_custom(VGMSTREAM * vgmstream, sample * outbuf, int32_t sample
|
|||
|
||||
decode_fail:
|
||||
/* on error just put some 0 samples */
|
||||
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * channels * sizeof(sample));
|
||||
}
|
||||
|
||||
/* converts from internal Vorbis format to standard PCM (mostly from Xiph's decoder_example.c) */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _VORBIS_CUSTOM_DECODER_H_
|
||||
|
||||
#include "../vgmstream.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* used by vorbis_custom_decoder.c, but scattered in other .c files */
|
||||
#ifdef VGM_USE_VORBIS
|
||||
|
@ -9,11 +10,13 @@ int vorbis_custom_setup_init_fsb(STREAMFILE *streamFile, off_t start_offset, vor
|
|||
int vorbis_custom_setup_init_wwise(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
|
||||
int vorbis_custom_setup_init_ogl(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
|
||||
int vorbis_custom_setup_init_sk(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
|
||||
int vorbis_custom_setup_init_vid1(STREAMFILE *streamFile, off_t start_offset, vorbis_custom_codec_data *data);
|
||||
|
||||
int vorbis_custom_parse_packet_fsb(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
|
||||
int vorbis_custom_parse_packet_wwise(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
|
||||
int vorbis_custom_parse_packet_ogl(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
|
||||
int vorbis_custom_parse_packet_sk(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
|
||||
int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL *stream, vorbis_custom_codec_data *data);
|
||||
#endif/* VGM_USE_VORBIS */
|
||||
|
||||
#endif/*_VORBIS_CUSTOM_DECODER_H_ */
|
||||
|
|
|
@ -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
|
|
@ -13,25 +13,17 @@
|
|||
/* DEFS */
|
||||
/* **************************************************************************** */
|
||||
|
||||
/* An internal struct to pass around and simulate a bitstream.
|
||||
* Mainly to keep code cleaner and somewhat closer to ww2ogg */
|
||||
typedef struct {
|
||||
uint8_t * buf; /* buffer to read/write*/
|
||||
size_t bufsize; /* max size of the buffer */
|
||||
off_t b_off; /* current offset in bits inside the buffer */
|
||||
} ww_bitstream;
|
||||
|
||||
static int build_header_identification(uint8_t * buf, size_t bufsize, int channels, int sample_rate, int blocksize_short, int blocksize_long);
|
||||
static int build_header_comment(uint8_t * buf, size_t bufsize);
|
||||
static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_t header_type, int * granulepos, size_t * packet_size, int big_endian);
|
||||
static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
|
||||
static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels);
|
||||
|
||||
static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
|
||||
static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile);
|
||||
static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw);
|
||||
static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile);
|
||||
static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile);
|
||||
static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
|
||||
static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile);
|
||||
static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw);
|
||||
static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile);
|
||||
static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile);
|
||||
static int ww2ogg_tremor_ilog(unsigned int v);
|
||||
static unsigned int ww2ogg_tremor_book_maptype1_quantvals(unsigned int entries, unsigned int dimensions);
|
||||
|
||||
|
@ -39,9 +31,6 @@ static int load_wvc(uint8_t * ibuf, size_t ibufsize, uint32_t codebook_id, wwise
|
|||
static int load_wvc_file(uint8_t * buf, size_t bufsize, uint32_t codebook_id, STREAMFILE *streamFile);
|
||||
static int load_wvc_array(uint8_t * buf, size_t bufsize, uint32_t codebook_id, wwise_setup_t setup_type);
|
||||
|
||||
static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value);
|
||||
static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value);
|
||||
|
||||
|
||||
/* **************************************************************************** */
|
||||
/* EXTERNAL API */
|
||||
|
@ -165,7 +154,7 @@ static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_
|
|||
|
||||
/* Transforms a Wwise data packet into a real Vorbis one (depending on config) */
|
||||
static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
|
||||
ww_bitstream ow, iw;
|
||||
vgm_bitstream ow, iw;
|
||||
int rc, granulepos;
|
||||
size_t header_size, packet_size;
|
||||
|
||||
|
@ -183,11 +172,13 @@ static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFil
|
|||
/* prepare helper structs */
|
||||
ow.buf = obuf;
|
||||
ow.bufsize = obufsize;
|
||||
ow.b_off = 0 ;
|
||||
ow.b_off = 0;
|
||||
ow.mode = BITSTREAM_VORBIS;
|
||||
|
||||
iw.buf = ibuf;
|
||||
iw.bufsize = ibufsize;
|
||||
iw.b_off = 0;
|
||||
iw.mode = BITSTREAM_VORBIS;
|
||||
|
||||
rc = ww2ogg_generate_vorbis_packet(&ow,&iw, streamFile,offset, data, big_endian);
|
||||
if (!rc) goto fail;
|
||||
|
@ -206,7 +197,7 @@ fail:
|
|||
|
||||
/* Transforms a Wwise setup packet into a real Vorbis one (depending on config). */
|
||||
static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels) {
|
||||
ww_bitstream ow, iw;
|
||||
vgm_bitstream ow, iw;
|
||||
int rc, granulepos;
|
||||
size_t header_size, packet_size;
|
||||
|
||||
|
@ -226,10 +217,12 @@ static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile
|
|||
ow.buf = obuf;
|
||||
ow.bufsize = obufsize;
|
||||
ow.b_off = 0;
|
||||
ow.mode = BITSTREAM_VORBIS;
|
||||
|
||||
iw.buf = ibuf;
|
||||
iw.bufsize = ibufsize;
|
||||
iw.b_off = 0;
|
||||
iw.mode = BITSTREAM_VORBIS;
|
||||
|
||||
rc = ww2ogg_generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile);
|
||||
if (!rc) goto fail;
|
||||
|
@ -295,7 +288,7 @@ static int build_header_comment(uint8_t * buf, size_t bufsize) {
|
|||
|
||||
/* Copy packet as-is or rebuild first byte if mod_packets is used.
|
||||
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-720004.3) */
|
||||
static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
|
||||
static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
|
||||
int i,granule;
|
||||
size_t header_size, packet_size, data_size;
|
||||
|
||||
|
@ -350,10 +343,13 @@ static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, S
|
|||
/* get next first byte to read next_mode_number */
|
||||
uint32_t next_mode_number;
|
||||
uint8_t nbuf[1];
|
||||
ww_bitstream nw;
|
||||
vgm_bitstream nw;
|
||||
|
||||
nw.buf = nbuf;
|
||||
nw.bufsize = 1;
|
||||
nw.b_off = 0;
|
||||
nw.mode = BITSTREAM_VORBIS;
|
||||
|
||||
|
||||
if (read_streamfile(nw.buf, next_offset + next_header_size, nw.bufsize, streamFile) != nw.bufsize)
|
||||
goto fail;
|
||||
|
@ -409,7 +405,7 @@ fail:
|
|||
|
||||
/* Rebuild a Wwise setup (simplified with removed stuff), recreating all six setup parts.
|
||||
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4) */
|
||||
static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) {
|
||||
static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) {
|
||||
int i,j,k;
|
||||
uint32_t codebook_count = 0, floor_count = 0, residue_count = 0;
|
||||
uint32_t codebook_count_less1 = 0;
|
||||
|
@ -798,7 +794,7 @@ fail:
|
|||
|
||||
|
||||
/* copies Vorbis codebooks (untouched, but size uncertain) */
|
||||
static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw) {
|
||||
static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw) {
|
||||
int i;
|
||||
uint32_t id = 0, dimensions = 0, entries = 0;
|
||||
uint32_t ordered = 0, lookup_type = 0;
|
||||
|
@ -914,7 +910,7 @@ fail:
|
|||
|
||||
|
||||
/* rebuilds a Wwise codebook into a Vorbis codebook */
|
||||
static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) {
|
||||
static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) {
|
||||
int i;
|
||||
uint32_t id = 0, dimensions = 0, entries = 0;
|
||||
uint32_t ordered = 0, lookup_type = 0;
|
||||
|
@ -1038,11 +1034,11 @@ fail:
|
|||
}
|
||||
|
||||
/* rebuilds an external Wwise codebook referenced by id to a Vorbis codebook */
|
||||
static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) {
|
||||
static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) {
|
||||
size_t ibufsize = 0x8000; /* arbitrary max size of a codebook */
|
||||
uint8_t ibuf[0x8000]; /* Wwise codebook buffer */
|
||||
size_t cb_size;
|
||||
ww_bitstream iw;
|
||||
vgm_bitstream iw;
|
||||
|
||||
cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, streamFile);
|
||||
if (cb_size == 0) goto fail;
|
||||
|
@ -1050,6 +1046,7 @@ static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t cod
|
|||
iw.buf = ibuf;
|
||||
iw.bufsize = ibufsize;
|
||||
iw.b_off = 0;
|
||||
iw.mode = BITSTREAM_VORBIS;
|
||||
|
||||
return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, streamFile);
|
||||
fail:
|
||||
|
@ -1228,70 +1225,4 @@ fail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ********************************************* */
|
||||
|
||||
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
|
||||
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
|
||||
static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value) {
|
||||
off_t off, pos;
|
||||
int i, bit_buf, bit_val;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || iw->b_off + num_bits > iw->bufsize*8) goto fail;
|
||||
|
||||
*value = 0; /* set all bits to 0 */
|
||||
off = iw->b_off / 8; /* byte offset */
|
||||
pos = iw->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
|
||||
bit_val = (1U << i); /* bit to set in value */
|
||||
|
||||
if (iw->buf[off] & bit_buf) /* is bit in buf set? */
|
||||
*value |= bit_val; /* set bit */
|
||||
|
||||
pos++; /* new byte starts */
|
||||
if (pos%8 == 0) {
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
iw->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
|
||||
* (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/
|
||||
static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value) {
|
||||
off_t off, pos;
|
||||
int i, bit_val, bit_buf;
|
||||
if (num_bits == 0) return 1;
|
||||
if (num_bits > 32 || num_bits < 0 || ow->b_off + num_bits > ow->bufsize*8) goto fail;
|
||||
|
||||
|
||||
off = ow->b_off / 8; /* byte offset */
|
||||
pos = ow->b_off % 8; /* bit sub-offset */
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
bit_val = (1U << i); /* bit check for value */
|
||||
bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */
|
||||
|
||||
if (value & bit_val) /* is bit in val set? */
|
||||
ow->buf[off] |= bit_buf; /* set bit */
|
||||
else
|
||||
ow->buf[off] &= ~bit_buf; /* unset bit */
|
||||
|
||||
pos++; /* new byte starts */
|
||||
if (pos%8 == 0) {
|
||||
pos = 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
|
||||
ow->b_off += num_bits;
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,21 +7,21 @@ const int SHC = 10;
|
|||
double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125};
|
||||
double K1[4] = { 0.0, 0.0, -0.8125,-0.859375};
|
||||
|
||||
int IK0(int fid)
|
||||
static int IK0(int fid)
|
||||
{ return ((int)((-K0[fid]) * (1 << SHC))); }
|
||||
|
||||
int IK1(int fid)
|
||||
static int IK1(int fid)
|
||||
{ return ((int)((-K1[fid]) * (1 << SHC))); }
|
||||
|
||||
int CLAMP(int value, int Minim, int Maxim)
|
||||
static int CLAMP(int value, int Minim, int Maxim)
|
||||
{
|
||||
if (value < Minim) value = Minim;
|
||||
if (value > Maxim) value = Maxim;
|
||||
return value;
|
||||
}
|
||||
|
||||
void init_get_high_nibble(VGMSTREAM *vgmstream) {
|
||||
vgmstream->get_high_nibble=1;
|
||||
void xa_init_get_high_nibble(VGMSTREAM *vgmstream) {
|
||||
vgmstream->xa_get_high_nibble=1;
|
||||
}
|
||||
|
||||
void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
|
@ -41,18 +41,18 @@ void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32
|
|||
|
||||
first_sample = first_sample % 28;
|
||||
|
||||
vgmstream->get_high_nibble=!vgmstream->get_high_nibble;
|
||||
vgmstream->xa_get_high_nibble=!vgmstream->xa_get_high_nibble;
|
||||
|
||||
if((first_sample) && (channelspacing==1))
|
||||
vgmstream->get_high_nibble=!vgmstream->get_high_nibble;
|
||||
vgmstream->xa_get_high_nibble=!vgmstream->xa_get_high_nibble;
|
||||
|
||||
predict_nr = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) >> 4;
|
||||
shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) & 0xf;
|
||||
predict_nr = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->xa_get_high_nibble,stream->streamfile) >> 4;
|
||||
shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->xa_get_high_nibble,stream->streamfile) & 0xf;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
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 & 0x0f)<<12);
|
||||
|
||||
|
@ -70,3 +70,13 @@ void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32
|
|||
stream->adpcm_history1_32=hist1;
|
||||
stream->adpcm_history2_32=hist2;
|
||||
}
|
||||
|
||||
size_t xa_bytes_to_samples(size_t bytes, int channels, int is_blocked) {
|
||||
if (is_blocked) {
|
||||
//todo with -0x10 misses the last sector, not sure if bug or feature
|
||||
return ((bytes - 0x10) / 0x930) * (0x900 - 18*0x10) * 2 / channels;
|
||||
}
|
||||
else {
|
||||
return ((bytes / 0x80)*0xE0) / 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "formats.h"
|
||||
#include "vgmstream.h"
|
||||
|
||||
//#define VGM_REGISTER_TYPE(extension) ...
|
||||
//#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */
|
||||
|
@ -52,6 +52,7 @@ static const char* extension_list[] = {
|
|||
"bar",
|
||||
"bcstm",
|
||||
"bcwav",
|
||||
"bd3", //txth/reserved [Elevator Action Deluxe (PS3)]
|
||||
"bdsp",
|
||||
"bfstm",
|
||||
"bfwav",
|
||||
|
@ -81,6 +82,7 @@ static const char* extension_list[] = {
|
|||
"capdsp",
|
||||
"cbd2",
|
||||
"ccc",
|
||||
"cd",
|
||||
"cfn",
|
||||
"ckd",
|
||||
"cnk",
|
||||
|
@ -92,6 +94,7 @@ static const char* extension_list[] = {
|
|||
"dcs",
|
||||
"ddsp",
|
||||
"de2",
|
||||
"dec",
|
||||
"dmsg",
|
||||
"dsp",
|
||||
"dspw",
|
||||
|
@ -103,10 +106,12 @@ static const char* extension_list[] = {
|
|||
"emff",
|
||||
"enth",
|
||||
"exa",
|
||||
"ezw",
|
||||
|
||||
"fag",
|
||||
"ffw",
|
||||
"filp",
|
||||
"flx",
|
||||
"fsb",
|
||||
"fwav",
|
||||
|
||||
|
@ -132,7 +137,7 @@ static const char* extension_list[] = {
|
|||
"iab",
|
||||
"iadp",
|
||||
"idsp",
|
||||
"idvi",
|
||||
"idvi", //fake extension (to be removed)
|
||||
"ikm",
|
||||
"ild",
|
||||
"int",
|
||||
|
@ -147,12 +152,13 @@ static const char* extension_list[] = {
|
|||
"jstm",
|
||||
|
||||
"kces",
|
||||
"kcey",
|
||||
"kcey", //fake extension (to be removed)
|
||||
"khv",
|
||||
"kovs",
|
||||
"kraw",
|
||||
|
||||
"laac", //fake extension, for AAC (tri-Ace/FFmpeg)
|
||||
"lac3", //fake extension, for AC3
|
||||
"leg",
|
||||
"lmp4", //fake extension, for MP4s
|
||||
"logg", //fake extension, for OGGs
|
||||
|
@ -174,7 +180,9 @@ static const char* extension_list[] = {
|
|||
"mic",
|
||||
"mihb",
|
||||
"mnstr",
|
||||
"mogg",
|
||||
//"mp4", //common
|
||||
//"mpc", //FFmpeg, not parsed (musepack) //common
|
||||
"mpdsp",
|
||||
"mpds",
|
||||
"msa",
|
||||
|
@ -190,6 +198,7 @@ static const char* extension_list[] = {
|
|||
"mxst",
|
||||
"myspd",
|
||||
|
||||
"naac",
|
||||
"ndp",
|
||||
"ngca",
|
||||
"nps",
|
||||
|
@ -201,7 +210,7 @@ static const char* extension_list[] = {
|
|||
"ogl",
|
||||
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
|
||||
"omu",
|
||||
"opus",
|
||||
//"opus", //common
|
||||
"otm",
|
||||
|
||||
"p1d", //txth/reserved [Farming Simulator 18 (3DS)]
|
||||
|
@ -226,7 +235,8 @@ static const char* extension_list[] = {
|
|||
"rrds",
|
||||
"rsd",
|
||||
"rsf",
|
||||
"rstm",
|
||||
"rsm",
|
||||
"rstm", //rsm header id
|
||||
"rvws",
|
||||
"rwar",
|
||||
"rwav",
|
||||
|
@ -239,10 +249,19 @@ static const char* extension_list[] = {
|
|||
"sab",
|
||||
"sad",
|
||||
"sap",
|
||||
"sb0",
|
||||
"sb1",
|
||||
"sb2",
|
||||
"sb3",
|
||||
"sb4",
|
||||
"sb5",
|
||||
"sb6",
|
||||
"sb7",
|
||||
"sc",
|
||||
"scd",
|
||||
"sck",
|
||||
"sd9",
|
||||
"sdf",
|
||||
"sdt",
|
||||
"seg",
|
||||
"sf0",
|
||||
|
@ -255,10 +274,11 @@ static const char* extension_list[] = {
|
|||
"sl3",
|
||||
"sli",
|
||||
"smp",
|
||||
"smpl",
|
||||
"smpl", //fake extension (to be removed)
|
||||
"snd",
|
||||
"snds",
|
||||
"sng",
|
||||
"snr",
|
||||
"sns",
|
||||
"snu",
|
||||
"spd",
|
||||
|
@ -267,8 +287,6 @@ static const char* extension_list[] = {
|
|||
"spsd",
|
||||
"spw",
|
||||
"ss2",
|
||||
"ss3",
|
||||
"ss7",
|
||||
"ssm",
|
||||
"sss",
|
||||
"ster",
|
||||
|
@ -299,21 +317,24 @@ static const char* extension_list[] = {
|
|||
"ulw",
|
||||
"um3",
|
||||
|
||||
"v0",
|
||||
//"v1", //dual channel with v0
|
||||
"vag",
|
||||
"vas",
|
||||
"vawx",
|
||||
"vb",
|
||||
"vbk",
|
||||
"vds",
|
||||
"vdm",
|
||||
"vgs",
|
||||
"vgv",
|
||||
"vig",
|
||||
"vds",
|
||||
"vdm",
|
||||
"vms",
|
||||
"voi",
|
||||
"vpk",
|
||||
"vs",
|
||||
"vsf",
|
||||
"vxn",
|
||||
|
||||
"waa",
|
||||
"wac",
|
||||
|
@ -365,22 +386,12 @@ static const char* extension_list[] = {
|
|||
//, NULL //end mark
|
||||
};
|
||||
|
||||
/**
|
||||
* List of supported formats.
|
||||
*
|
||||
* For plugins that need to know (test.exe doesn't use it)
|
||||
*/
|
||||
const char ** vgmstream_get_formats() {
|
||||
/* List supported formats and return elements in the list, for plugins that need to know. */
|
||||
const char ** vgmstream_get_formats(size_t * size) {
|
||||
*size = sizeof(extension_list) / sizeof(char*);
|
||||
return extension_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of elements in the list.
|
||||
*/
|
||||
int vgmstream_get_formats_length() {
|
||||
return sizeof(extension_list) / sizeof(char*);
|
||||
}
|
||||
|
||||
|
||||
/* internal description info */
|
||||
|
||||
|
@ -404,51 +415,54 @@ static const coding_info coding_info_list[] = {
|
|||
{coding_PCM16LE, "Little Endian 16-bit PCM"},
|
||||
{coding_PCM16LE_XOR_int, "Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"},
|
||||
{coding_PCM16BE, "Big Endian 16-bit PCM"},
|
||||
{coding_PCM16_int, "16-bit PCM with 2 byte interleave"},
|
||||
{coding_PCM16_int, "16-bit PCM with 2 byte interleave (block)"},
|
||||
{coding_PCM8, "8-bit PCM"},
|
||||
{coding_PCM8_int, "8-bit PCM with 1 byte interleave (block)"},
|
||||
{coding_PCM8_U, "8-bit unsigned PCM"},
|
||||
{coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave"},
|
||||
{coding_PCM8_int, "8-bit PCM with 1 byte interleave"},
|
||||
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"},
|
||||
{coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave (block)"},
|
||||
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave (block)"},
|
||||
{coding_ULAW, "8-bit u-Law"},
|
||||
{coding_ALAW, "8-bit a-Law"},
|
||||
{coding_PCMFLOAT, "32-bit float PCM"},
|
||||
|
||||
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
|
||||
{coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM with exponential scale"},
|
||||
{coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM with fixed coefficients"},
|
||||
{coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM (fixed coefficients)"},
|
||||
{coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM (exponential scale)"},
|
||||
{coding_CRI_ADX_enc_8, "CRI ADX 4-bit ADPCM (type 8 encryption)"},
|
||||
{coding_CRI_ADX_enc_9, "CRI ADX 4-bit ADPCM (type 9 encryption)"},
|
||||
|
||||
{coding_NGC_DSP, "Nintendo DSP 4-bit ADPCM"},
|
||||
{coding_NGC_DSP_subint, "Nintendo DSP 4-bit ADPCM (subinterleave)"},
|
||||
{coding_NGC_DTK, "Nintendo DTK 4-bit ADPCM"},
|
||||
{coding_NGC_AFC, "Nintendo AFC 4-bit ADPCM"},
|
||||
{coding_CRI_HCA, "CRI HCA"},
|
||||
{coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"},
|
||||
{coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"},
|
||||
|
||||
{coding_G721, "CCITT G.721 4-bit ADPCM"},
|
||||
|
||||
{coding_XA, "CD-ROM XA 4-bit ADPCM"},
|
||||
{coding_PSX, "Playstation 4-bit ADPCM"},
|
||||
{coding_PSX_badflags, "Playstation 4-bit ADPCM (bad flags)"},
|
||||
{coding_PSX_bmdx, "Playstation 4-bit ADPCM (BMDX encryption)"},
|
||||
{coding_PSX_cfg, "Playstation 4-bit ADPCM (configurable)"},
|
||||
{coding_HEVAG, "Playstation Vita HEVAG 4-bit ADPCM"},
|
||||
{coding_XA, "CD-ROM XA 4-bit ADPCM"},
|
||||
{coding_XBOX, "XBOX 4-bit IMA ADPCM"},
|
||||
{coding_XBOX_int, "XBOX 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM (v1)"},
|
||||
{coding_EA_XA_int, "Electronic Arts EA-XA 4-bit ADPCM (v1) (interleaved)"},
|
||||
{coding_EA_XA_V2, "Electronic Arts EA-XA 4-bit ADPCM (v2)"},
|
||||
|
||||
{coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM v1"},
|
||||
{coding_EA_XA_int, "Electronic Arts EA-XA 4-bit ADPCM v1 (mono/interleave)"},
|
||||
{coding_EA_XA_V2, "Electronic Arts EA-XA 4-bit ADPCM v2"},
|
||||
{coding_MAXIS_XA, "Maxis EA-XA 4-bit ADPCM"},
|
||||
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
|
||||
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"},
|
||||
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
|
||||
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"},
|
||||
{coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"},
|
||||
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_EACS_IMA, "EACS 4-bit IMA ADPCM"},
|
||||
{coding_IMA_int, "IMA 4-bit ADPCM (interleaved)"},
|
||||
{coding_EA_XAS, "Electronic Arts EA-XAS 4-bit ADPCM"},
|
||||
|
||||
{coding_IMA, "IMA 4-bit ADPCM"},
|
||||
{coding_IMA_int, "IMA 4-bit ADPCM (mono/interleave)"},
|
||||
{coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"},
|
||||
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (mono/interleave)"},
|
||||
{coding_3DS_IMA, "3DS IMA 4-bit ADPCM"},
|
||||
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
|
||||
{coding_XBOX, "XBOX 4-bit IMA ADPCM"},
|
||||
{coding_XBOX_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"},
|
||||
{coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"},
|
||||
{coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"},
|
||||
{coding_RAD_IMA, "Radical 4-bit IMA ADPCM"},
|
||||
{coding_RAD_IMA_mono, "Radical 4-bit IMA ADPCM (mono)"},
|
||||
{coding_RAD_IMA_mono, "Radical 4-bit IMA ADPCM (mono/interleave)"},
|
||||
{coding_APPLE_IMA4, "Apple Quicktime 4-bit IMA ADPCM"},
|
||||
{coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"},
|
||||
{coding_OTNS_IMA, "Omikron: The Nomad Soul 4-bit IMA ADPCM"},
|
||||
|
@ -456,15 +470,10 @@ static const coding_info coding_info_list[] = {
|
|||
{coding_WWISE_IMA, "Audiokinetic Wwise 4-bit IMA ADPCM"},
|
||||
{coding_REF_IMA, "Reflections 4-bit IMA ADPCM"},
|
||||
{coding_AWC_IMA, "Rockstar AWC 4-bit IMA ADPCM"},
|
||||
{coding_WS, "Westwood Studios VBR ADPCM"},
|
||||
{coding_ACM, "InterPlay ACM"},
|
||||
{coding_NWA0, "NWA DPCM Level 0"},
|
||||
{coding_NWA1, "NWA DPCM Level 1"},
|
||||
{coding_NWA2, "NWA DPCM Level 2"},
|
||||
{coding_NWA3, "NWA DPCM Level 3"},
|
||||
{coding_NWA4, "NWA DPCM Level 4"},
|
||||
{coding_NWA5, "NWA DPCM Level 5"},
|
||||
{coding_UBI_IMA, "Ubisoft 4-bit IMA ADPCM"},
|
||||
|
||||
{coding_MSADPCM, "Microsoft 4-bit ADPCM"},
|
||||
{coding_WS, "Westwood Studios VBR ADPCM"},
|
||||
{coding_AICA, "Yamaha AICA 4-bit ADPCM"},
|
||||
{coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"},
|
||||
{coding_L5_555, "Level-5 0x555 4-bit ADPCM"},
|
||||
|
@ -473,7 +482,22 @@ static const coding_info coding_info_list[] = {
|
|||
{coding_MTAF, "Konami MTAF 4-bit ADPCM"},
|
||||
{coding_MTA2, "Konami MTA2 4-bit ADPCM"},
|
||||
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
|
||||
{coding_EA_XAS, "Electronic Arts EA-XAS 4-bit ADPCM"},
|
||||
|
||||
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
|
||||
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"},
|
||||
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
|
||||
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"},
|
||||
{coding_ACM, "InterPlay ACM"},
|
||||
{coding_NWA0, "NWA DPCM Level 0"},
|
||||
{coding_NWA1, "NWA DPCM Level 1"},
|
||||
{coding_NWA2, "NWA DPCM Level 2"},
|
||||
{coding_NWA3, "NWA DPCM Level 3"},
|
||||
{coding_NWA4, "NWA DPCM Level 4"},
|
||||
{coding_NWA5, "NWA DPCM Level 5"},
|
||||
|
||||
{coding_EA_MT, "Electronic Arts MicroTalk"},
|
||||
|
||||
{coding_CRI_HCA, "CRI HCA"},
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{coding_ogg_vorbis, "Ogg Vorbis"},
|
||||
|
@ -505,20 +529,19 @@ static const layout_info layout_info_list[] = {
|
|||
{layout_none, "flat (no layout)"},
|
||||
{layout_interleave, "interleave"},
|
||||
{layout_interleave_shortblock, "interleave with short last block"},
|
||||
{layout_interleave_byte, "sub-frame interleave"},
|
||||
{layout_mxch_blocked, "MxCh blocked"},
|
||||
{layout_ast_blocked, "AST blocked"},
|
||||
{layout_halpst_blocked, "HALPST blocked"},
|
||||
{layout_xa_blocked, "CD-ROM XA"},
|
||||
{layout_ea_blocked, "Electronic Arts SCxx blocked"},
|
||||
{layout_eacs_blocked, "Electronic Arts EACS blocked"},
|
||||
{layout_blocked_ea_schl, "blocked (EA SCHl)"},
|
||||
{layout_blocked_ea_1snh, "blocked (EA 1SNh)"},
|
||||
{layout_caf_blocked, "CAF blocked"},
|
||||
{layout_wsi_blocked, ".wsi blocked"},
|
||||
{layout_xvas_blocked, ".xvas blocked"},
|
||||
{layout_str_snds_blocked, ".str SNDS blocked"},
|
||||
{layout_ws_aud_blocked, "Westwood Studios .aud blocked"},
|
||||
{layout_matx_blocked, "Matrix .matx blocked"},
|
||||
{layout_de2_blocked, "de2 blocked"},
|
||||
{layout_blocked_dec, "blocked (DEC)"},
|
||||
{layout_vs_blocked, "vs blocked"},
|
||||
{layout_emff_ps2_blocked, "EMFF (PS2) blocked"},
|
||||
{layout_emff_ngc_blocked, "EMFF (NGC/WII) blocked"},
|
||||
|
@ -528,7 +551,7 @@ static const layout_info layout_info_list[] = {
|
|||
{layout_psx_mgav_blocked, "MGAV blocked"},
|
||||
{layout_ps2_adm_blocked, "ADM blocked"},
|
||||
{layout_dsp_bdsp_blocked, "DSP blocked"},
|
||||
{layout_ivaud_blocked, "GTA IV blocked"},
|
||||
{layout_blocked_ivaud, "blocked (IVAUD)"},
|
||||
{layout_ps2_iab_blocked, "IAB blocked"},
|
||||
{layout_ps2_strlr_blocked, "The Bouncer STR blocked"},
|
||||
{layout_rws_blocked, "RWS blocked"},
|
||||
|
@ -539,9 +562,10 @@ static const layout_info layout_info_list[] = {
|
|||
{layout_aix, "AIX interleave, internally 18-byte interleaved"},
|
||||
{layout_aax, "AAX blocked, 18-byte interleaved"},
|
||||
{layout_scd_int, "SCD multistream interleave"},
|
||||
{layout_ea_sns_blocked, "Electronic Arts SNS blocked"},
|
||||
{layout_blocked_ea_sns, "blocked (EA SNS)"},
|
||||
{layout_blocked_awc, "blocked (AWC)"},
|
||||
{layout_blocked_vgs, "blocked (VGS)"},
|
||||
{layout_blocked_vawx, "blocked (VAWX)"},
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{layout_ogg_vorbis, "Ogg"},
|
||||
#endif
|
||||
|
@ -561,8 +585,8 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_UTF_DSP, "CRI ADPCM_WII header"},
|
||||
{meta_DSP_AGSC, "Retro Studios AGSC header"},
|
||||
{meta_DSP_CSMP, "Retro Studios CSMP header"},
|
||||
{meta_NGC_ADPDTK, "assumed Nintendo ADP by .adp extension and valid first frame"},
|
||||
{meta_RSF, "assumed Retro Studios RSF by .rsf extension and valid first bytes"},
|
||||
{meta_NGC_ADPDTK, "Nintendo ADP raw header"},
|
||||
{meta_RSF, "Retro Studios RSF raw header"},
|
||||
{meta_AFC, "Nintendo AFC header"},
|
||||
{meta_AST, "Nintendo AST header"},
|
||||
{meta_HALPST, "HAL Laboratory HALPST header"},
|
||||
|
@ -631,9 +655,7 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_HGC1, "Knights of the Temple 2 hgC1 Header"},
|
||||
{meta_AUS, "Capcom AUS Header"},
|
||||
{meta_RWS, "RenderWare RWS header"},
|
||||
{meta_EACS_PC, "Electronic Arts EACS header (PC)"},
|
||||
{meta_EACS_PSX, "Electronic Arts EACS header (PSX)"},
|
||||
{meta_EACS_SAT, "Electronic Arts EACS header (SATURN)"},
|
||||
{meta_EA_1SNH, "Electronic Arts 1SNh/EACS header"},
|
||||
{meta_SL3, "SL3 Header"},
|
||||
{meta_FSB1, "FMOD Sample Bank (FSB1) Header"},
|
||||
{meta_FSB2, "FMOD Sample Bank (FSB2) Header"},
|
||||
|
@ -653,8 +675,8 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_FILP, "Bio Hazard - Gun Survivor FILp Header"},
|
||||
{meta_IKM, "Zwei!! IKM Header"},
|
||||
{meta_SFS, "Baroque SFS Header"},
|
||||
{meta_DVI, "DVI Header"},
|
||||
{meta_KCEY, "KCEYCOMP Header"},
|
||||
{meta_SAT_DVI, "Konami KCEN DVI. header"},
|
||||
{meta_DC_KCEY, "Konami KCEY KCEYCOMP header"},
|
||||
{meta_BG00, "Falcom BG00 Header"},
|
||||
{meta_PS2_RSTM, "Rockstar Games RSTM Header"},
|
||||
{meta_ACM, "InterPlay ACM Header"},
|
||||
|
@ -667,8 +689,8 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_RIFX_WAVE, "RIFX WAVE header"},
|
||||
{meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"},
|
||||
{meta_XNB, "Microsoft XNA Game Studio 4.0 header"},
|
||||
{meta_PCM_SCD, "PCM file with custom header (SCD)"},
|
||||
{meta_PCM_PS2, "PCM file with custom header (PS2)"},
|
||||
{meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"},
|
||||
{meta_PS2_PCM, "Konami KCEJ East .PCM header"},
|
||||
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"},
|
||||
{meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"},
|
||||
{meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"},
|
||||
|
@ -676,14 +698,15 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_XBOX_WVS, "Metal Arms WVS Header (XBOX)"},
|
||||
{meta_NGC_WVS, "Metal Arms WVS Header (GameCube)"},
|
||||
{meta_XBOX_MATX, "assumed Matrix file by .matx extension"},
|
||||
{meta_DE2, "gurumin .de2 with embedded funky RIFF"},
|
||||
{meta_DEC, "Falcom DEC RIFF header"},
|
||||
{meta_VS, "Men in Black VS Header"},
|
||||
{meta_DC_STR, "Sega Stream Asset Builder header"},
|
||||
{meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"},
|
||||
{meta_XBOX_XMU, "XMU header"},
|
||||
{meta_XBOX_XVAS, "assumed TMNT file by .xvas extension"},
|
||||
{meta_PS2_XA2, "Acclaim XA2 Header"},
|
||||
{meta_DC_IDVI, "IDVI Header"},
|
||||
{meta_DC_IDVI, "Capcom IDVI header"},
|
||||
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"},
|
||||
{meta_NGC_YMF, "YMF DSP Header"},
|
||||
{meta_PS2_CCC, "CCC Header"},
|
||||
{meta_PSX_FAG, "FAG Header"},
|
||||
|
@ -769,14 +792,14 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_NGC_SWD, "PSF + Standard DSP Headers"},
|
||||
{meta_CAFF, "Apple Core Audio Format Header"},
|
||||
{meta_PC_MXST, "Lego Island MxSt Header"},
|
||||
{meta_PC_SOB_SAB, "Worms 4: Mayhem SOB/SAB Header"},
|
||||
{meta_SAB, "Team17 SAB header"},
|
||||
{meta_MAXIS_XA, "Maxis XAI/XAJ Header"},
|
||||
{meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"},
|
||||
{meta_WII_BNS, "Nintendo BNS header"},
|
||||
{meta_WII_WAS, "WAS (iSWS) DSP header"},
|
||||
{meta_XBOX_HLWAV, "Half Life 2 bgm header"},
|
||||
{meta_STX, "Nintendo .stx header"},
|
||||
{meta_MYSPD, "U-Sing .myspd header"},
|
||||
{meta_MYSPD, "U-Sing .MYSPD header"},
|
||||
{meta_HIS, "Her Interactive Sound header"},
|
||||
{meta_PS2_AST, "KOEI AST header"},
|
||||
{meta_CAPDSP, "Capcom DSP header"},
|
||||
|
@ -788,15 +811,15 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_PS2_STER, "STER Header"},
|
||||
{meta_BNSF, "Namco Bandai BNSF header"},
|
||||
{meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"},
|
||||
{meta_S14, "assumed Polycom Siren 14 by .s14 extension"},
|
||||
{meta_SSS, "assumed Polycom Siren 14 by .sss extension"},
|
||||
{meta_S14, "Namco .S14 raw header"},
|
||||
{meta_SSS, "Namco .SSS raw header"},
|
||||
{meta_PS2_GCM, "GCM 'MCG' Header"},
|
||||
{meta_PS2_SMPL, "Homura 'SMPL' Header"},
|
||||
{meta_PS2_SMPL, "Homura SMPL header"},
|
||||
{meta_PS2_MSA, "Psyvariar -Complete Edition- MSA header"},
|
||||
{meta_PC_SMP, "Ghostbusters .smp Header"},
|
||||
{meta_NGC_PDT, "PDT DSP header"},
|
||||
{meta_NGC_BO2, "Blood Omen 2 DSP header"},
|
||||
{meta_P3D, "Radical P3D Header"},
|
||||
{meta_P3D, "Radical P3D header"},
|
||||
{meta_PS2_TK1, "Tekken TK5STRM1 Header"},
|
||||
{meta_PS2_ADSC, "ADSC Header"},
|
||||
{meta_NGC_DSP_MPDS, "MPDS DSP header"},
|
||||
|
@ -826,7 +849,7 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_NGCA, "NGCA header"},
|
||||
{meta_WII_RAS, "RAS header"},
|
||||
{meta_PS2_SPM, "SPM header"},
|
||||
{meta_X360_TRA, "assumed DefJam Rapstar Audio File by .tra extension"},
|
||||
{meta_X360_TRA, "Terminal Reality .TRA raw header"},
|
||||
{meta_PS2_VGS, "Princess Soft VGS header"},
|
||||
{meta_PS2_IAB, "IAB header"},
|
||||
{meta_PS2_STRLR, "STR L/R header"},
|
||||
|
@ -844,7 +867,7 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_PS2_MTAF, "Konami MTAF header"},
|
||||
{meta_PS2_VAG1, "Konami VAG Mono header (VAG1)"},
|
||||
{meta_PS2_VAG2, "Konami VAG Stereo header (VAG2)"},
|
||||
{meta_TUN, "TUN 'ALP' header"},
|
||||
{meta_TUN, "Lego Racers ALP header"},
|
||||
{meta_WPD, "WPD 'DPW' header"},
|
||||
{meta_MN_STR, "Mini Ninjas 'STR' header"},
|
||||
{meta_MSS, "Guerilla MCSS header"},
|
||||
|
@ -870,7 +893,7 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_NUB_XMA, "Namco NUB XMA header"},
|
||||
{meta_X360_PASX, "Namco PASX header"},
|
||||
{meta_XMA_RIFF, "Microsoft XMA RIFF header"},
|
||||
{meta_X360_AST, "Capcom AST header"},
|
||||
{meta_X360_AST, "Capcom AST (X360) header"},
|
||||
{meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"},
|
||||
{meta_UBI_RAKI, "Ubisoft RAKI header"},
|
||||
{meta_SXD, "Sony SXD header"},
|
||||
|
@ -891,8 +914,19 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_BINK, "RAD Game Tools Bink header"},
|
||||
{meta_EA_SNU, "Electronic Arts SNU header"},
|
||||
{meta_AWC, "Rockstar AWC header"},
|
||||
{meta_NSW_OPUS, ".OPUS header"},
|
||||
{meta_NSW_OPUS, "Nintendo Switch OPUS header"},
|
||||
{meta_PC_AL2, "Illwinter Game Design AL2 raw header"},
|
||||
{meta_PC_AST, "Capcom AST (PC) header"},
|
||||
{meta_UBI_SB, "Ubisoft SBx header"},
|
||||
{meta_NAAC, "Namco NAAC header"},
|
||||
{meta_EZW, "EZ2DJ EZWAVE header"},
|
||||
{meta_VXN, "Gameloft VXN header"},
|
||||
{meta_EA_SNR_SNS, "Electronic Arts SNR+SNS header"},
|
||||
{meta_EA_SPS, "Electronic Arts SPS header"},
|
||||
{meta_NGC_VID1, "Neversoft VID1 header"},
|
||||
{meta_PC_FLX, "Ultima IX .FLX header"},
|
||||
{meta_MOGG, "Harmonix Music Systems MOGG Vorbis "},
|
||||
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
||||
|
|
|
@ -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_ */
|
|
@ -8,23 +8,24 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||
int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
|
||||
int samples_this_block;
|
||||
|
||||
/* get samples in the current block */
|
||||
if (vgmstream->current_block_samples) {
|
||||
samples_this_block = vgmstream->current_block_samples;
|
||||
} else if (frame_size == 0) {
|
||||
/* assume 4 bit */
|
||||
/* TODO: get_vgmstream_frame_size() really should return bits... */
|
||||
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
|
||||
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
|
||||
} else {
|
||||
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
|
||||
}
|
||||
|
||||
while (samples_written<sample_count) {
|
||||
/* decode all samples */
|
||||
while (samples_written < sample_count) {
|
||||
int samples_to_do;
|
||||
|
||||
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
|
||||
/* on loop those values are changed */
|
||||
if (vgmstream->current_block_samples) {
|
||||
samples_this_block = vgmstream->current_block_samples;
|
||||
} else if (frame_size == 0) {
|
||||
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
|
||||
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
|
||||
} else {
|
||||
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
|
||||
|
@ -32,52 +33,62 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||
continue;
|
||||
}
|
||||
|
||||
/* probably block bug or EOF, next calcs would give wrong values and buffer segfaults */
|
||||
if (samples_this_block <= 0) {
|
||||
VGM_LOG("layout_blocked: empty/wrong block\n");
|
||||
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
|
||||
if (samples_written + samples_to_do > sample_count)
|
||||
samples_to_do = sample_count - samples_written;
|
||||
|
||||
if (samples_written+samples_to_do > sample_count)
|
||||
samples_to_do=sample_count-samples_written;
|
||||
|
||||
if (vgmstream->current_block_offset>=0)
|
||||
if (vgmstream->current_block_offset >= 0) {
|
||||
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer);
|
||||
}
|
||||
else {
|
||||
/* block end signal (used below): partially 0-set buffer */
|
||||
int i;
|
||||
/* we've run off the end! */
|
||||
for (i=samples_written*vgmstream->channels;
|
||||
i<(samples_written+samples_to_do)*vgmstream->channels;i++)
|
||||
buffer[i]=0;
|
||||
for (i = samples_written*vgmstream->channels; i < (samples_written+samples_to_do)*vgmstream->channels; i++) {
|
||||
buffer[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
samples_written += samples_to_do;
|
||||
vgmstream->current_sample += samples_to_do;
|
||||
vgmstream->samples_into_block+=samples_to_do;
|
||||
vgmstream->samples_into_block += samples_to_do;
|
||||
|
||||
|
||||
/* move to next block when all samples are consumed */
|
||||
if (vgmstream->samples_into_block==samples_this_block
|
||||
/*&& vgmstream->current_sample < vgmstream->num_samples*/) { /* don't go past last block */
|
||||
switch (vgmstream->layout_type) {
|
||||
case layout_ast_blocked:
|
||||
ast_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_mxch_blocked:
|
||||
case layout_mxch_blocked:
|
||||
mxch_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_halpst_blocked:
|
||||
if (vgmstream->next_block_offset>=0)
|
||||
halpst_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
else
|
||||
vgmstream->current_block_offset=-1;
|
||||
vgmstream->current_block_offset = -1;
|
||||
break;
|
||||
case layout_xa_blocked:
|
||||
xa_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_blocked_ea_schl:
|
||||
block_update_ea_schl(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_blocked_ea_1snh:
|
||||
block_update_ea_1snh(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_caf_blocked:
|
||||
caf_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_xa_blocked:
|
||||
xa_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ea_blocked:
|
||||
ea_schl_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_eacs_blocked:
|
||||
eacs_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_caf_blocked:
|
||||
caf_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_wsi_blocked:
|
||||
wsi_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
|
@ -90,8 +101,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||
case layout_matx_blocked:
|
||||
matx_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_de2_blocked:
|
||||
de2_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
case layout_blocked_dec:
|
||||
block_update_dec(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_emff_ps2_blocked:
|
||||
emff_ps2_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
|
@ -105,33 +116,33 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||
case layout_vs_blocked:
|
||||
vs_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_xvas_blocked:
|
||||
xvas_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_thp_blocked:
|
||||
thp_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_filp_blocked:
|
||||
filp_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ivaud_blocked:
|
||||
ivaud_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_psx_mgav_blocked:
|
||||
psx_mgav_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ps2_adm_blocked:
|
||||
ps2_adm_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_dsp_bdsp_blocked:
|
||||
dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_tra_blocked:
|
||||
tra_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ps2_iab_blocked:
|
||||
ps2_iab_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_xvas_blocked:
|
||||
xvas_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_thp_blocked:
|
||||
thp_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_filp_blocked:
|
||||
filp_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_blocked_ivaud:
|
||||
block_update_ivaud(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_psx_mgav_blocked:
|
||||
psx_mgav_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ps2_adm_blocked:
|
||||
ps2_adm_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_dsp_bdsp_blocked:
|
||||
dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_tra_blocked:
|
||||
tra_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ps2_iab_blocked:
|
||||
ps2_iab_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ps2_strlr_blocked:
|
||||
ps2_strlr_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
|
@ -141,8 +152,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||
case layout_hwas_blocked:
|
||||
hwas_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_ea_sns_blocked:
|
||||
ea_sns_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
case layout_blocked_ea_sns:
|
||||
block_update_ea_sns(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_blocked_awc:
|
||||
block_update_awc(vgmstream->next_block_offset,vgmstream);
|
||||
|
@ -150,22 +161,27 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||
case layout_blocked_vgs:
|
||||
block_update_vgs(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
default:
|
||||
case layout_blocked_vawx:
|
||||
block_update_vawx(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* for VBR these may change */
|
||||
frame_size = get_vgmstream_frame_size(vgmstream);
|
||||
frame_size = get_vgmstream_frame_size(vgmstream); /* for VBR these may change */
|
||||
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
|
||||
|
||||
/* get samples in the current block */
|
||||
if (vgmstream->current_block_samples) {
|
||||
samples_this_block = vgmstream->current_block_samples;
|
||||
} else if (frame_size == 0) {
|
||||
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
|
||||
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
|
||||
} else {
|
||||
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
|
||||
}
|
||||
vgmstream->samples_into_block=0;
|
||||
|
||||
vgmstream->samples_into_block = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
#include "../vgmstream.h"
|
||||
|
||||
/* set up for the block at the given offset */
|
||||
void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
int i;
|
||||
int new_schl = 0;
|
||||
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
|
||||
|
@ -91,7 +91,7 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
|||
break;
|
||||
|
||||
/* id, size, IMA hist, stereo/mono data */
|
||||
case coding_EACS_IMA:
|
||||
case coding_DVI_IMA:
|
||||
for(i = 0; i < vgmstream->channels; i++) {
|
||||
off_t header_offset = block_offset + 0xc + i*4;
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_16bitLE(header_offset+0x00, vgmstream->ch[i].streamfile);
|
||||
|
@ -119,6 +119,17 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
|||
|
||||
break;
|
||||
|
||||
/* id, size, samples, offsets-per-channel, flag (0x01 = data start), data */
|
||||
case coding_EA_MT:
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
off_t channel_start = read_32bit(block_offset + 0x0C + (0x04*i),streamFile);
|
||||
vgmstream->ch[i].offset = block_offset + 0x0C + (0x04*vgmstream->channels) + channel_start + 0x01;
|
||||
}
|
||||
|
||||
/* flush decoder in every block change */
|
||||
flush_ea_mt(vgmstream);
|
||||
break;
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
/* id, size, samples, offset?, unknown (null for MP2, some constant for all blocks for EALayer3) */
|
||||
case coding_MPEG_custom:
|
||||
|
@ -161,64 +172,4 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
|||
vgmstream->next_block_offset = block_offset + block_size;
|
||||
vgmstream->current_block_samples = block_samples;
|
||||
vgmstream->current_block_size = 0; /* uses current_block_samples instead */
|
||||
|
||||
|
||||
/* reset channel sub offset for codecs using it */
|
||||
if (vgmstream->coding_type == coding_EA_XA
|
||||
|| vgmstream->coding_type == coding_EA_XA_int
|
||||
|| vgmstream->coding_type == coding_EA_XA_V2) {
|
||||
for(i=0;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;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
#include "../vgmstream.h"
|
||||
|
||||
/* EA "SNS "blocks (most common in .SNS) */
|
||||
void ea_sns_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
|
||||
uint32_t block_size, block_samples;
|
||||
size_t file_size = get_streamfile_size(streamFile);
|
||||
|
@ -21,15 +21,25 @@ void ea_sns_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* known: 0x80 = last block, 0x40, 0x08, 0x04, 0x01 */
|
||||
/* 0x80: last block
|
||||
* 0x40: new block for some codecs?
|
||||
* 0x08: ?
|
||||
* 0x04: new block for some codecs?
|
||||
* 0x01: last block for some codecs?
|
||||
* 0x00: none? */
|
||||
if (block_size & 0xFF000000) {
|
||||
VGM_ASSERT(!(block_size & 0x80000000), "EA SNS: unknown flag found at %lx\n", block_offset);
|
||||
//VGM_ASSERT(!(block_size & 0x80000000), "EA SNS: unknown flag found at %lx\n", block_offset);
|
||||
block_size &= 0x00FFFFFF;
|
||||
}
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
off_t channel_start = 0x00;
|
||||
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start;
|
||||
|
||||
/* also fix first offset (for EALayer3) */
|
||||
if (block_offset == vgmstream->ch[i].channel_start_offset) {
|
||||
vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset;
|
||||
}
|
||||
}
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
|
@ -2,7 +2,7 @@
|
|||
#include "../vgmstream.h"
|
||||
|
||||
/* set up for the block at the given offset */
|
||||
void ivaud_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
int i;
|
||||
off_t start_offset;
|
||||
off_t interleave_size;
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -5,19 +5,18 @@
|
|||
#include "../vgmstream.h"
|
||||
|
||||
/* blocked layouts */
|
||||
void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
||||
void ast_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
|
||||
|
||||
void mxch_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
|
||||
|
||||
void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
||||
void halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
|
||||
|
||||
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
|
@ -29,7 +28,7 @@ void ws_aud_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
|||
|
||||
void matx_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void de2_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_dec(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void vs_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
|
@ -45,7 +44,7 @@ void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
|||
|
||||
void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void ivaud_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
|
@ -63,18 +62,16 @@ void rws_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
|||
|
||||
void hwas_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void ea_sns_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_vgs(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_vawx(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
/* other layouts */
|
||||
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
||||
void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
||||
void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
||||
void render_vgmstream_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
||||
void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
|
|
@ -48,7 +48,7 @@ void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
|||
read_32bitBE(vgmstream->current_block_offset+4,
|
||||
vgmstream->ch[0].streamfile);
|
||||
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18;
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18 + i * vgmstream->interleave_block_size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
|||
nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile);
|
||||
|
||||
vgmstream->next_block_offset = vgmstream->current_block_offset
|
||||
+ vgmstream->thpNextFrameSize;
|
||||
vgmstream->thpNextFrameSize=nextFrameSize;
|
||||
+ vgmstream->full_block_size;
|
||||
vgmstream->full_block_size = nextFrameSize;
|
||||
|
||||
start_offset=vgmstream->current_block_offset
|
||||
+ read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10;
|
||||
|
|
|
@ -4,48 +4,69 @@
|
|||
|
||||
/* set up for the block at the given offset */
|
||||
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
int i;
|
||||
int8_t currentChannel=0;
|
||||
int8_t subAudio=0;
|
||||
|
||||
int i;
|
||||
int8_t currentChannel=0;
|
||||
int8_t subAudio=0;
|
||||
|
||||
init_get_high_nibble(vgmstream);
|
||||
xa_init_get_high_nibble(vgmstream);
|
||||
|
||||
if(vgmstream->samples_into_block!=0)
|
||||
// don't change this variable in the init process
|
||||
vgmstream->xa_sector_length+=128;
|
||||
/* don't change this variable in the init process */
|
||||
if (vgmstream->samples_into_block != 0)
|
||||
vgmstream->xa_sector_length += 0x80;
|
||||
|
||||
// We get to the end of a sector ?
|
||||
if(vgmstream->xa_sector_length==(18*128)) {
|
||||
vgmstream->xa_sector_length=0;
|
||||
/* XA mode2/form2 sector
|
||||
* 0x00: sync word
|
||||
* 0x0c: header = minute, second, sector, mode (always 0x02)
|
||||
* 0x10: subheader = file, channel (marker), submode flags, xa header
|
||||
* 0x14: subheader again
|
||||
* 0x18: data
|
||||
* 0x918: unused
|
||||
* 0x92c: EDC/checksum or null
|
||||
* 0x930: end
|
||||
*/
|
||||
|
||||
// 0x30 of unused bytes/sector :(
|
||||
if (!vgmstream->xa_headerless) {
|
||||
block_offset+=0x30;
|
||||
/* submode flags (typical audio value = 0x64)
|
||||
* - 7: end of file
|
||||
* - 6: real time mode
|
||||
* - 5: sector form (0=form1, 1=form2)
|
||||
* - 4: trigger (for application)
|
||||
* - 3: data sector
|
||||
* - 2: audio sector
|
||||
* - 1: video sector
|
||||
* - 0: end of audio
|
||||
*/
|
||||
|
||||
// We get to the end of a sector ?
|
||||
if (vgmstream->xa_sector_length == (18*0x80)) {
|
||||
vgmstream->xa_sector_length = 0;
|
||||
|
||||
// 0x30 of unused bytes/sector :(
|
||||
if (!vgmstream->xa_headerless) {
|
||||
block_offset += 0x30;
|
||||
begin:
|
||||
// Search for selected channel & valid audio
|
||||
currentChannel=read_8bit(block_offset-7,vgmstream->ch[0].streamfile);
|
||||
subAudio=read_8bit(block_offset-6,vgmstream->ch[0].streamfile);
|
||||
// Search for selected channel & valid audio
|
||||
currentChannel = read_8bit(block_offset-0x07,vgmstream->ch[0].streamfile);
|
||||
subAudio = read_8bit(block_offset-0x06,vgmstream->ch[0].streamfile);
|
||||
|
||||
// audio is coded as 0x64
|
||||
if(!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) {
|
||||
// go to next sector
|
||||
block_offset+=2352;
|
||||
if(currentChannel!=-1) goto begin;
|
||||
}
|
||||
}
|
||||
}
|
||||
// audio is coded as 0x64
|
||||
if (!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) {
|
||||
// go to next sector
|
||||
block_offset += 0x930;
|
||||
if (currentChannel!=-1) goto begin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
|
||||
// Quid : how to stop the current channel ???
|
||||
// i set up 0 to current_block_size to make vgmstream not playing bad samples
|
||||
// another way to do it ???
|
||||
// (as the number of samples can be false in cd-xa due to multi-channels)
|
||||
vgmstream->current_block_size = (currentChannel==-1?0:112);
|
||||
|
||||
vgmstream->next_block_offset = vgmstream->current_block_offset+128;
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].offset = vgmstream->current_block_offset;
|
||||
}
|
||||
// Quid : how to stop the current channel ???
|
||||
// i set up 0 to current_block_size to make vgmstream not playing bad samples
|
||||
// another way to do it ???
|
||||
// (as the number of samples can be false in cd-xa due to multi-channels)
|
||||
vgmstream->current_block_size = (currentChannel==-1 ? 0 : 0x70);
|
||||
|
||||
vgmstream->next_block_offset = vgmstream->current_block_offset + 0x80;
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].offset = vgmstream->current_block_offset;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include "../util.h"
|
||||
|
||||
/* .dsp w/ Cstr header, seen in Star Fox Assault and Donkey Konga */
|
||||
|
||||
VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
|
|
|
@ -1,16 +1,5 @@
|
|||
#include "../vgmstream.h"
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
typedef struct _AAXSTREAMFILE
|
||||
{
|
||||
STREAMFILE sf;
|
||||
STREAMFILE *real_file;
|
||||
off_t start_physical_offset;
|
||||
size_t file_size;
|
||||
} AAXSTREAMFILE;
|
||||
|
||||
static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size);
|
||||
#include "aax_streamfile.h"
|
||||
|
||||
struct utf_query
|
||||
{
|
||||
|
@ -107,10 +96,9 @@ struct utf_table_info
|
|||
};
|
||||
|
||||
|
||||
/* Actual AAX init fcn */
|
||||
/* AAX - segmented ADX [Padora's Tower (Wii)] */
|
||||
VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
|
||||
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
STREAMFILE * streamFileAAX = NULL;
|
||||
STREAMFILE * streamFileADX = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
|
@ -131,7 +119,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
|
|||
int channel_count = 0, segment_count;
|
||||
int sample_rate = 0;
|
||||
|
||||
int i;
|
||||
int i;
|
||||
|
||||
|
||||
long aax_data_offset;
|
||||
|
@ -297,91 +285,6 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* virtual file, a piece of the overall file */
|
||||
|
||||
static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
|
||||
{
|
||||
/* truncate at end of logical file */
|
||||
if (offset+length > streamfile->file_size)
|
||||
{
|
||||
long signed_length = length;
|
||||
signed_length = streamfile->file_size - offset;
|
||||
if (signed_length < 0) signed_length = 0;
|
||||
length = signed_length;
|
||||
}
|
||||
return read_streamfile(dest,
|
||||
streamfile->start_physical_offset+offset,
|
||||
length,streamfile->real_file);
|
||||
}
|
||||
|
||||
static void close_aax(AAXSTREAMFILE *streamfile)
|
||||
{
|
||||
free(streamfile);
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t get_size_aax(AAXSTREAMFILE *streamfile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t get_offset_aax(AAXSTREAMFILE *streamfile)
|
||||
{
|
||||
long offset = streamfile->real_file->get_offset(streamfile->real_file);
|
||||
offset -= streamfile->start_physical_offset;
|
||||
if (offset < 0) offset = 0;
|
||||
if (offset > streamfile->file_size) offset = streamfile->file_size;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void get_name_aax(AAXSTREAMFILE *streamfile,char *buffer,size_t length)
|
||||
{
|
||||
strncpy(buffer,"ARBITRARY.ADX",length);
|
||||
buffer[length-1]='\0';
|
||||
}
|
||||
|
||||
static STREAMFILE *open_aax_impl(AAXSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
|
||||
{
|
||||
AAXSTREAMFILE *newfile;
|
||||
if (strcmp(filename,"ARBITRARY.ADX"))
|
||||
return NULL;
|
||||
|
||||
newfile = malloc(sizeof(AAXSTREAMFILE));
|
||||
if (!newfile)
|
||||
return NULL;
|
||||
memcpy(newfile,streamfile,sizeof(AAXSTREAMFILE));
|
||||
return &newfile->sf;
|
||||
}
|
||||
|
||||
static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size)
|
||||
{
|
||||
AAXSTREAMFILE *streamfile = malloc(sizeof(AAXSTREAMFILE));
|
||||
|
||||
if (!streamfile)
|
||||
return NULL;
|
||||
|
||||
/* success, set our pointers */
|
||||
|
||||
streamfile->sf.read = (void*)read_aax;
|
||||
streamfile->sf.get_size = (void*)get_size_aax;
|
||||
streamfile->sf.get_offset = (void*)get_offset_aax;
|
||||
streamfile->sf.get_name = (void*)get_name_aax;
|
||||
streamfile->sf.get_realname = (void*)get_name_aax;
|
||||
streamfile->sf.open = (void*)open_aax_impl;
|
||||
streamfile->sf.close = (void*)close_aax;
|
||||
#ifdef PROFILE_STREAMFILE
|
||||
streamfile->sf.get_bytes_read = NULL;
|
||||
streamfile->sf.get_error_count = NULL;
|
||||
#endif
|
||||
|
||||
streamfile->real_file = file;
|
||||
streamfile->start_physical_offset = start_offset;
|
||||
streamfile->file_size = file_size;
|
||||
|
||||
return &streamfile->sf;
|
||||
}
|
||||
|
||||
/* @UTF table reading, abridged */
|
||||
static struct utf_query_result analyze_utf(STREAMFILE *infile, const long offset, const struct utf_query *query)
|
||||
{
|
||||
|
@ -744,8 +647,7 @@ static struct offset_size_pair query_utf_data(STREAMFILE *infile, const long off
|
|||
|
||||
/* CRI's UTF wrapper around DSP */
|
||||
VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
|
||||
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int table_error = 0;
|
||||
|
||||
|
@ -843,4 +745,3 @@ fail:
|
|||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_ */
|
|
@ -2,12 +2,13 @@
|
|||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "meta.h"
|
||||
|
||||
#include "meta.h"
|
||||
#include "adx_keys.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
#define MAX_TEST_FRAMES (INT_MAX/0x8000)
|
||||
|
||||
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add);
|
||||
|
||||
|
@ -233,270 +234,6 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* guessadx stuff */
|
||||
|
||||
/* type 8 keys */
|
||||
static struct {
|
||||
uint16_t start,mult,add;
|
||||
} keys_8[] = {
|
||||
/* Clover Studio (GOD HAND, Okami) */
|
||||
/* Verified by VGAudio and the game's executable */
|
||||
/* Key string: karaage */
|
||||
{0x49e1,0x4a57,0x553d},
|
||||
|
||||
/* Grasshopper Manufacture 0 (Blood+) */
|
||||
/* this is estimated */
|
||||
{0x5f5d,0x58bd,0x55ed},
|
||||
|
||||
/* Grasshopper Manufacture 1 (Killer7) */
|
||||
/* this is estimated */
|
||||
{0x50fb,0x5803,0x5701},
|
||||
|
||||
/* Grasshopper Manufacture 2 (Samurai Champloo) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x4f3f,0x472f,0x562f},
|
||||
|
||||
/* Moss Ltd (Raiden III) */
|
||||
/* this is estimated */
|
||||
{0x66f5,0x58bd,0x4459},
|
||||
|
||||
/* Sonic Team 0 (Phantasy Star Universe) */
|
||||
/* Verified by VGAudio and the game's executable */
|
||||
/* Key string: 3x5k62bg9ptbwy */
|
||||
{0x5deb,0x5f27,0x673f},
|
||||
|
||||
/* G.rev 0 (Senko no Ronde) */
|
||||
/* this is estimated */
|
||||
{0x46d3,0x5ced,0x474d},
|
||||
|
||||
/* Sonic Team 1 (NiGHTS: Journey of Dreams) */
|
||||
/* this seems to be dead on, but still estimated */
|
||||
{0x440b,0x6539,0x5723},
|
||||
|
||||
/* from guessadx (unique?), unknown source */
|
||||
{0x586d,0x5d65,0x63eb},
|
||||
|
||||
/* Navel (Shuffle! On the Stage) */
|
||||
/* 2nd key from guessadx */
|
||||
{0x4969,0x5deb,0x467f},
|
||||
|
||||
/* Success (Aoishiro) */
|
||||
/* 1st key from guessadx */
|
||||
{0x4d65,0x5eb7,0x5dfd},
|
||||
|
||||
/* Sonic Team 2 (Sonic and the Black Knight) */
|
||||
/* Verified by VGAudio and the game's executable */
|
||||
/* Key string: morio */
|
||||
{0x55b7,0x6191,0x5a77},
|
||||
|
||||
/* Enterbrain (Amagami) */
|
||||
/* Verified by VGAudio and the game's executable */
|
||||
/* Key string: mituba */
|
||||
{0x5a17,0x509f,0x5bfd},
|
||||
|
||||
/* Yamasa (Yamasa Digi Portable: Matsuri no Tatsujin) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x4c01,0x549d,0x676f},
|
||||
|
||||
/* Kadokawa Shoten (Fragments Blue) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x5803,0x4555,0x47bf},
|
||||
|
||||
/* Namco (Soulcalibur IV) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x59ed,0x4679,0x46c9},
|
||||
|
||||
/* G.rev 1 (Senko no Ronde DUO) */
|
||||
/* from guessadx */
|
||||
{0x6157,0x6809,0x4045},
|
||||
|
||||
/* ASCII Media Works 0 (Nogizaka Haruka no Himitsu: Cosplay Hajimemashita) */
|
||||
/* 2nd from guessadx, other was {0x45ad,0x5f27,0x10fd} */
|
||||
{0x45af,0x5f27,0x52b1},
|
||||
|
||||
/* D3 Publisher 0 (Little Anchor) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x5f65,0x5b3d,0x5f65},
|
||||
|
||||
/* Marvelous 0 (Hanayoi Romanesque: Ai to Kanashimi) */
|
||||
/* 2nd from guessadx, other was {0x5562,0x5047,0x1433} */
|
||||
{0x5563,0x5047,0x43ed},
|
||||
|
||||
/* Capcom (Mobile Suit Gundam: Gundam vs. Gundam NEXT PLUS) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x4f7b,0x4fdb,0x5cbf},
|
||||
|
||||
/* Developer: Bridge NetShop
|
||||
* Publisher: Kadokawa Shoten (Shoukan Shoujo: Elemental Girl Calling) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x4f7b,0x5071,0x4c61},
|
||||
|
||||
/* Developer: Net Corporation
|
||||
* Publisher: Tecmo (Rakushou! Pachi-Slot Sengen 6: Rio 2 Cruising Vanadis) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x53e9,0x586d,0x4eaf},
|
||||
|
||||
/* Developer: Aquaplus
|
||||
* Tears to Tiara Gaiden Avalon no Kagi (PS3) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x47e1,0x60e9,0x51c1},
|
||||
|
||||
/* Developer: Broccoli
|
||||
* Neon Genesis Evangelion: Koutetsu no Girlfriend 2nd (PS2) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x481d,0x4f25,0x5243},
|
||||
|
||||
/* Developer: Marvelous
|
||||
* Futakoi Alternative (PS2) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x413b,0x543b,0x57d1},
|
||||
|
||||
/* Developer: Marvelous
|
||||
* Gakuen Utopia - Manabi Straight! KiraKira Happy Festa! (PS2)
|
||||
* Second guess from guessadx, other was
|
||||
* {0x440b,0x4327,0x564b}
|
||||
**/
|
||||
{0x440d,0x4327,0x4fff},
|
||||
|
||||
/* Developer: Datam Polystar
|
||||
* Soshite Kono Uchuu ni Kirameku Kimi no Shi XXX (PS2) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x5f5d,0x552b,0x5507},
|
||||
|
||||
/* Developer: Sega
|
||||
* Sakura Taisen: Atsuki Chishio Ni (PS2) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x645d,0x6011,0x5c29},
|
||||
|
||||
/* Developer: Sega
|
||||
* Sakura Taisen 3 ~Paris wa Moeteiru ka~ (PS2) */
|
||||
/* confirmed unique with guessadx */
|
||||
{0x62ad,0x4b13,0x5957},
|
||||
|
||||
/* Developer: Jinx
|
||||
* Sotsugyou 2nd Generation (PS2)
|
||||
* First guess from guessadx, other was
|
||||
* {0x6307,0x509f,0x2ac5}
|
||||
*/
|
||||
{0x6305,0x509f,0x4c01},
|
||||
|
||||
/*
|
||||
* La Corda d'Oro (2005)(-)(Koei)[PSP]
|
||||
* confirmed unique with guessadx */
|
||||
{0x55b7,0x67e5,0x5387},
|
||||
|
||||
/*
|
||||
* Nanatsuiro * Drops Pure!! (2007)(Media Works)[PS2]
|
||||
* confirmed unique with guessadx */
|
||||
{0x6731,0x645d,0x566b},
|
||||
|
||||
/*
|
||||
* Shakugan no Shana (2006)(Vridge)(Media Works)[PS2]
|
||||
* confirmed unique with guessadx */
|
||||
{0x5fc5,0x63d9,0x599f},
|
||||
|
||||
/*
|
||||
* Uragiri wa Boku no Namae o Shitteiru (2010)(Kadokawa Shoten)[PS2]
|
||||
* confirmed unique with guessadx */
|
||||
{0x4c73,0x4d8d,0x5827},
|
||||
|
||||
/*
|
||||
* StormLover Kai!! (2012)(D3 Publisher)[PSP]
|
||||
* confirmed unique with guessadx */
|
||||
{0x5a11,0x67e5,0x6751},
|
||||
|
||||
/*
|
||||
* Sora no Otoshimono - DokiDoki Summer Vacation (2010)(Kadokawa Shoten)[PSP]
|
||||
* confirmed unique with guessadx */
|
||||
{0x5e75,0x4a89,0x4c61},
|
||||
|
||||
/*
|
||||
* Boku wa Koukuu Kanseikan - Airport Hero Naha (2006)(Sonic Powered)(Electronic Arts)[PSP]
|
||||
* confirmed unique with guessadx */
|
||||
{0x64ab,0x5297,0x632f},
|
||||
|
||||
/*
|
||||
* Lucky Star - Net Idol Meister (2009)(Kadokawa Shoten)[PSP]
|
||||
* confirmed unique with guessadx */
|
||||
{0x4d82,0x5243,0x685},
|
||||
|
||||
/*
|
||||
* Ishin Renka: Ryouma Gaiden (2010-11-25)(-)(D3 Publisher)[PSP]
|
||||
*/
|
||||
{0x54d1,0x526d,0x5e8b},
|
||||
|
||||
/*
|
||||
* Lucky Star - Ryouou Gakuen Outousai Portable (2010-12-22)(-)(Kadokawa Shoten)[PSP]
|
||||
*/
|
||||
{0x4d06,0x663b,0x7d09},
|
||||
|
||||
/*
|
||||
* Marriage Royale - Prism Story (2010-04-28)(-)(ASCII Media Works)[PSP]
|
||||
*/
|
||||
{0x40a9,0x46b1,0x62ad},
|
||||
|
||||
/*
|
||||
* Nogizaka Haruka no Himitsu - Doujinshi Hajime Mashita (2010-10-28)(-)(ASCII Media Works)[PSP]
|
||||
*/
|
||||
{0x4601,0x671f,0x0455},
|
||||
|
||||
/*
|
||||
* Slotter Mania P - Mach Go Go Go III (2011-01-06)(-)(Dorart)[PSP]
|
||||
*/
|
||||
{0x41ef,0x463d,0x5507},
|
||||
|
||||
/*
|
||||
* Nichijou - Uchuujin (2011-07-28)(-)(Kadokawa Shoten)[PSP]
|
||||
*/
|
||||
{0x4369,0x486d,0x5461},
|
||||
|
||||
/*
|
||||
* R-15 Portable (2011-10-27)(-)(Kadokawa Shoten)[PSP]
|
||||
*/
|
||||
{0x6809,0x5fd5,0x5bb1},
|
||||
|
||||
/*
|
||||
* Suzumiya Haruhi-chan no Mahjong (2011-07-07)(-)(Kadokawa Shoten)[PSP]
|
||||
*/
|
||||
{0x5c33,0x4133,0x4ce7},
|
||||
|
||||
// Storm Lover Natsu Koi!! (2011-08-04)(Vridge)(D3 Publisher)
|
||||
{0x4133,0x5a01,0x5723},
|
||||
|
||||
};
|
||||
|
||||
/* type 9 keys (may not be autodetected correctly) */
|
||||
static struct {
|
||||
uint16_t start,mult,add;
|
||||
} keys_9[] = {
|
||||
/* Phantasy Star Online 2
|
||||
* guessed with degod */
|
||||
{0x07d2,0x1ec5,0x0c7f},
|
||||
|
||||
/* Dragon Ball Z: Dokkan Battle
|
||||
* Verified by VGAudio
|
||||
* Key code: 416383518 */
|
||||
{0x0003,0x0d19,0x043b},
|
||||
|
||||
/* Kisou Ryouhei Gunhound EX (2013-01-31)(Dracue)[PSP]
|
||||
* Verified by VGAudio
|
||||
* Key code: 683461999 */
|
||||
{0x0005,0x0bcd,0x1add},
|
||||
|
||||
/* Raramagi [Android]
|
||||
* Verified by VGAudio
|
||||
* Key code: 12160794 */
|
||||
{0x0000,0x0b99,0x1e33},
|
||||
|
||||
/* Sonic runners [Android]
|
||||
* Verified by VGAudio
|
||||
* Key code: 19910623 */
|
||||
{0x0000,0x12fd,0x1fbd},
|
||||
|
||||
};
|
||||
|
||||
static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]);
|
||||
static const int keys_9_count = sizeof(keys_9)/sizeof(keys_9[0]);
|
||||
|
||||
/* return 0 if not found, 1 if found and set parameters */
|
||||
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add)
|
||||
|
@ -521,7 +258,7 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_
|
|||
}
|
||||
|
||||
|
||||
/* guess key from the tables above */
|
||||
/* guess key from the tables */
|
||||
startoff=read_16bitBE(2, file)+4;
|
||||
endoff=(read_32bitBE(12, file)+31)/32*18*read_8bit(7, file)+startoff;
|
||||
|
||||
|
@ -558,14 +295,13 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_
|
|||
|
||||
{
|
||||
/* try to guess key */
|
||||
#define MAX_FRAMES (INT_MAX/0x8000)
|
||||
struct { uint16_t start, mult, add; } *keys = NULL;
|
||||
const adxkey_info * keys = NULL;
|
||||
int keycount = 0, keymask = 0;
|
||||
int scales_to_do;
|
||||
int key_id;
|
||||
|
||||
/* allocate storage for scales */
|
||||
scales_to_do = (bruteframecount > MAX_FRAMES ? MAX_FRAMES : bruteframecount);
|
||||
scales_to_do = (bruteframecount > MAX_TEST_FRAMES ? MAX_TEST_FRAMES : bruteframecount);
|
||||
scales = malloc(scales_to_do*sizeof(uint16_t));
|
||||
if (!scales) {
|
||||
goto find_key_cleanup;
|
||||
|
@ -595,8 +331,8 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_
|
|||
|
||||
if (type == 8)
|
||||
{
|
||||
keys = &keys_8;
|
||||
keycount = keys_8_count;
|
||||
keys = adxkey8_list;
|
||||
keycount = adxkey8_list_count;
|
||||
keymask = 0x6000;
|
||||
}
|
||||
else if (type == 9)
|
||||
|
@ -605,8 +341,8 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_
|
|||
* but the maximum value assigned by the encoder is 0x1000.
|
||||
* This is written to the ADX file as 0xFFF, leaving the high bit
|
||||
* empty, which is used to validate a key */
|
||||
keys = &keys_9;
|
||||
keycount = keys_9_count;
|
||||
keys = adxkey9_list;
|
||||
keycount = adxkey9_list_count;
|
||||
keymask = 0x1000;
|
||||
}
|
||||
|
||||
|
@ -618,6 +354,23 @@ static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_
|
|||
uint16_t add = keys[key_id].add;
|
||||
int i;
|
||||
|
||||
#ifdef ADX_VERIFY_DERIVED_KEYS
|
||||
{
|
||||
uint16_t test_start, test_mult, test_add;
|
||||
if (type == 8 && keys[key_id].key8) {
|
||||
process_cri_key8(keys[key_id].key8, &test_start, &test_mult, &test_add);
|
||||
VGM_LOG("key8: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (\"%s\")\n",
|
||||
xor,mult,add, test_start,test_mult,test_add, xor==test_start && mult==test_mult && add==test_add ? "ok" : "ko", keys[key_id].key8);
|
||||
}
|
||||
else if (type == 9 && keys[key_id].key9) {
|
||||
process_cri_key9(keys[key_id].key9, &test_start, &test_mult, &test_add);
|
||||
VGM_LOG("key9: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (%"PRIu64")\n",
|
||||
xor,mult,add, test_start,test_mult,test_add, xor==test_start && mult==test_mult && add==test_add ? "ok" : "ko", keys[key_id].key9);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=0;i<bruteframe &&
|
||||
((prescales[i]&keymask)==(xor&keymask) ||
|
||||
prescales[i]==0);
|
||||
|
|
|
@ -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_*/
|
|
@ -8,7 +8,7 @@
|
|||
/* Included primarily for 3DO */
|
||||
|
||||
/* for reading integers inexplicably packed into 80 bit floats */
|
||||
uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) {
|
||||
static uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) {
|
||||
uint8_t buf[10];
|
||||
int32_t exponent;
|
||||
int32_t mantissa;
|
||||
|
@ -31,7 +31,7 @@ uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) {
|
|||
return mantissa*((buf[0]&0x80)?-1:1);
|
||||
}
|
||||
|
||||
uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset,
|
||||
static uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset,
|
||||
int marker_id) {
|
||||
uint16_t marker_count;
|
||||
int i;
|
||||
|
@ -173,7 +173,7 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
|
|||
interleave = 1;
|
||||
break;
|
||||
case 0x41445034: /* ADP4 */
|
||||
coding_type = coding_DVI_IMA;
|
||||
coding_type = coding_DVI_IMA_int;
|
||||
/* don't know how stereo DVI is laid out */
|
||||
if (channel_count != 1) break;
|
||||
break;
|
||||
|
|
|
@ -1,20 +1,7 @@
|
|||
#include "../vgmstream.h"
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
typedef struct _AIXSTREAMFILE
|
||||
{
|
||||
STREAMFILE sf;
|
||||
STREAMFILE *real_file;
|
||||
off_t start_physical_offset;
|
||||
off_t current_physical_offset;
|
||||
off_t current_logical_offset;
|
||||
off_t current_block_size;
|
||||
int stream_id;
|
||||
} AIXSTREAMFILE;
|
||||
|
||||
static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id);
|
||||
#include "aix_streamfile.h"
|
||||
|
||||
/* AIX - interleaved AAX, N segments per channels [SoulCalibur IV (PS3)] */
|
||||
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
|
||||
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
|
@ -61,7 +48,7 @@ VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
|
|||
goto fail;
|
||||
|
||||
sample_rate = read_32bitBE(stream_list_offset+8,streamFile);
|
||||
if (!check_sample_rate(sample_rate))
|
||||
if (sample_rate < 300 || sample_rate > 96000)
|
||||
goto fail;
|
||||
|
||||
samples_in_segment = calloc(segment_count,sizeof(int32_t));
|
||||
|
@ -228,190 +215,3 @@ fail:
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
|
||||
{
|
||||
size_t sz = 0;
|
||||
|
||||
/*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/
|
||||
while (length > 0)
|
||||
{
|
||||
int read_something = 0;
|
||||
|
||||
/* read the beginning of the requested block, if we can */
|
||||
if (offset >= streamfile->current_logical_offset)
|
||||
{
|
||||
off_t to_read;
|
||||
off_t length_available;
|
||||
|
||||
length_available =
|
||||
(streamfile->current_logical_offset+
|
||||
streamfile->current_block_size) -
|
||||
offset;
|
||||
|
||||
if (length < length_available)
|
||||
{
|
||||
to_read = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
to_read = length_available;
|
||||
}
|
||||
|
||||
if (to_read > 0)
|
||||
{
|
||||
size_t bytes_read;
|
||||
|
||||
bytes_read = read_streamfile(dest,
|
||||
streamfile->current_physical_offset+0x10+
|
||||
(offset-streamfile->current_logical_offset),
|
||||
to_read,streamfile->real_file);
|
||||
|
||||
sz += bytes_read;
|
||||
if (bytes_read != to_read)
|
||||
{
|
||||
/* an error which we will not attempt to handle here */
|
||||
return sz;
|
||||
}
|
||||
|
||||
read_something = 1;
|
||||
|
||||
dest += bytes_read;
|
||||
offset += bytes_read;
|
||||
length -= bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
if (!read_something)
|
||||
{
|
||||
/* couldn't read anything, must seek */
|
||||
int found_block = 0;
|
||||
|
||||
/* as we have no memory we must start seeking from the beginning */
|
||||
if (offset < streamfile->current_logical_offset)
|
||||
{
|
||||
streamfile->current_logical_offset = 0;
|
||||
streamfile->current_block_size = 0;
|
||||
streamfile->current_physical_offset =
|
||||
streamfile->start_physical_offset;
|
||||
}
|
||||
|
||||
/* seek ye forwards */
|
||||
while (!found_block) {
|
||||
/*printf("seek looks at %x\n",streamfile->current_physical_offset);*/
|
||||
switch (read_32bitBE(streamfile->current_physical_offset,
|
||||
streamfile->real_file))
|
||||
{
|
||||
case 0x41495850: /* AIXP */
|
||||
if (read_8bit(
|
||||
streamfile->current_physical_offset+8,
|
||||
streamfile->real_file) ==
|
||||
streamfile->stream_id)
|
||||
{
|
||||
streamfile->current_block_size =
|
||||
(uint16_t)read_16bitBE(
|
||||
streamfile->current_physical_offset+0x0a,
|
||||
streamfile->real_file);
|
||||
|
||||
if (offset >= streamfile->current_logical_offset+
|
||||
streamfile->current_block_size)
|
||||
{
|
||||
streamfile->current_logical_offset +=
|
||||
streamfile->current_block_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
found_block = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_block)
|
||||
{
|
||||
streamfile->current_physical_offset +=
|
||||
read_32bitBE(
|
||||
streamfile->current_physical_offset+0x04,
|
||||
streamfile->real_file
|
||||
) + 8;
|
||||
}
|
||||
|
||||
break;
|
||||
case 0x41495846: /* AIXF */
|
||||
/* shouldn't ever see this */
|
||||
case 0x41495845: /* AIXE */
|
||||
/* shouldn't have reached the end o' the line... */
|
||||
default:
|
||||
return sz;
|
||||
break;
|
||||
} /* end block/chunk type select */
|
||||
} /* end while !found_block */
|
||||
} /* end if !read_something */
|
||||
} /* end while length > 0 */
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void close_aix(AIXSTREAMFILE *streamfile)
|
||||
{
|
||||
free(streamfile);
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t get_size_aix(AIXSTREAMFILE *streamfile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t get_offset_aix(AIXSTREAMFILE *streamfile)
|
||||
{
|
||||
return streamfile->current_logical_offset;
|
||||
}
|
||||
|
||||
static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length)
|
||||
{
|
||||
strncpy(buffer,"ARBITRARY.ADX",length);
|
||||
buffer[length-1]='\0';
|
||||
}
|
||||
|
||||
static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
|
||||
{
|
||||
AIXSTREAMFILE *newfile;
|
||||
if (strcmp(filename,"ARBITRARY.ADX"))
|
||||
return NULL;
|
||||
|
||||
newfile = malloc(sizeof(AIXSTREAMFILE));
|
||||
if (!newfile)
|
||||
return NULL;
|
||||
memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE));
|
||||
return &newfile->sf;
|
||||
}
|
||||
|
||||
static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id)
|
||||
{
|
||||
AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE));
|
||||
|
||||
if (!streamfile)
|
||||
return NULL;
|
||||
|
||||
/* success, set our pointers */
|
||||
|
||||
streamfile->sf.read = (void*)read_aix;
|
||||
streamfile->sf.get_size = (void*)get_size_aix;
|
||||
streamfile->sf.get_offset = (void*)get_offset_aix;
|
||||
streamfile->sf.get_name = (void*)get_name_aix;
|
||||
streamfile->sf.get_realname = (void*)get_name_aix;
|
||||
streamfile->sf.open = (void*)open_aix_impl;
|
||||
streamfile->sf.close = (void*)close_aix;
|
||||
#ifdef PROFILE_STREAMFILE
|
||||
streamfile->sf.get_bytes_read = NULL;
|
||||
streamfile->sf.get_error_count = NULL;
|
||||
#endif
|
||||
|
||||
streamfile->real_file = file;
|
||||
streamfile->current_physical_offset =
|
||||
streamfile->start_physical_offset = start_offset;
|
||||
streamfile->current_logical_offset = 0;
|
||||
streamfile->current_block_size = 0;
|
||||
streamfile->stream_id = stream_id;
|
||||
|
||||
return &streamfile->sf;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_ */
|
|
@ -223,11 +223,12 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) {
|
|||
sample_rate = (uint16_t)read_16bit(offset + 0x0c + 0x10*ch + 0x0a,streamFile);
|
||||
codec = read_8bit(offset + 0x0c + 0x10*ch + 0x0c, streamFile);
|
||||
|
||||
/* validate as all channels should repeat this */
|
||||
if ((awc->num_samples && awc->num_samples != num_samples) ||
|
||||
/* validate as all channels should repeat this (when channels is even and > 2 seems
|
||||
* it's stereo pairs, and num_samples can vary slightly but no matter) */
|
||||
if ((awc->num_samples && !(awc->num_samples >= num_samples - 10 && awc->num_samples <= num_samples + 10)) ||
|
||||
(awc->sample_rate && awc->sample_rate != sample_rate) ||
|
||||
(awc->codec && awc->codec != codec)) {
|
||||
VGM_LOG("AWC: found header diffs between channels\n"); /* can rarely happen in stereo pairs */
|
||||
VGM_LOG("AWC: found header diffs between channels\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -3,166 +3,166 @@
|
|||
|
||||
/* BCSTM - Nintendo 3DS format */
|
||||
VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
coding_t coding_type;
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
coding_t coding_type;
|
||||
|
||||
off_t info_offset = 0, seek_offset = 0, data_offset = 0;
|
||||
uint16_t temp_id;
|
||||
int codec_number;
|
||||
int channel_count, loop_flag;
|
||||
int i, ima = 0;
|
||||
off_t start_offset;
|
||||
int section_count;
|
||||
off_t info_offset = 0, seek_offset = 0, data_offset = 0;
|
||||
uint16_t temp_id;
|
||||
int codec_number;
|
||||
int channel_count, loop_flag;
|
||||
int i, ima = 0;
|
||||
off_t start_offset;
|
||||
int section_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* check extension, case insensitive */
|
||||
if ( !check_extensions(streamFile,"bcstm") )
|
||||
goto fail;
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */
|
||||
goto fail;
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */
|
||||
goto fail;
|
||||
|
||||
if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF)
|
||||
goto fail;
|
||||
|
||||
section_count = read_16bitLE(0x10, streamFile);
|
||||
for (i = 0; i < section_count; i++) {
|
||||
temp_id = read_16bitLE(0x14 + i * 0xc, streamFile);
|
||||
switch(temp_id) {
|
||||
case 0x4000:
|
||||
info_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
|
||||
/* size_t info_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4001:
|
||||
seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
|
||||
/* size_t seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4002:
|
||||
data_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
|
||||
/* size_t data_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4003:
|
||||
/* off_t regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
|
||||
/* size_t regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4004:
|
||||
/* off_t pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
|
||||
/* size_t pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF)
|
||||
goto fail;
|
||||
|
||||
section_count = read_16bitLE(0x10, streamFile);
|
||||
for (i = 0; i < section_count; i++) {
|
||||
temp_id = read_16bitLE(0x14 + i * 0xc, streamFile);
|
||||
switch(temp_id) {
|
||||
case 0x4000:
|
||||
info_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
|
||||
/* size_t info_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4001:
|
||||
seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
|
||||
/* size_t seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4002:
|
||||
data_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
|
||||
/* size_t data_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4003:
|
||||
/* off_t regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
|
||||
/* size_t regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
case 0x4004:
|
||||
/* off_t pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
|
||||
/* size_t pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (info_offset == 0) goto fail;
|
||||
if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */
|
||||
goto fail;
|
||||
|
||||
|
||||
/* check type details */
|
||||
codec_number = read_8bit(info_offset + 0x20, streamFile);
|
||||
loop_flag = read_8bit(info_offset + 0x21, streamFile);
|
||||
channel_count = read_8bit(info_offset + 0x22, streamFile);
|
||||
|
||||
switch (codec_number) {
|
||||
case 0:
|
||||
coding_type = coding_PCM8;
|
||||
break;
|
||||
case 1:
|
||||
coding_type = coding_PCM16LE;
|
||||
break;
|
||||
case 2:
|
||||
if (seek_offset == 0) goto fail;
|
||||
if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */
|
||||
ima = 1;
|
||||
coding_type = coding_IMA_int;
|
||||
}
|
||||
else
|
||||
coding_type = coding_NGC_DSP;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
/* check type details */
|
||||
codec_number = read_8bit(info_offset + 0x20, streamFile);
|
||||
loop_flag = read_8bit(info_offset + 0x21, streamFile);
|
||||
channel_count = read_8bit(info_offset + 0x22, streamFile);
|
||||
|
||||
if (channel_count < 1) goto fail;
|
||||
switch (codec_number) {
|
||||
case 0:
|
||||
coding_type = coding_PCM8;
|
||||
break;
|
||||
case 1:
|
||||
coding_type = coding_PCM16LE;
|
||||
break;
|
||||
case 2:
|
||||
if (seek_offset == 0) goto fail;
|
||||
if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */
|
||||
ima = 1;
|
||||
coding_type = coding_3DS_IMA;
|
||||
}
|
||||
else
|
||||
coding_type = coding_NGC_DSP;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
if (channel_count < 1) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile);
|
||||
vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile);
|
||||
/* channels and loop flag are set by allocate_vgmstream */
|
||||
if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting
|
||||
{
|
||||
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
|
||||
if (vgmstream->loop_start_sample > 10000)
|
||||
{
|
||||
vgmstream->loop_start_sample -= 5000;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples - 5000;
|
||||
}
|
||||
else
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
else
|
||||
{
|
||||
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
if (channel_count == 1)
|
||||
vgmstream->layout_type = layout_none;
|
||||
else
|
||||
{
|
||||
if (ima)
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
else
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
}
|
||||
vgmstream->meta_type = meta_CSTM;
|
||||
|
||||
if (ima)
|
||||
vgmstream->interleave_block_size = 0x200;
|
||||
else {
|
||||
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile);
|
||||
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
off_t coef_offset;
|
||||
off_t tempoffset = info_offset;
|
||||
int foundcoef = 0;
|
||||
int i, j;
|
||||
int coef_spacing = 0x2E;
|
||||
|
||||
while (!(foundcoef))
|
||||
{
|
||||
if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102)
|
||||
{
|
||||
coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset;
|
||||
foundcoef++;
|
||||
break;
|
||||
}
|
||||
tempoffset++;
|
||||
}
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile);
|
||||
vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile);
|
||||
/* channels and loop flag are set by allocate_vgmstream */
|
||||
if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting
|
||||
{
|
||||
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
|
||||
if (vgmstream->loop_start_sample > 10000)
|
||||
{
|
||||
vgmstream->loop_start_sample -= 5000;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples - 5000;
|
||||
}
|
||||
else
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
else
|
||||
{
|
||||
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
if (channel_count == 1)
|
||||
vgmstream->layout_type = layout_none;
|
||||
else
|
||||
{
|
||||
if (ima)
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
else
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
}
|
||||
vgmstream->meta_type = meta_CSTM;
|
||||
|
||||
if (ima)
|
||||
vgmstream->interleave_block_size = 0x200;
|
||||
else {
|
||||
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile);
|
||||
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
off_t coef_offset;
|
||||
off_t tempoffset = info_offset;
|
||||
int foundcoef = 0;
|
||||
int i, j;
|
||||
int coef_spacing = 0x2E;
|
||||
|
||||
while (!(foundcoef))
|
||||
{
|
||||
if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102)
|
||||
{
|
||||
coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset;
|
||||
foundcoef++;
|
||||
break;
|
||||
}
|
||||
tempoffset++;
|
||||
}
|
||||
|
||||
for (j = 0; 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 */
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* BGW - from Final Fantasy XI (PC) music files
|
||||
* Some info from POLUtils */
|
||||
/* BGW - from Final Fantasy XI (PC) music files */
|
||||
VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
uint32_t codec, filesize, blocksize, sample_rate;
|
||||
uint32_t codec, file_size, block_size, sample_rate, block_align;
|
||||
int32_t loop_start;
|
||||
uint8_t block_align;
|
||||
off_t start_offset;
|
||||
|
||||
int channel_count, loop_flag = 0;
|
||||
|
@ -22,11 +21,11 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
|
|||
goto fail;
|
||||
|
||||
codec = read_32bitLE(0x0c,streamFile);
|
||||
filesize = read_32bitLE(0x10,streamFile);
|
||||
file_size = read_32bitLE(0x10,streamFile);
|
||||
/*file_id = read_32bitLE(0x14,streamFile);*/
|
||||
blocksize = read_32bitLE(0x18,streamFile);
|
||||
block_size = read_32bitLE(0x18,streamFile);
|
||||
loop_start = read_32bitLE(0x1c,streamFile);
|
||||
sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0xFFFFFFFF; /* bizarrely obfuscated sample rate */
|
||||
sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
|
||||
start_offset = read_32bitLE(0x28,streamFile);
|
||||
/*0x2c: unk (vol?) */
|
||||
/*0x2d: unk (0x10?) */
|
||||
|
@ -35,7 +34,7 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
|
|||
|
||||
|
||||
/* check file size with header value */
|
||||
if (filesize != get_streamfile_size(streamFile))
|
||||
if (file_size != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
loop_flag = (loop_start > 0);
|
||||
|
@ -54,15 +53,46 @@ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
|
|||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */
|
||||
|
||||
vgmstream->num_samples = blocksize * block_align;
|
||||
vgmstream->num_samples = block_size * block_align;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = (loop_start-1) * block_align;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3: /* ATRAC3 (encrypted) */
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 3: { /* ATRAC3 (encrypted) */
|
||||
uint8_t buf[0x100];
|
||||
int bytes, joint_stereo, skip_samples;
|
||||
ffmpeg_custom_config cfg;
|
||||
|
||||
vgmstream->num_samples = block_size; /* atrac3_bytes_to_samples gives the same value */
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
block_align = 0xC0 * vgmstream->channels; /* 0x00 in header */
|
||||
joint_stereo = 0;
|
||||
skip_samples = 0;
|
||||
|
||||
bytes = ffmpeg_make_riff_atrac3(buf, 0x100, vgmstream->num_samples, file_size - start_offset, vgmstream->channels, vgmstream->sample_rate, block_align, joint_stereo, skip_samples);
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
memset(&cfg, 0, sizeof(ffmpeg_custom_config));
|
||||
cfg.type = FFMPEG_BGW_ATRAC3;
|
||||
cfg.channels = vgmstream->channels;
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,file_size - start_offset, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
@ -82,9 +112,8 @@ fail:
|
|||
/* SPW (SEWave) - from PlayOnline viewer for Final Fantasy XI (PC) */
|
||||
VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
uint32_t codec, filesize, blocksize, sample_rate;
|
||||
uint32_t codec, file_size, block_size, sample_rate, block_align;
|
||||
int32_t loop_start;
|
||||
uint8_t block_align;
|
||||
off_t start_offset;
|
||||
|
||||
int channel_count, loop_flag = 0;
|
||||
|
@ -102,12 +131,12 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
|
|||
if (read_32bitLE(0x8,streamFile) != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
filesize = read_32bitLE(0x08,streamFile);
|
||||
file_size = read_32bitLE(0x08,streamFile);
|
||||
codec = read_32bitLE(0x0c,streamFile);
|
||||
/*file_id = read_32bitLE(0x10,streamFile);*/
|
||||
blocksize = read_32bitLE(0x14,streamFile);
|
||||
block_size = read_32bitLE(0x14,streamFile);
|
||||
loop_start = read_32bitLE(0x18,streamFile);
|
||||
sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0xFFFFFFFF; /* bizarrely obfuscated sample rate */
|
||||
sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0x7FFFFFFF; /* bizarrely obfuscated sample rate */
|
||||
start_offset = read_32bitLE(0x24,streamFile);
|
||||
/*0x2c: unk (0x00?) */
|
||||
/*0x2d: unk (0x00/01?) */
|
||||
|
@ -116,7 +145,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
|
|||
/*0x2c: unk (0x01 when PCM, 0x10 when VAG?) */
|
||||
|
||||
/* check file size with header value */
|
||||
if (filesize != get_streamfile_size(streamFile))
|
||||
if (file_size != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
loop_flag = (loop_start > 0);
|
||||
|
@ -135,7 +164,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
|
|||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */
|
||||
|
||||
vgmstream->num_samples = blocksize * block_align;
|
||||
vgmstream->num_samples = block_size * block_align;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = (loop_start-1) * block_align;;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
@ -148,7 +177,7 @@ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
|
|||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
|
||||
vgmstream->num_samples = blocksize;
|
||||
vgmstream->num_samples = block_size;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = (loop_start-1);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
|
|
@ -1,243 +1,96 @@
|
|||
#include "meta.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util.h"
|
||||
#include "../vgmstream.h"
|
||||
|
||||
/* Namco Bandai's Bandai Namco Sound Format/File (BNSF) */
|
||||
/* similar to RIFX */
|
||||
|
||||
/* BNSF - Namco Bandai's Bandai Namco Sound Format/File */
|
||||
VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset = 0, first_offset = 0x0C;
|
||||
int loop_flag = 0, channel_count = 0;
|
||||
int sample_rate, num_samples, loop_start = 0, loop_end = 0, block_size;
|
||||
uint32_t codec, subcodec = 0;
|
||||
size_t sdat_size;
|
||||
off_t loop_chunk = 0, sfmt_chunk, sdat_chunk;
|
||||
|
||||
off_t file_size = -1;
|
||||
uint32_t riff_size;
|
||||
uint32_t bnsf_form;
|
||||
enum {
|
||||
form_IS14 = UINT32_C(0x49533134), /* IS14 */
|
||||
form_IS22 = UINT32_C(0x49533232), /* IS22 */
|
||||
};
|
||||
|
||||
int channel_count = 0;
|
||||
int sample_count = 0;
|
||||
int sample_rate = 0;
|
||||
int coding_type = -1;
|
||||
off_t start_offset = -1;
|
||||
|
||||
int loop_flag = 0;
|
||||
off_t loop_start = -1;
|
||||
off_t loop_end = -1;
|
||||
uint32_t data_size = 0;
|
||||
uint32_t block_size = 0;
|
||||
uint32_t block_samples = 0;
|
||||
|
||||
int FormatChunkFound = 0;
|
||||
int DataChunkFound = 0;
|
||||
int RiffSizeExtra = 8;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("bnsf",filename_extension(filename)))
|
||||
{
|
||||
if (!check_extensions(streamFile,"bnsf"))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(0,streamFile)!=0x424E5346) /* BNSF */
|
||||
if (read_32bitBE(0,streamFile) != 0x424E5346) /* "BNSF" */
|
||||
goto fail;
|
||||
|
||||
/* check form */
|
||||
bnsf_form = read_32bitBE(8,streamFile);
|
||||
switch (bnsf_form)
|
||||
{
|
||||
#ifdef VGM_USE_G7221
|
||||
case form_IS14:
|
||||
break;
|
||||
#endif
|
||||
#ifdef VGM_USE_G719
|
||||
case form_IS22:
|
||||
RiffSizeExtra = 0;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
goto fail;
|
||||
codec = read_32bitBE(0x08,streamFile);
|
||||
|
||||
/* check RIFF size (for siren22 it's full size) */
|
||||
if (read_32bitBE(0x04,streamFile) + (codec == 0x49533232 ? 0 : 8) != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
if (!find_chunk_be(streamFile, 0x73666d74,first_offset,0, &sfmt_chunk,NULL)) /* "sfmt" */
|
||||
goto fail;
|
||||
if (!find_chunk_be(streamFile, 0x73646174,first_offset,0, &sdat_chunk,&sdat_size)) /* "sdat" */
|
||||
goto fail;
|
||||
if ( find_chunk_be(streamFile, 0x6C6F6F70,first_offset,0, &loop_chunk,NULL)) { /* "loop" */
|
||||
loop_flag = 1;
|
||||
loop_start = read_32bitBE(loop_chunk+0x00, streamFile);
|
||||
loop_end = read_32bitBE(loop_chunk+0x04,streamFile);
|
||||
}
|
||||
|
||||
riff_size = read_32bitBE(4,streamFile);
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
subcodec = read_16bitBE(sfmt_chunk+0x00,streamFile);
|
||||
channel_count = read_16bitBE(sfmt_chunk+0x02,streamFile);
|
||||
sample_rate = read_32bitBE(sfmt_chunk+0x04,streamFile);
|
||||
num_samples = read_32bitBE(sfmt_chunk+0x08,streamFile);
|
||||
/* 0x0c: some kind of sample count (skip?), can be 0 when no loops */
|
||||
block_size = read_16bitBE(sfmt_chunk+0x10,streamFile);
|
||||
//block_samples = read_16bitBE(sfmt_chunk+0x12,streamFile);
|
||||
/* max_samples = sdat_size/block_size*block_samples //num_samples is smaller */
|
||||
|
||||
/* check for tructated RIFF */
|
||||
if (file_size < riff_size+RiffSizeExtra) goto fail;
|
||||
start_offset = sdat_chunk;
|
||||
|
||||
/* read through chunks to verify format and find metadata */
|
||||
{
|
||||
off_t current_chunk = 0xc; /* start with first chunk */
|
||||
|
||||
while (current_chunk < file_size && current_chunk < riff_size+8) {
|
||||
uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
|
||||
off_t chunk_size = read_32bitBE(current_chunk+4,streamFile);
|
||||
|
||||
if (current_chunk+8+chunk_size > file_size) goto fail;
|
||||
|
||||
switch(chunk_type) {
|
||||
case 0x73666d74: /* "sfmt" */
|
||||
/* only one per file */
|
||||
if (FormatChunkFound) goto fail;
|
||||
FormatChunkFound = 1;
|
||||
|
||||
sample_rate = read_32bitBE(current_chunk+0x0c,streamFile);
|
||||
channel_count = read_16bitBE(current_chunk+0x0a,streamFile);
|
||||
// read_32bitBE(current_chunk+0x10,streamFile); // ?
|
||||
// read_32bitBE(current_chunk+0x14,streamFile); // ?
|
||||
block_size = read_16bitBE(current_chunk+0x18,streamFile);
|
||||
block_samples = read_16bitBE(current_chunk+0x1a,streamFile);
|
||||
|
||||
/* I assume this is still the codec id, but as the codec is
|
||||
specified by the BNSF "form" I've only seen this zero */
|
||||
switch ((uint16_t)read_16bitBE(current_chunk+0x8,streamFile)) {
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case 0x73646174: /* sdat */
|
||||
/* at most one per file */
|
||||
if (DataChunkFound) goto fail;
|
||||
DataChunkFound = 1;
|
||||
|
||||
start_offset = current_chunk + 8;
|
||||
data_size = chunk_size;
|
||||
break;
|
||||
case 0x6C6F6F70: /* loop */
|
||||
loop_flag = 1;
|
||||
loop_start =
|
||||
read_32bitBE(current_chunk+8, streamFile);
|
||||
loop_end =
|
||||
read_32bitBE(current_chunk+0xc,streamFile);
|
||||
break;
|
||||
default:
|
||||
/* ignorance is bliss */
|
||||
break;
|
||||
}
|
||||
|
||||
current_chunk += 8+chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FormatChunkFound || !DataChunkFound) goto fail;
|
||||
|
||||
switch (bnsf_form) {
|
||||
#ifdef VGM_USE_G7221
|
||||
case form_IS14:
|
||||
coding_type = coding_G7221C;
|
||||
sample_count = data_size/block_size*block_samples;
|
||||
|
||||
break;
|
||||
#endif
|
||||
#ifdef VGM_USE_G719
|
||||
case form_IS22:
|
||||
coding_type = coding_G719;
|
||||
sample_count = data_size/block_size*block_samples;
|
||||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = sample_count;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
vgmstream->meta_type = meta_BNSF;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = block_size/channel_count;
|
||||
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
}
|
||||
vgmstream->meta_type = meta_BNSF;
|
||||
/* some IS14 voice files have 0x02 (Tales of Zestiria, The Idolm@ster 2); data looks normal and silent
|
||||
* frames decode ok but rest fails, must be some subtle decoding variation (not encryption) */
|
||||
if (subcodec != 0)
|
||||
goto fail;
|
||||
|
||||
switch (codec) {
|
||||
#ifdef VGM_USE_G7221
|
||||
if (coding_G7221C == coding_type)
|
||||
{
|
||||
int i;
|
||||
g7221_codec_data *data;
|
||||
case 0x49533134: /* "IS14" */
|
||||
vgmstream->coding_type = coding_G7221C;
|
||||
vgmstream->codec_data = init_g7221(vgmstream->channels, vgmstream->interleave_block_size);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
||||
/* one data structure per channel */
|
||||
data = malloc(sizeof(g7221_codec_data) * channel_count);
|
||||
if (!data)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
memset(data,0,sizeof(g7221_codec_data) * channel_count);
|
||||
vgmstream->codec_data = data;
|
||||
|
||||
for (i = 0; i < channel_count; i++)
|
||||
{
|
||||
/* Siren 14 == 14khz bandwidth */
|
||||
data[i].handle = g7221_init(vgmstream->interleave_block_size, 14000);
|
||||
if (!data[i].handle)
|
||||
{
|
||||
goto fail; /* close_vgmstream is able to clean up */
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_G719
|
||||
if (coding_G719 == coding_type)
|
||||
{
|
||||
int i;
|
||||
g719_codec_data *data;
|
||||
|
||||
/* one data structure per channel */
|
||||
data = malloc(sizeof(g719_codec_data) * channel_count);
|
||||
if (!data)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
memset(data,0,sizeof(g719_codec_data) * channel_count);
|
||||
vgmstream->codec_data = data;
|
||||
|
||||
for (i = 0; i < channel_count; i++)
|
||||
{
|
||||
/* Siren 22 == 22khz bandwidth */
|
||||
data[i].handle = g719_init(vgmstream->interleave_block_size);
|
||||
if (!data[i].handle)
|
||||
{
|
||||
goto fail; /* close_vgmstream is able to clean up */
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0x49533232: /* "IS22" */
|
||||
vgmstream->coding_type = coding_G719;
|
||||
vgmstream->codec_data = init_g719(vgmstream->channels, vgmstream->interleave_block_size);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* open the file, set up each channel */
|
||||
{
|
||||
int i;
|
||||
|
||||
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
|
||||
STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[0].streamfile) goto fail;
|
||||
|
||||
for (i=0;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;
|
||||
}
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,40 +1,35 @@
|
|||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* IDVI (Eldorado Gate Volume 1-7) */
|
||||
/* IDVI - from Capcom's Eldorado Gate Volume 1-7 (DC) */
|
||||
VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("idvi",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x49445649) /* "IDVI." */
|
||||
/* check extension (.dvi: original, .idvi: renamed to header id) */
|
||||
if ( !check_extensions(streamFile,"dvi,idvi") )
|
||||
goto fail;
|
||||
|
||||
loop_flag = read_32bitLE(0x0C,streamFile);
|
||||
channel_count = read_32bitLE(0x04,streamFile);
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x49445649) /* "IDVI" */
|
||||
goto fail;
|
||||
|
||||
loop_flag = (read_32bitLE(0x0C,streamFile) != 0);
|
||||
channel_count = read_32bitLE(0x04,streamFile); /* always 2? */
|
||||
start_offset = 0x800;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->channels = channel_count;
|
||||
start_offset = 0x800;
|
||||
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
|
||||
vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count);
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->loop_end_sample = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count);
|
||||
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset);
|
||||
}
|
||||
vgmstream->meta_type = meta_DC_IDVI;
|
||||
|
||||
/* Calculating the short block... */
|
||||
|
@ -47,24 +42,10 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
|
|||
}
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
|
|
|
@ -1,65 +1,42 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
VGMSTREAM * init_vgmstream_kcey(STREAMFILE *streamFile) {
|
||||
/* DVI - from Konami KCE Yokohama DC games (Pop'n Music series) */
|
||||
VGMSTREAM * init_vgmstream_dc_kcey(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
int loop_flag = 0;
|
||||
int channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("kcey",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4B434559) /* "DVI." */
|
||||
/* check extension (.pcm: original, .kcey: renamed to header id) */
|
||||
if ( !check_extensions(streamFile,"pcm,kcey") )
|
||||
goto fail;
|
||||
|
||||
loop_flag = (read_32bitBE(0x14,streamFile)!=0xFFFFFFFF);
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4B434559) /* "KCEY" (also "COMP") */
|
||||
goto fail;
|
||||
|
||||
start_offset = read_32bitBE(0x10,streamFile);
|
||||
loop_flag = (read_32bitBE(0x14,streamFile) != 0xFFFFFFFF);
|
||||
channel_count = read_32bitBE(0x08,streamFile);
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->channels = channel_count;
|
||||
start_offset = read_32bitBE(0x10,streamFile);
|
||||
vgmstream->sample_rate = 37800;
|
||||
vgmstream->coding_type = coding_EACS_IMA;
|
||||
|
||||
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
|
||||
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
|
||||
}
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
|
||||
|
||||
vgmstream->coding_type = coding_DVI_IMA; /* stereo/mono, high nibble first */
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_KCEY;
|
||||
vgmstream->get_high_nibble=1;
|
||||
vgmstream->meta_type = meta_DC_KCEY;
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;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;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
#include "meta.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* Gurumin .de2 */
|
||||
/* A ways into the file we have a fake RIFF header wrapping MS ADPCM */
|
||||
|
||||
VGMSTREAM * init_vgmstream_de2(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
off_t riff_off;
|
||||
int channel_count;
|
||||
int sample_count;
|
||||
int sample_rate;
|
||||
off_t start_offset;
|
||||
|
||||
int loop_flag = 0;
|
||||
uint32_t data_size;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("de2",filename_extension(filename))) goto fail;
|
||||
|
||||
/* still not sure what this is for, but consistently 0xb */
|
||||
if (read_32bitLE(0x04,streamFile)!=0xb) goto fail;
|
||||
|
||||
/* legitimate! really! */
|
||||
riff_off = 0x10 +
|
||||
(read_32bitLE(0x0c,streamFile) ^ read_32bitLE(0x04,streamFile));
|
||||
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(riff_off+0,streamFile)!=0x52494646) /* "RIFF" */
|
||||
goto fail;
|
||||
/* check for WAVE form */
|
||||
if ((uint32_t)read_32bitBE(riff_off+8,streamFile)!=0x57415645) /* "WAVE" */
|
||||
goto fail;
|
||||
/* check for "fmt " */
|
||||
if ((uint32_t)read_32bitBE(riff_off+12,streamFile)!=0x666d7420) /* "fmt " */
|
||||
goto fail;
|
||||
/* check for "data" */
|
||||
if ((uint32_t)read_32bitBE(riff_off+0x24,streamFile)!=0x64617461) /* "data" */
|
||||
goto fail;
|
||||
/* check for bad fmt chunk size */
|
||||
if (read_32bitLE(riff_off+0x10,streamFile)!=0x12) goto fail;
|
||||
|
||||
sample_rate = read_32bitLE(riff_off+0x18,streamFile);
|
||||
|
||||
channel_count = read_16bitLE(riff_off+0x16,streamFile);
|
||||
if (channel_count != 2) goto fail;
|
||||
|
||||
/* PCM */
|
||||
if (read_16bitLE(riff_off+0x14,streamFile) != 1) goto fail;
|
||||
|
||||
/* 16-bit */
|
||||
if (read_16bitLE(riff_off+0x20,streamFile) != 4 ||
|
||||
read_16bitLE(riff_off+0x22,streamFile) != 16) goto fail;
|
||||
|
||||
start_offset = riff_off + 0x2c;
|
||||
data_size = read_32bitLE(riff_off+0x28,streamFile);
|
||||
|
||||
sample_count = data_size/2/channel_count;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = sample_count;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_de2_blocked;
|
||||
vgmstream->interleave_block_size = 0x800;
|
||||
|
||||
vgmstream->meta_type = meta_DE2;
|
||||
|
||||
/* open the file, set up each channel */
|
||||
{
|
||||
int i;
|
||||
|
||||
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
|
||||
STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[0].streamfile) goto fail;
|
||||
|
||||
for (i=0;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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -140,7 +140,7 @@ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) {
|
|||
goto fail;
|
||||
|
||||
/* use header size as endianness flag */
|
||||
if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x00F00000) {
|
||||
if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x000F0000) { /* todo not very accurate */
|
||||
read_32bit = read_32bitBE;
|
||||
read_16bit = read_16bitBE;
|
||||
} else {
|
||||
|
@ -250,7 +250,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
|
|||
}
|
||||
}
|
||||
else {
|
||||
vgmstream->layout_type = layout_ea_blocked;
|
||||
vgmstream->layout_type = layout_blocked_ea_schl;
|
||||
}
|
||||
|
||||
if (is_bnk)
|
||||
|
@ -311,14 +311,12 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
|
|||
#ifdef VGM_USE_MPEG
|
||||
case EA_CODEC2_LAYER2: /* MPEG Layer II, aka MP2 */
|
||||
case EA_CODEC2_LAYER3: { /* MPEG Layer III, aka MP3 */
|
||||
mpeg_custom_config cfg;
|
||||
mpeg_custom_config cfg = {0};
|
||||
off_t mpeg_start_offset = is_bnk ?
|
||||
start_offset :
|
||||
get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea);
|
||||
if (!mpeg_start_offset) goto fail;
|
||||
|
||||
memset(&cfg, 0, sizeof(mpeg_custom_config));
|
||||
|
||||
/* layout is still blocks, but should work fine with the custom mpeg decoder */
|
||||
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, mpeg_start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_EA, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
@ -326,14 +324,12 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
|
|||
}
|
||||
|
||||
case EA_CODEC2_EALAYER3: { /* MP3 variant */
|
||||
mpeg_custom_config cfg;
|
||||
mpeg_custom_config cfg = {0};
|
||||
off_t mpeg_start_offset = is_bnk ?
|
||||
start_offset :
|
||||
get_ea_stream_mpeg_start_offset(streamFile, start_offset, ea);
|
||||
if (!mpeg_start_offset) goto fail;
|
||||
|
||||
memset(&cfg, 0, sizeof(mpeg_custom_config));
|
||||
|
||||
/* layout is still blocks, but should work fine with the custom mpeg decoder */
|
||||
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, mpeg_start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_EAL31, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
@ -343,6 +339,12 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
|
|||
|
||||
case EA_CODEC2_MT10: /* MicroTalk (10:1 compression) */
|
||||
case EA_CODEC2_MT5: /* MicroTalk (5:1 compression) */
|
||||
vgmstream->coding_type = coding_EA_MT;
|
||||
VGM_LOG("mt: codec=%x, cv=%x, v=%x\n", ea->codec2, ea->codec_version, ea->version);
|
||||
vgmstream->codec_data = init_ea_mt(vgmstream->channels, ea->version == EA_VERSION_V3);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
break;
|
||||
|
||||
case EA_CODEC2_ATRAC3PLUS: /* regular ATRAC3plus chunked in SCxx blocks, including RIFF header */
|
||||
default:
|
||||
VGM_LOG("EA SCHl: unknown codec2 0x%02x for platform 0x%02x\n", ea->codec2, ea->platform);
|
||||
|
@ -401,19 +403,10 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* reset channel sub offset for codecs using it */
|
||||
if (vgmstream->coding_type == coding_EA_XA
|
||||
|| vgmstream->coding_type == coding_EA_XA_int
|
||||
|| vgmstream->coding_type == coding_EA_XA_V2) {
|
||||
for(i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].channel_start_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* setup first block to update offsets */
|
||||
ea_schl_block_update(start_offset,vgmstream);
|
||||
block_update_ea_schl(start_offset,vgmstream);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
|
|||
|
||||
vgmstream->meta_type = meta_EA_SCHL_fixed;
|
||||
|
||||
vgmstream->layout_type = layout_ea_blocked;
|
||||
vgmstream->layout_type = layout_blocked_ea_schl;
|
||||
|
||||
switch (ea.codec) {
|
||||
case EA_CODEC_PCM:
|
||||
|
@ -66,7 +66,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
|
|||
break;
|
||||
|
||||
case EA_CODEC_IMA:
|
||||
vgmstream->coding_type = coding_EACS_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA; /* stereo/mono, high nibble first */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -80,7 +80,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
|
|||
goto fail;
|
||||
|
||||
/* setup first block to update offsets */
|
||||
ea_schl_block_update(start_offset,vgmstream);
|
||||
block_update_ea_schl(start_offset,vgmstream);
|
||||
|
||||
|
||||
return vgmstream;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -254,7 +254,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
|
|||
|
||||
/* sometimes there is garbage at the end or missing bytes due to improper demuxing */
|
||||
VGM_ASSERT(fsbh.hdrsize + fsbh.shdrsize + fsbh.datasize != streamFile->get_size(streamFile) - offset,
|
||||
"FSB wrong head/datasize found\n");
|
||||
"FSB wrong head/datasize found (expected 0x%x vs 0x%lx)\n",
|
||||
fsbh.hdrsize + fsbh.shdrsize + fsbh.datasize, streamFile->get_size(streamFile) - offset);
|
||||
|
||||
/* Loops unless disabled. FMOD default seems full loops (0/num_samples-1) without flags, for repeating tracks
|
||||
* that should loop and jingles/sfx that shouldn't. We'll try to disable looping is it looks jingly enough. */
|
||||
|
@ -352,8 +353,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
|
|||
}
|
||||
else if (fsbh.mode & FSOUND_GCADPCM) {
|
||||
/* FSB3: ?; FSB4: de Blob (Wii), Night at the Museum, M. Night Shyamalan Avatar: The Last Airbender */
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave_byte;
|
||||
vgmstream->coding_type = coding_NGC_DSP_subint;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = 0x2;
|
||||
dsp_read_coefs_be(vgmstream, streamFile, custom_data_offset, 0x2e);
|
||||
}
|
||||
|
@ -379,6 +380,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
|
|||
|
||||
/* full channel interleave, used in short streams (ex. de Blob Wii SFXs) */
|
||||
if (fsbh.numchannels > 1 && (fsbh.flags & FMOD_FSB_SOURCE_NOTINTERLEAVED)) {
|
||||
if (vgmstream->coding_type == coding_NGC_DSP_subint)
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = fsbh.lengthcompressedbytes / fsbh.numchannels;
|
||||
}
|
||||
|
|
|
@ -193,27 +193,22 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
|||
goto fail;
|
||||
|
||||
case 0x01: /* FMOD_SOUND_FORMAT_PCM8 [Anima - Gate of Memories (PC)] */
|
||||
vgmstream->coding_type = coding_PCM8_U;
|
||||
vgmstream->layout_type = ChannelCount == 1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x01;
|
||||
vgmstream->coding_type = coding_PCM8_U;
|
||||
break;
|
||||
|
||||
case 0x02: /* FMOD_SOUND_FORMAT_PCM16 */
|
||||
if (ChannelCount == 1) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
} else {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_PCM16LE;
|
||||
vgmstream->layout_type = ChannelCount == 1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
break;
|
||||
|
||||
case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */
|
||||
goto fail;
|
||||
goto fail; /* not used */
|
||||
|
||||
case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */
|
||||
goto fail;
|
||||
goto fail; /* not used */
|
||||
|
||||
case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima - Gate of Memories (PC)] */
|
||||
vgmstream->coding_type = coding_PCMFLOAT;
|
||||
|
@ -222,31 +217,25 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
|||
break;
|
||||
|
||||
case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM [Sonic Boom - Fire and Ice (3DS)] */
|
||||
if (ChannelCount == 1) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
} else {
|
||||
vgmstream->layout_type = layout_interleave_byte;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
}
|
||||
vgmstream->coding_type = coding_NGC_DSP_subint;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
|
||||
dsp_read_coefs_be(vgmstream,streamFile,DSPInfoStart,0x2E);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
break;
|
||||
|
||||
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */
|
||||
vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->coding_type = coding_XBOX;
|
||||
if (vgmstream->channels > 2) /* multichannel FSB IMA (interleaved header) */
|
||||
vgmstream->coding_type = coding_FSB_IMA;
|
||||
break;
|
||||
|
||||
case 0x08: /* FMOD_SOUND_FORMAT_VAG */
|
||||
goto fail;
|
||||
goto fail; /* not used */
|
||||
|
||||
case 0x09: /* FMOD_SOUND_FORMAT_HEVAG */
|
||||
vgmstream->coding_type = coding_HEVAG;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x10;
|
||||
vgmstream->coding_type = coding_HEVAG;
|
||||
break;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
|
@ -270,9 +259,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
|||
|
||||
#ifdef VGM_USE_MPEG
|
||||
case 0x0B: {/* FMOD_SOUND_FORMAT_MPEG */
|
||||
mpeg_custom_config cfg;
|
||||
mpeg_custom_config cfg = {0};
|
||||
|
||||
memset(&cfg, 0, sizeof(mpeg_custom_config));
|
||||
cfg.fsb_padding = (vgmstream->channels > 2 ? 16 : 4); /* observed default */
|
||||
|
||||
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, StartOffset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg);
|
||||
|
@ -295,9 +283,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
|||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case 0x0F: {/* FMOD_SOUND_FORMAT_VORBIS */
|
||||
vorbis_custom_config cfg;
|
||||
vorbis_custom_config cfg = {0};
|
||||
|
||||
memset(&cfg, 0, sizeof(vorbis_custom_config));
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.sample_rate = vgmstream->sample_rate;
|
||||
cfg.setup_id = VorbisSetupId;
|
||||
|
|
|
@ -88,11 +88,10 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t
|
|||
vgmstream->loop_start_sample = read_32bitBE(offset+0x14, streamFile);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave_byte;
|
||||
vgmstream->meta_type = meta_KT_WIIBGM;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP_subint;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = 0x1;
|
||||
vgmstream->meta_type = meta_KT_WIIBGM;
|
||||
|
||||
dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60);
|
||||
start_offset = offset+0x800;
|
||||
|
@ -101,7 +100,7 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t
|
|||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "../layout/layout.h"
|
||||
#include "../util.h"
|
||||
|
||||
|
||||
|
||||
/* known GENH types */
|
||||
typedef enum {
|
||||
PSX = 0, /* PSX ADPCM */
|
||||
|
@ -28,26 +30,45 @@ typedef enum {
|
|||
XMA1 = 20, /* raw XMA1 */
|
||||
XMA2 = 21, /* raw XMA2 */
|
||||
FFMPEG = 22, /* any headered FFmpeg format */
|
||||
AC3 = 23, /* AC3/SPDIF */
|
||||
} genh_type;
|
||||
|
||||
typedef struct {
|
||||
genh_type codec;
|
||||
int codec_mode;
|
||||
size_t interleave;
|
||||
|
||||
int channels;
|
||||
int32_t sample_rate;
|
||||
|
||||
size_t data_size;
|
||||
off_t start_offset;
|
||||
|
||||
int32_t num_samples;
|
||||
int32_t loop_start_sample;
|
||||
int32_t loop_end_sample;
|
||||
int skip_samples_mode;
|
||||
int32_t skip_samples;
|
||||
|
||||
int loop_flag;
|
||||
|
||||
int32_t coef[2];
|
||||
int32_t coef_splitted[2];
|
||||
int32_t coef_type;
|
||||
int32_t coef_interleave_type;
|
||||
int coef_big_endian;
|
||||
|
||||
} genh_header;
|
||||
|
||||
static int parse_genh(STREAMFILE * streamFile, genh_header * genh);
|
||||
|
||||
/* GENH is an artificial "generic" header for headerless streams */
|
||||
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
|
||||
int channel_count, loop_flag, sample_rate, interleave;
|
||||
int32_t num_samples = 0, loop_start, loop_end, skip_samples = 0;
|
||||
int32_t start_offset, header_size;
|
||||
off_t datasize = 0;
|
||||
|
||||
int32_t coef[2];
|
||||
int32_t coef_splitted[2];
|
||||
int32_t dsp_interleave_type;
|
||||
int32_t coef_type;
|
||||
int skip_samples_mode, atrac3_mode, xma_mode;
|
||||
genh_header genh = {0};
|
||||
coding_t coding;
|
||||
int i, j;
|
||||
|
||||
coding_t coding;
|
||||
genh_type type;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if (!check_extensions(streamFile,"genh")) goto fail;
|
||||
|
@ -55,12 +76,13 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
/* check header magic */
|
||||
if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;
|
||||
|
||||
channel_count = read_32bitLE(0x4,streamFile);
|
||||
if (channel_count < 1) goto fail;
|
||||
/* process the header */
|
||||
if (!parse_genh(streamFile, &genh))
|
||||
goto fail;
|
||||
|
||||
|
||||
type = read_32bitLE(0x18,streamFile);
|
||||
/* type to coding conversion */
|
||||
switch (type) {
|
||||
switch (genh.codec) {
|
||||
case PSX: coding = coding_PSX; break;
|
||||
case XBOX: coding = coding_XBOX; break;
|
||||
case NGC_DTK: coding = coding_NGC_DTK; break;
|
||||
|
@ -86,68 +108,27 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
case ATRAC3PLUS:
|
||||
case XMA1:
|
||||
case XMA2:
|
||||
case AC3:
|
||||
case FFMPEG: coding = coding_FFmpeg; break;
|
||||
#endif
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
start_offset = read_32bitLE(0x1C,streamFile);
|
||||
header_size = read_32bitLE(0x20,streamFile);
|
||||
|
||||
/* HACK to support old genh */
|
||||
if (header_size == 0) {
|
||||
start_offset = 0x800;
|
||||
header_size = 0x800;
|
||||
}
|
||||
|
||||
/* check for audio data start past header end */
|
||||
if (header_size > start_offset) goto fail;
|
||||
|
||||
interleave = read_32bitLE(0x8,streamFile);
|
||||
sample_rate = read_32bitLE(0xc,streamFile);
|
||||
loop_start = read_32bitLE(0x10,streamFile);
|
||||
loop_end = read_32bitLE(0x14,streamFile);
|
||||
|
||||
coef[0] = read_32bitLE(0x24,streamFile);
|
||||
coef[1] = read_32bitLE(0x28,streamFile);
|
||||
dsp_interleave_type = read_32bitLE(0x2C,streamFile);
|
||||
|
||||
/* DSP coefficient variants */
|
||||
/* bit 0 - split coefs (2 arrays) */
|
||||
/* bit 1 - little endian coefs */
|
||||
coef_type = read_32bitLE(0x30,streamFile);
|
||||
/* when using split coefficients, 2nd array is at: */
|
||||
coef_splitted[0] = read_32bitLE(0x34,streamFile);
|
||||
coef_splitted[1] = read_32bitLE(0x38,streamFile);
|
||||
|
||||
/* other fields */
|
||||
num_samples = read_32bitLE(0x40,streamFile);
|
||||
skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */
|
||||
skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */
|
||||
atrac3_mode = read_8bit(0x49,streamFile); /* 0=autodetect, 1=force joint stereo, 2=force full stereo */
|
||||
xma_mode = read_8bit(0x4a,streamFile); /* 0=default (4ch = 2ch + 2ch), 1=single (4ch = 1ch + 1ch + 1ch + 1ch) */
|
||||
datasize = read_32bitLE(0x50,streamFile);
|
||||
if (!datasize)
|
||||
datasize = get_streamfile_size(streamFile)-start_offset;
|
||||
|
||||
num_samples = num_samples > 0 ? num_samples : loop_end;
|
||||
loop_flag = loop_start != -1;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
vgmstream = allocate_vgmstream(genh.channels,genh.loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
vgmstream->sample_rate = genh.sample_rate;
|
||||
vgmstream->num_samples = genh.num_samples;
|
||||
vgmstream->loop_start_sample = genh.loop_start_sample;
|
||||
vgmstream->loop_end_sample = genh.loop_end_sample;
|
||||
|
||||
/* codec specific */
|
||||
switch (coding) {
|
||||
case coding_PCM8_U_int:
|
||||
vgmstream->layout_type=layout_none;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
case coding_PCM16LE:
|
||||
case coding_PCM16BE:
|
||||
|
@ -160,14 +141,14 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
case coding_IMA:
|
||||
case coding_AICA:
|
||||
case coding_APPLE_IMA4:
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
if (channel_count > 1)
|
||||
vgmstream->interleave_block_size = genh.interleave;
|
||||
if (vgmstream->channels > 1)
|
||||
{
|
||||
if (coding == coding_SDX2) {
|
||||
coding = coding_SDX2_int;
|
||||
}
|
||||
|
||||
if (vgmstream->interleave_block_size==0xffffffff) {
|
||||
if (vgmstream->interleave_block_size==0xffffffff) {// || vgmstream->interleave_block_size == 0) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
else {
|
||||
|
@ -179,7 +160,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
}
|
||||
|
||||
/* to avoid endless loops */
|
||||
if (!interleave && (
|
||||
if (!genh.interleave && (
|
||||
coding == coding_PSX ||
|
||||
coding == coding_PSX_badflags ||
|
||||
coding == coding_IMA_int ||
|
||||
|
@ -194,64 +175,62 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
/* setup adpcm */
|
||||
if (coding == coding_AICA) {
|
||||
int i;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].adpcm_step_index = 0x7f;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case coding_MS_IMA:
|
||||
if (!interleave) goto fail; /* creates garbage */
|
||||
if (!genh.interleave) goto fail; /* creates garbage */
|
||||
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->interleave_block_size = genh.interleave;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
case coding_MSADPCM:
|
||||
if (channel_count > 2) goto fail;
|
||||
if (!interleave) goto fail; /* creates garbage */
|
||||
if (vgmstream->channels > 2) goto fail;
|
||||
if (!genh.interleave) goto fail; /* creates garbage */
|
||||
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->interleave_block_size = genh.interleave;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
case coding_XBOX:
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
case coding_NGC_DTK:
|
||||
if (channel_count != 2) goto fail;
|
||||
if (vgmstream->channels != 2) goto fail;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
case coding_NGC_DSP:
|
||||
if (dsp_interleave_type == 0) {
|
||||
if (!interleave) goto fail;
|
||||
if (genh.coef_interleave_type == 0) {
|
||||
if (!genh.interleave) goto fail;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
} else if (dsp_interleave_type == 1) {
|
||||
if (!interleave) goto fail;
|
||||
vgmstream->layout_type = layout_interleave_byte;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
} else if (dsp_interleave_type == 2) {
|
||||
vgmstream->interleave_block_size = genh.interleave;
|
||||
} else if (genh.coef_interleave_type == 1) {
|
||||
if (!genh.interleave) goto fail;
|
||||
coding = coding_NGC_DSP_subint;
|
||||
vgmstream->interleave_block_size = genh.interleave;
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
} else if (genh.coef_interleave_type == 2) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}// else {
|
||||
// goto fail;
|
||||
//}
|
||||
|
||||
/* get coefs */
|
||||
for (i=0;i<channel_count;i++) {
|
||||
int16_t (*read_16bit)(off_t , STREAMFILE*);
|
||||
/* bit 1 - little endian coefs */
|
||||
if ((coef_type & 2) == 0) {
|
||||
read_16bit = read_16bitBE;
|
||||
} else {
|
||||
read_16bit = read_16bitLE;
|
||||
}
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
int16_t (*read_16bit)(off_t , STREAMFILE*) = genh.coef_big_endian ? read_16bitBE : read_16bitLE;
|
||||
|
||||
/* bit 0 - split coefs (2 arrays) */
|
||||
if ((coef_type & 1) == 0) {
|
||||
/* normal/split coefs bit flag */
|
||||
if ((genh.coef_type & 1) == 0) { /* not set: normal coefs, all 16 interleaved into one array */
|
||||
for (j=0;j<16;j++) {
|
||||
vgmstream->ch[i].adpcm_coef[j] = read_16bit(coef[i]+j*2,streamFile);
|
||||
vgmstream->ch[i].adpcm_coef[j] = read_16bit(genh.coef[i]+j*2,streamFile);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else { /* set: split coefs, 8 coefs in the main array, additional offset to 2nd array given at 0x34 for left, 0x38 for right */
|
||||
for (j=0;j<8;j++) {
|
||||
vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(coef[i]+j*2,streamFile);
|
||||
vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(coef_splitted[i]+j*2,streamFile);
|
||||
vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(genh.coef[i]+j*2,streamFile);
|
||||
vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(genh.coef_splitted[i]+j*2,streamFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -260,7 +239,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
#ifdef VGM_USE_MPEG
|
||||
case coding_MPEG_layer3:
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->codec_data = init_mpeg_codec_data(streamFile, start_offset, &coding, vgmstream->channels);
|
||||
vgmstream->codec_data = init_mpeg_codec_data(streamFile, genh.start_offset, &coding, vgmstream->channels);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
||||
break;
|
||||
|
@ -269,50 +248,53 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
case coding_FFmpeg: {
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
|
||||
if (type == FFMPEG) {
|
||||
if (genh.codec == FFMPEG || genh.codec == AC3) {
|
||||
/* default FFmpeg */
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,datasize);
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, genh.start_offset,genh.data_size);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
||||
//if (vgmstream->num_samples == 0)
|
||||
// vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */
|
||||
}
|
||||
else {
|
||||
/* fake header FFmpeg */
|
||||
uint8_t buf[200];
|
||||
int32_t bytes;
|
||||
|
||||
if (type == ATRAC3) {
|
||||
int block_size = interleave;
|
||||
if (genh.codec == ATRAC3) {
|
||||
int block_size = genh.interleave;
|
||||
int joint_stereo;
|
||||
switch(atrac3_mode) {
|
||||
case 0: joint_stereo = vgmstream->channels > 1 && interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */
|
||||
switch(genh.codec_mode) {
|
||||
case 0: joint_stereo = vgmstream->channels > 1 && genh.interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */
|
||||
case 1: joint_stereo = 1; break; /* force joint stereo */
|
||||
case 2: joint_stereo = 0; break; /* force stereo */
|
||||
default: goto fail;
|
||||
}
|
||||
|
||||
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples);
|
||||
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, genh.skip_samples);
|
||||
}
|
||||
else if (type == ATRAC3PLUS) {
|
||||
int block_size = interleave;
|
||||
else if (genh.codec == ATRAC3PLUS) {
|
||||
int block_size = genh.interleave;
|
||||
|
||||
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, skip_samples);
|
||||
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples);
|
||||
}
|
||||
else if (type == XMA1) {
|
||||
int xma_stream_mode = xma_mode == 1 ? 1 : 0;
|
||||
else if (genh.codec == XMA1) {
|
||||
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
|
||||
|
||||
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
|
||||
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
|
||||
}
|
||||
else if (type == XMA2) {
|
||||
int block_size = interleave ? interleave : 2048;
|
||||
int block_count = datasize / block_size;
|
||||
else if (genh.codec == XMA2) {
|
||||
int block_size = genh.interleave ? genh.interleave : 2048;
|
||||
int block_count = genh.data_size / block_size;
|
||||
|
||||
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
||||
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
|
||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
}
|
||||
|
||||
|
@ -320,8 +302,8 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
vgmstream->layout_type = layout_none;
|
||||
|
||||
/* force encoder delay */
|
||||
if (skip_samples_mode && skip_samples >= 0) {
|
||||
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples);
|
||||
if (genh.skip_samples_mode && genh.skip_samples >= 0) {
|
||||
ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -335,7 +317,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
|||
vgmstream->meta_type = meta_GENH;
|
||||
|
||||
|
||||
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
||||
if ( !vgmstream_open_stream(vgmstream,streamFile,genh.start_offset) )
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
|
@ -344,3 +326,60 @@ fail:
|
|||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int parse_genh(STREAMFILE * streamFile, genh_header * genh) {
|
||||
size_t header_size;
|
||||
|
||||
genh->channels = read_32bitLE(0x4,streamFile);
|
||||
|
||||
genh->interleave = read_32bitLE(0x8,streamFile);
|
||||
genh->sample_rate = read_32bitLE(0xc,streamFile);
|
||||
genh->loop_start_sample = read_32bitLE(0x10,streamFile);
|
||||
genh->loop_end_sample = read_32bitLE(0x14,streamFile);
|
||||
|
||||
genh->codec = read_32bitLE(0x18,streamFile);
|
||||
genh->start_offset = read_32bitLE(0x1C,streamFile);
|
||||
header_size = read_32bitLE(0x20,streamFile);
|
||||
/* HACK to support old genh */
|
||||
if (header_size == 0) {
|
||||
genh->start_offset = 0x800;
|
||||
header_size = 0x800;
|
||||
}
|
||||
/* check for audio data start past header end */
|
||||
if (header_size > genh->start_offset) goto fail;
|
||||
|
||||
genh->coef[0] = read_32bitLE(0x24,streamFile);
|
||||
genh->coef[1] = read_32bitLE(0x28,streamFile);
|
||||
genh->coef_interleave_type = read_32bitLE(0x2C,streamFile);
|
||||
|
||||
/* DSP coefficient variants */
|
||||
/* bit 0 flag - split coefs (2 arrays) */
|
||||
/* bit 1 flag - little endian coefs (for some 3DS) */
|
||||
genh->coef_type = read_32bitLE(0x30,streamFile);
|
||||
genh->coef_big_endian = ((genh->coef_type & 2) == 0);
|
||||
|
||||
/* when using split coefficients, 2nd array is at: */
|
||||
genh->coef_splitted[0] = read_32bitLE(0x34,streamFile);
|
||||
genh->coef_splitted[1] = read_32bitLE(0x38,streamFile);
|
||||
|
||||
/* other fields */
|
||||
genh->num_samples = read_32bitLE(0x40,streamFile);
|
||||
genh->skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */
|
||||
genh->skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */
|
||||
if (genh->codec == ATRAC3 || genh->codec == ATRAC3PLUS)
|
||||
genh->codec_mode = read_8bit(0x49,streamFile); /* 0=autodetect, 1=force joint stereo, 2=force full stereo */
|
||||
if (genh->codec == XMA1 || genh->codec == XMA2)
|
||||
genh->codec_mode = read_8bit(0x4a,streamFile); /* 0=default (4ch = 2ch + 2ch), 1=single (4ch = 1ch + 1ch + 1ch + 1ch) */
|
||||
genh->data_size = read_32bitLE(0x50,streamFile);
|
||||
if (genh->data_size == 0)
|
||||
genh->data_size = get_streamfile_size(streamFile) - genh->start_offset;
|
||||
|
||||
genh->num_samples = genh->num_samples > 0 ? genh->num_samples : genh->loop_end_sample;
|
||||
genh->loop_flag = genh->loop_start_sample != -1;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -155,7 +155,6 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe
|
|||
f++;
|
||||
}
|
||||
|
||||
//;VGM_LOG("HCA: key %08x%08x clip_count=%i\n", ciphKey2,ciphKey1, clip_count);
|
||||
if (min_clip_count < 0 || clip_count < min_clip_count) {
|
||||
min_clip_count = clip_count;
|
||||
best_key2 = key2;
|
||||
|
@ -176,7 +175,7 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe
|
|||
read_streamfile(buffer, hca_data->start, header_size, hca_data->streamfile);
|
||||
|
||||
end:
|
||||
VGM_LOG("HCA: best key=%08x%08x (clips=%i)\n", best_key2,best_key1, min_clip_count);
|
||||
VGM_ASSERT(min_clip_count > 0, "HCA: best key=%08x%08x (clips=%i)\n", best_key2,best_key1, min_clip_count);
|
||||
*out_key2 = best_key2;
|
||||
*out_key1 = best_key1;
|
||||
free(testbuf);//free(temp);
|
||||
|
|
|
@ -12,7 +12,7 @@ typedef struct {
|
|||
*/
|
||||
static const hcakey_info hcakey_list[] = {
|
||||
|
||||
// HCA Decoder default
|
||||
// CRI HCA decoder default
|
||||
{9621963164387704}, // CF222F1FE0748978
|
||||
|
||||
// Phantasy Star Online 2 (multi?)
|
||||
|
@ -28,7 +28,13 @@ static const hcakey_info hcakey_list[] = {
|
|||
// Ro-Kyu-Bu! Himitsu no Otoshimono (PSP)
|
||||
{2012082716}, // 0000000077EDF21C
|
||||
|
||||
// Ro-Kyu-Bu! Naisho no Shutter Chance (PSV)
|
||||
// VRIDGE Inc. games:
|
||||
// - HatsuKare * Renai Debut Sengen! (PSP)
|
||||
// - Seitokai no Ichizon Lv. 2 Portable (PSP)
|
||||
// - Koi wa Kousoku ni Shibararenai! (PSP)
|
||||
// - StormLover 2nd (PSP)
|
||||
// - Prince of Stride (PSVita)
|
||||
// - Ro-Kyu-Bu! Naisho no Shutter Chance (PSVita)
|
||||
{1234253142}, // 0000000049913556
|
||||
|
||||
// Idolm@ster Cinderella Stage (iOS/Android)
|
||||
|
@ -99,18 +105,45 @@ static const hcakey_info hcakey_list[] = {
|
|||
// World Chain (iOS/Android)
|
||||
{4892292804961027794}, // 43E4EA62B8E6C6D2
|
||||
|
||||
// Yuyuyui (iOS/Android) *unconfirmed
|
||||
// Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android)
|
||||
{4867249871962584729}, // 438BF1F883653699
|
||||
|
||||
// Tekken Mobile (iOS/Android)
|
||||
{0xFFFFFFFFFFFFFFFF}, //
|
||||
{0xFFFFFFFFFFFFFFFF}, // FFFFFFFFFFFFFFFF / 18446744073709551615
|
||||
|
||||
// Tales of the Rays (iOS/Android)
|
||||
{9516284}, // 00000000009134FC
|
||||
|
||||
// Skylock - Kamigami to Unmei no Itsutsuko [iOS]
|
||||
// Skylock - Kamigami to Unmei no Itsutsuko (iOS/Android)
|
||||
{49160768297}, // 0000000B7235CB29
|
||||
|
||||
// Tokyo Ghoul: Re Invoke (iOS/Android)
|
||||
{6929101074247145}, // 00189DFB1024ADE9
|
||||
|
||||
// Azur Lane (iOS/Android)
|
||||
{621561580448882}, // 0002354E95356C72
|
||||
|
||||
// One Piece Treasure Cruise (iOS/Android)
|
||||
{1224}, // 00000000000004C8
|
||||
|
||||
// Schoolgirl Strikers ~Twinkle Melodies~ (iOS/Android)
|
||||
{0xDB5B61B8343D0000}, // DB5B61B8343D0000
|
||||
|
||||
// Bad Apple Wars (PSVita)
|
||||
{241352432}, // 000000000E62BEF0
|
||||
|
||||
// Koi to Senkyo to Chocolate Portable (PSP)
|
||||
{243812156}, // 000000000E88473C
|
||||
|
||||
// Custom Drive (PSP)
|
||||
{2012062010}, // 0000000077EDA13A
|
||||
|
||||
// Root Letter (PSVita)
|
||||
{1547531215412131}, // 00057F78B05F9BA3
|
||||
|
||||
// Pro Evolution Soccer 2018 / Winning Eleven 2018 (Android)
|
||||
{14121473}, // 0000000000D77A01
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) {
|
|||
vgmstream->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile);
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
|
||||
vgmstream->layout_type = layout_ivaud_blocked;
|
||||
vgmstream->layout_type = layout_blocked_ivaud;
|
||||
vgmstream->meta_type = meta_PC_IVAUD;
|
||||
|
||||
/* open the file for reading */
|
||||
|
@ -57,7 +57,7 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) {
|
|||
// to avoid troubles with "extra" samples
|
||||
vgmstream->num_samples=((read_32bitLE(0x60,streamFile)/2)*2);
|
||||
|
||||
ivaud_block_update(start_offset,vgmstream);
|
||||
block_update_ivaud(start_offset,vgmstream);
|
||||
|
||||
return vgmstream;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count, i;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if (!check_extensions(streamFile,"xa"))
|
||||
|
@ -18,30 +18,22 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
|
|||
|
||||
loop_flag = 0;
|
||||
channel_count = read_16bitLE(0x0A,streamFile);
|
||||
start_offset = 0x18;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
start_offset = 0x18;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->coding_type = coding_MAXIS_XA;
|
||||
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count;
|
||||
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_MAXIS_XA;
|
||||
vgmstream->coding_type = coding_MAXIS_XA;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
/* open streams */
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
/* fix channel offsets as needed by the codec (could be simplified) */
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
vgmstream->ch[i].channel_start_offset = start_offset+i;
|
||||
vgmstream->ch[i].offset = 0;
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
|
|
|
@ -15,7 +15,7 @@ VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_gcsw(STREAMFILE *streamFile);
|
||||
|
||||
|
@ -80,8 +80,6 @@ VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile);
|
||||
|
@ -160,7 +158,7 @@ VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_nwa(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_eacs(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xss(STREAMFILE * streamFile);
|
||||
|
||||
|
@ -173,7 +171,6 @@ VGMSTREAM * init_vgmstream_aus(STREAMFILE * streamFile);
|
|||
VGMSTREAM * init_vgmstream_rws(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_fsb(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_fsb5(STREAMFILE * streamFile);
|
||||
|
@ -200,11 +197,11 @@ VGMSTREAM * init_vgmstream_ikm(STREAMFILE * streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_sfs(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dvi(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_sat_dvi(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_bg00(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_kcey(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_dc_kcey(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE * streamFile);
|
||||
|
||||
|
@ -218,9 +215,9 @@ VGMSTREAM * init_vgmstream_ps2_psh(STREAMFILE * streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pcm_scd(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_scd_pcm(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pcm_ps2(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_ps2_pcm(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE * streamFile);
|
||||
|
||||
|
@ -243,16 +240,14 @@ VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE * streamFile);
|
|||
VGMSTREAM * init_vgmstream_capdsp(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_de2(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile);
|
||||
|
||||
|
@ -276,14 +271,8 @@ VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE * streamFile);
|
||||
|
||||
//VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_idsp2(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_idsp3(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_idsp4(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE * streamFile);
|
||||
|
@ -323,7 +312,6 @@ VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile);
|
|||
VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE * streamFile);
|
||||
|
@ -361,7 +349,6 @@ VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE * streamFile);
|
|||
VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile);
|
||||
|
@ -389,6 +376,7 @@ VGMSTREAM * init_vgmstream_ps2_vsf(STREAMFILE *streamFile);
|
|||
VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile);
|
||||
|
||||
|
@ -449,7 +437,6 @@ VGMSTREAM * init_vgmstream_wii_bns(STREAMFILE* streamFile);
|
|||
VGMSTREAM * init_vgmstream_wii_was(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xbox_hlwav(STREAMFILE* streamFile);
|
||||
|
@ -494,8 +481,6 @@ VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_p3d(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_adsc(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE* streamFile);
|
||||
|
@ -505,9 +490,7 @@ VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile);
|
|||
VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE* streamFile);
|
||||
|
@ -528,7 +511,7 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE* streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_xau(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE* streamFile);
|
||||
VGMSTREAM * init_vgmstream_bar(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ffw(STREAMFILE* streamFile);
|
||||
|
||||
|
@ -581,10 +564,10 @@ VGMSTREAM * init_vgmstream_hyperscan_kvag(STREAMFILE* streamFile);
|
|||
VGMSTREAM * init_vgmstream_ios_psnd(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE* streamFile);
|
||||
|
@ -670,6 +653,7 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE * streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_txth(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile);
|
||||
|
@ -678,12 +662,30 @@ VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE * streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_stm(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pc_ast(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_naac(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ezw(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_vxn(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_flx(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_mogg(STREAMFILE * streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
|
|
@ -45,6 +45,9 @@ VGMSTREAM * init_vgmstream_mn_str(STREAMFILE *streamFile) {
|
|||
vgmstream->interleave_block_size = 0x800;
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vgmstream->num_samples = read_32bitLE(0x4C,streamFile);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#define NAME_LENGTH PATH_LIMIT
|
||||
|
||||
int exists(char *filename, STREAMFILE *streamfile) {
|
||||
static int exists(char *filename, STREAMFILE *streamfile) {
|
||||
STREAMFILE * temp =
|
||||
streamfile->open(streamfile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!temp) return 0;
|
||||
|
@ -25,7 +25,7 @@ int exists(char *filename, STREAMFILE *streamfile) {
|
|||
}
|
||||
|
||||
/* needs the name of a file in the directory to test, as all we can do reliably is attempt to open a file */
|
||||
int find_directory_name(char *name_base, char *dir_name, int subdir_name_size, char *subdir_name, char *name, char *file_name, STREAMFILE *streamfile) {
|
||||
static int find_directory_name(char *name_base, char *dir_name, int subdir_name_size, char *subdir_name, char *name, char *file_name, STREAMFILE *streamfile) {
|
||||
/* find directory name */
|
||||
{
|
||||
char temp_dir_name[NAME_LENGTH];
|
||||
|
@ -125,7 +125,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) {
|
|||
if (strcasecmp("mus",filename_extension(filename))) goto fail;
|
||||
|
||||
/* read file name base */
|
||||
line_bytes = get_streamfile_dos_line(sizeof(line_buffer),line_buffer,
|
||||
line_bytes = get_streamfile_text_line(sizeof(line_buffer),line_buffer,
|
||||
mus_offset, streamFile, &whole_line_read);
|
||||
if (!whole_line_read) goto fail;
|
||||
mus_offset += line_bytes;
|
||||
|
@ -140,7 +140,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) {
|
|||
/*printf("name base: %s\n",name_base);*/
|
||||
|
||||
/* read track entry count */
|
||||
line_bytes = get_streamfile_dos_line(sizeof(line_buffer),line_buffer,
|
||||
line_bytes = get_streamfile_text_line(sizeof(line_buffer),line_buffer,
|
||||
mus_offset, streamFile, &whole_line_read);
|
||||
if (!whole_line_read) goto fail;
|
||||
if (line_buffer[0] == '\0') goto fail;
|
||||
|
@ -184,7 +184,7 @@ VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) {
|
|||
{
|
||||
int fields_matched;
|
||||
line_bytes =
|
||||
get_streamfile_dos_line(sizeof(line_buffer),line_buffer,
|
||||
get_streamfile_text_line(sizeof(line_buffer),line_buffer,
|
||||
mus_offset, streamFile, &whole_line_read);
|
||||
if (!whole_line_read) goto fail;
|
||||
mus_offset += line_bytes;
|
||||
|
|
|
@ -1,59 +1,42 @@
|
|||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* U-Sing (Wii) .myspd */
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .MYSPF - from U-Sing (Wii) */
|
||||
VGMSTREAM * init_vgmstream_myspd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int channel_count;
|
||||
int loop_flag = 0;
|
||||
int loop_flag = 0, channel_count;
|
||||
off_t start_offset;
|
||||
size_t channel_size;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("myspd",filename_extension(filename))) goto fail;
|
||||
if (!check_extensions(streamFile,"myspd"))
|
||||
goto fail;
|
||||
|
||||
channel_count = 2;
|
||||
start_offset = 0x20;
|
||||
channel_size = read_32bitBE(0x00,streamFile);
|
||||
|
||||
/* check size */
|
||||
if ((read_32bitBE(0x0,streamFile)*channel_count+start_offset) != get_streamfile_size(streamFile))
|
||||
if ((channel_size * channel_count + start_offset) != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = read_32bitBE(0x0,streamFile) * 2;
|
||||
vgmstream->sample_rate = read_32bitBE(0x4,streamFile);
|
||||
vgmstream->num_samples = ima_bytes_to_samples(channel_size*channel_count, channel_count);
|
||||
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
|
||||
|
||||
vgmstream->coding_type = coding_IMA;
|
||||
vgmstream->meta_type = meta_MYSPD;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = channel_size;
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
vgmstream->ch[0].streamfile = file;
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
vgmstream->ch[0].channel_start_offset=
|
||||
vgmstream->ch[0].offset=start_offset;
|
||||
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
vgmstream->ch[1].streamfile = file;
|
||||
|
||||
vgmstream->ch[0].channel_start_offset=
|
||||
vgmstream->ch[1].offset=start_offset + read_32bitBE(0x0,streamFile);
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) {
|
|||
off_t start_offset;
|
||||
int channel_count, loop_flag = 0;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* check extension, case insensitive (made-up extension) */
|
||||
if (!check_extensions(streamFile,"hwas"))
|
||||
goto fail;
|
||||
|
||||
|
@ -33,7 +33,7 @@ VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) {
|
|||
|
||||
vgmstream->meta_type = meta_NDS_HWAS;
|
||||
|
||||
vgmstream->coding_type = coding_IMA;
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
vgmstream->layout_type = layout_hwas_blocked;
|
||||
vgmstream->full_block_size = read_32bitLE(0x04,streamFile); /* usually 0x2000, 0x4000 or 0x8000 */
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile) {
|
|||
int loop_flag;
|
||||
off_t start_offset;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* check extension, case insensitive (made-up extension) */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("rrds",filename_extension(filename))) goto fail;
|
||||
|
||||
|
@ -37,7 +37,7 @@ VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile) {
|
|||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_IMA;
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
vgmstream->meta_type = meta_NDS_RRDS;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@ VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) {
|
|||
if (strcasecmp("strm",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */
|
||||
if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */
|
||||
goto fail;
|
||||
if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */
|
||||
((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */
|
||||
goto fail;
|
||||
if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */
|
||||
((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */
|
||||
goto fail;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* STRM - from Final Fantasy Tactics A2 (NDS) */
|
||||
VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) {
|
||||
|
@ -18,25 +17,24 @@ VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) {
|
|||
|
||||
loop_flag = (read_32bitLE(0x20,streamFile) !=0);
|
||||
channel_count = read_32bitLE(0x24,streamFile);
|
||||
start_offset = 0x2C;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
start_offset = 0x2C;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->coding_type = coding_IMA_int; //todo: seems it has some diffs vs regular IMA
|
||||
vgmstream->num_samples = (read_32bitLE(0x04,streamFile)-start_offset);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x28,streamFile);
|
||||
}
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x28,streamFile);
|
||||
|
||||
vgmstream->interleave_block_size = 0x80;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->meta_type = meta_NDS_STRM_FFTA2;
|
||||
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x80;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -1214,6 +1214,7 @@ fail:
|
|||
Lego Indiana Jones - The Original Adventures (Wii)
|
||||
Lego Indiana Jones 2 - The Adventure Continues (Wii)
|
||||
Lego Star Wars - The Complete Saga (Wii)
|
||||
Lego The Lord of the Rings (Wii)
|
||||
The Chronicles of Narnia - Prince Caspian (Wii) */
|
||||
VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
|
@ -1249,6 +1250,14 @@ VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) {
|
|||
|
||||
start_offset = 0xe0;
|
||||
}
|
||||
else if (read_32bitBE(0x4, streamFile) == 3 && //Lego The Lord of the Rings (Wii)
|
||||
read_32bitBE(0x8, streamFile) == 0x12c)
|
||||
{
|
||||
if (read_dsp_header(&ch0_header, 0x20, streamFile)) goto fail;
|
||||
if (read_dsp_header(&ch1_header, 0x80, streamFile)) goto fail;
|
||||
|
||||
start_offset = 0xe0;
|
||||
}
|
||||
else goto fail;
|
||||
|
||||
interleave = read_32bitBE(0xc, streamFile);
|
||||
|
@ -2070,8 +2079,8 @@ VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) {
|
|||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(
|
||||
ch0_header.loop_end_offset)+1;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave_byte;
|
||||
vgmstream->coding_type = coding_NGC_DSP_subint;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = 0x4;
|
||||
vgmstream->meta_type = meta_WII_NDP;
|
||||
|
||||
|
@ -2089,22 +2098,12 @@ VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) {
|
|||
vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2;
|
||||
|
||||
/* open the file for reading */
|
||||
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[0].streamfile)
|
||||
goto fail;
|
||||
vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start;
|
||||
|
||||
vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[1].streamfile)
|
||||
goto fail;
|
||||
vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,ch1_start))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
|
||||
fail:
|
||||
/* clean up anything we may have opened */
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
#include "../util.h"
|
||||
|
||||
/* .dsp found in:
|
||||
Hikaru No Go 3 (NGC)
|
||||
Yu-Gi-Oh! The Falsebound Kingdom (NGC)
|
||||
Hikaru No Go 3 (NGC)
|
||||
Yu-Gi-Oh! The Falsebound Kingdom (NGC)
|
||||
|
||||
2010-01-31 - added loop stuff and some header checks...
|
||||
2010-01-31 - added loop stuff and some header checks...
|
||||
*/
|
||||
|
||||
VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
off_t start_offset;
|
||||
int i;
|
||||
|
||||
|
@ -24,29 +24,29 @@ VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
|
|||
if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile)))
|
||||
goto fail;
|
||||
|
||||
loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0);
|
||||
loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0);
|
||||
channel_count = 1;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = 0xE0;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
|
||||
/* fill in the vital statistics */
|
||||
start_offset = 0xE0;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->num_samples = read_32bitBE(0x20,streamFile);
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_DSP_YGO;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16);
|
||||
vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16);
|
||||
}
|
||||
vgmstream->meta_type = meta_DSP_YGO;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16);
|
||||
vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16);
|
||||
}
|
||||
|
||||
// read coef stuff
|
||||
{
|
||||
for (i=0;i<16;i++) {
|
||||
// read coef stuff
|
||||
{
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,63 +8,63 @@
|
|||
|
||||
VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
|
||||
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
STREAMFILE * streamFileDSP = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
char filenameDSP[PATH_LIMIT];
|
||||
|
||||
int i;
|
||||
int channel_count;
|
||||
int loop_flag;
|
||||
char filenameDSP[PATH_LIMIT];
|
||||
|
||||
int i;
|
||||
int channel_count;
|
||||
int loop_flag;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("sck",filename_extension(filename))) goto fail;
|
||||
|
||||
|
||||
strcpy(filenameDSP,filename);
|
||||
strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp");
|
||||
strcpy(filenameDSP,filename);
|
||||
strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp");
|
||||
|
||||
streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
if (read_32bitBE(0x5C,streamFile) != 0x60A94000)
|
||||
goto fail;
|
||||
|
||||
if (!streamFile) goto fail;
|
||||
|
||||
channel_count = 2;
|
||||
loop_flag = 0;
|
||||
if (!streamFile) goto fail;
|
||||
|
||||
channel_count = 2;
|
||||
loop_flag = 0;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x18,streamFile);
|
||||
vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14;
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
|
||||
if(loop_flag) {
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14;
|
||||
}
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x18,streamFile);
|
||||
vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14;
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
|
||||
if (channel_count == 1) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
} else if (channel_count == 2) {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile);
|
||||
}
|
||||
if(loop_flag) {
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14;
|
||||
}
|
||||
|
||||
if (channel_count == 1) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
} else if (channel_count == 2) {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
vgmstream->meta_type = meta_NGC_SCK_DSP;
|
||||
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
for (i=0;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].offset = 0;
|
||||
|
||||
|
@ -74,7 +74,7 @@ VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
|
|||
|
||||
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
int i;
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x2C+i*2,streamFile);
|
||||
|
@ -87,7 +87,7 @@ VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
|
|||
}
|
||||
|
||||
|
||||
close_streamfile(streamFileDSP); streamFileDSP=NULL;
|
||||
close_streamfile(streamFileDSP); streamFileDSP=NULL;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -2,30 +2,61 @@
|
|||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .OPUS - from Lego City Undercover (Switch) */
|
||||
/* .OPUS - from Switch games (Lego City Undercover, Ultra SF II, Disgaea 5) */
|
||||
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag = 0, channel_count;
|
||||
int num_samples = 0, loop_start = 0, loop_end = 0;
|
||||
off_t offset = 0;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x01000080)
|
||||
/* variations, maybe custom */
|
||||
if (read_32bitBE(0x00,streamFile) == 0x01000080) { /* Lego City Undercover */
|
||||
offset = 0x00;
|
||||
}
|
||||
else if ((read_32bitBE(0x04,streamFile) == 0x00000000 && read_32bitBE(0x0c,streamFile) == 0x00000000) ||
|
||||
(read_32bitBE(0x04,streamFile) == 0xFFFFFFFF && read_32bitBE(0x0c,streamFile) == 0xFFFFFFFF)) { /* Disgaea 5 */
|
||||
offset = 0x10;
|
||||
|
||||
loop_start = read_32bitLE(0x00,streamFile);
|
||||
loop_end = read_32bitLE(0x08,streamFile);
|
||||
}
|
||||
else if (read_32bitLE(0x04,streamFile) == 0x02) { /* Ultra Street Fighter II */
|
||||
offset = read_32bitLE(0x1c,streamFile);
|
||||
|
||||
num_samples = read_32bitLE(0x00,streamFile);
|
||||
loop_start = read_32bitLE(0x08,streamFile);
|
||||
loop_end = read_32bitLE(0x0c,streamFile);
|
||||
}
|
||||
else {
|
||||
offset = 0x00;
|
||||
}
|
||||
|
||||
if (read_32bitBE(offset + 0x00,streamFile) != 0x01000080)
|
||||
goto fail;
|
||||
|
||||
start_offset = 0x28;
|
||||
channel_count = read_8bit(0x09,streamFile); /* assumed */
|
||||
/* other values in the header: no idea */
|
||||
start_offset = offset + 0x28;
|
||||
channel_count = read_8bit(offset + 0x09,streamFile); /* assumed */
|
||||
/* 0x0a: packet size if CBR?, other values: no idea */
|
||||
|
||||
loop_flag = (loop_end > 0); /* -1 when not set */
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x0c,streamFile);
|
||||
vgmstream->sample_rate = read_32bitLE(offset + 0x0c,streamFile);
|
||||
vgmstream->meta_type = meta_NSW_OPUS;
|
||||
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
uint8_t buf[0x100];
|
||||
|
@ -47,7 +78,8 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
|
|||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile);
|
||||
if (vgmstream->num_samples == 0)
|
||||
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile);
|
||||
}
|
||||
#else
|
||||
goto fail;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* ADP - from Balls of Steel */
|
||||
VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE *streamFile) {
|
||||
|
@ -31,7 +30,7 @@ VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE *streamFile) {
|
|||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_BOS_ADP;
|
||||
|
||||
|
@ -48,45 +47,3 @@ fail:
|
|||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ADP - from Omikron: The Nomad Soul (PC/DC) */
|
||||
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, datasize;
|
||||
int loop_flag = 0, channel_count, stereo_flag;
|
||||
|
||||
if (!check_extensions(streamFile,"adp")) goto fail;
|
||||
|
||||
/* no ID, only a basic 0x10 header with filesize and nulls; do some extra checks */
|
||||
datasize = read_32bitLE(0x00,streamFile) & 0x00FFFFFF; /*24 bit*/
|
||||
if (datasize + 0x10 != streamFile->get_size(streamFile)
|
||||
|| read_32bitLE(0x04,streamFile) != 0
|
||||
|| read_32bitLE(0x08,streamFile) != 0
|
||||
|| read_32bitLE(0x10,streamFile) != 0)
|
||||
goto fail;
|
||||
|
||||
stereo_flag = read_8bit(0x03, streamFile);
|
||||
if (stereo_flag > 1 || stereo_flag < 0) goto fail;
|
||||
channel_count = stereo_flag ? 2 : 1;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
start_offset = 0x10;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = 22050;
|
||||
vgmstream->num_samples = channel_count== 1 ? datasize*2 : datasize;
|
||||
|
||||
vgmstream->coding_type = coding_OTNS_IMA;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_OTNS_ADP;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -9,17 +9,17 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
|
|||
|
||||
int loop_flag=0;
|
||||
int channel_count;
|
||||
off_t start_offset;
|
||||
off_t check_offset;
|
||||
int32_t streamSize;
|
||||
off_t start_offset;
|
||||
off_t check_offset;
|
||||
int32_t streamSize;
|
||||
|
||||
uint8_t testBuffer[0x10];
|
||||
uint8_t isPCM = 0;
|
||||
uint8_t testBuffer[0x10];
|
||||
uint8_t isPCM = 0;
|
||||
|
||||
off_t readOffset = 0;
|
||||
off_t loopEnd = 0;
|
||||
off_t readOffset = 0;
|
||||
off_t loopEnd = 0;
|
||||
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
|
@ -35,27 +35,27 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
|
|||
goto fail;
|
||||
|
||||
/* check if file is not corrupt */
|
||||
/* seems the Gran Turismo 4 ADS files are considered corrupt,*/
|
||||
/* so I changed it to adapt the stream size if that's the case */
|
||||
/* instead of failing playing them at all*/
|
||||
streamSize = read_32bitLE(0x24,streamFile);
|
||||
/* seems the Gran Turismo 4 ADS files are considered corrupt,*/
|
||||
/* so I changed it to adapt the stream size if that's the case */
|
||||
/* instead of failing playing them at all*/
|
||||
streamSize = read_32bitLE(0x24,streamFile);
|
||||
|
||||
if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28))
|
||||
{
|
||||
streamSize = get_streamfile_size(streamFile) - 0x28;
|
||||
}
|
||||
if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28))
|
||||
{
|
||||
streamSize = get_streamfile_size(streamFile) - 0x28;
|
||||
}
|
||||
|
||||
/* check loop */
|
||||
if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) ||
|
||||
((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0)))
|
||||
{
|
||||
loop_flag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
loop_flag = 1;
|
||||
}
|
||||
|
||||
if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) ||
|
||||
((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0)))
|
||||
{
|
||||
loop_flag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
loop_flag = 1;
|
||||
}
|
||||
|
||||
channel_count=read_32bitLE(0x10,streamFile);
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
@ -70,9 +70,9 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
|
|||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->num_samples = ((streamSize-0x40)/16*28)/vgmstream->channels;
|
||||
|
||||
/* SS2 container with RAW Interleaved PCM */
|
||||
/* SS2 container with RAW Interleaved PCM */
|
||||
if (read_32bitLE(0x08,streamFile)!=0x10)
|
||||
{
|
||||
{
|
||||
|
||||
vgmstream->coding_type=coding_PCM16LE;
|
||||
vgmstream->num_samples = streamSize/2/vgmstream->channels;
|
||||
|
@ -84,100 +84,100 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
|
|||
|
||||
/* Get loop point values */
|
||||
if(vgmstream->loop_flag) {
|
||||
if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile))
|
||||
{
|
||||
// Search for Loop Value
|
||||
readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size);
|
||||
if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile))
|
||||
{
|
||||
// Search for Loop Value
|
||||
readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size);
|
||||
|
||||
do {
|
||||
readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
|
||||
|
||||
// Loop End ...
|
||||
if(testBuffer[0x01]==0x01) {
|
||||
if(loopEnd==0) loopEnd = readOffset-0x10;
|
||||
break;
|
||||
}
|
||||
do {
|
||||
readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
|
||||
|
||||
} while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile));
|
||||
// Loop End ...
|
||||
if(testBuffer[0x01]==0x01) {
|
||||
if(loopEnd==0) loopEnd = readOffset-0x10;
|
||||
break;
|
||||
}
|
||||
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28;
|
||||
vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28;
|
||||
vgmstream->loop_end_sample /=vgmstream->channels;
|
||||
} while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile));
|
||||
|
||||
} else {
|
||||
if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
|
||||
} else {
|
||||
vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;;
|
||||
vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels;
|
||||
}
|
||||
}
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28;
|
||||
vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28;
|
||||
vgmstream->loop_end_sample /=vgmstream->channels;
|
||||
|
||||
} else {
|
||||
if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
|
||||
} else {
|
||||
vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;;
|
||||
vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* don't know why, but it does happen, in ps2 too :( */
|
||||
if (vgmstream->loop_end_sample > vgmstream->num_samples)
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
{
|
||||
start_offset=0x28;
|
||||
}
|
||||
{
|
||||
start_offset=0x28;
|
||||
}
|
||||
|
||||
|
||||
if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18))
|
||||
{
|
||||
// True Fortune PS2
|
||||
streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10;
|
||||
vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels;
|
||||
}
|
||||
else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800)
|
||||
{
|
||||
// Hack for files with start_offset = 0x800
|
||||
start_offset=0x800;
|
||||
}
|
||||
|
||||
if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28))
|
||||
{
|
||||
start_offset=0x800;
|
||||
|
||||
for(i=0;i<0x1f6;i+=4)
|
||||
{
|
||||
if(read_32bitLE(0x28+(i*4),streamFile)!=0)
|
||||
{
|
||||
start_offset=0x28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18))
|
||||
{
|
||||
// True Fortune PS2
|
||||
streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10;
|
||||
vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels;
|
||||
}
|
||||
else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800)
|
||||
{
|
||||
// Hack for files with start_offset = 0x800
|
||||
start_offset=0x800;
|
||||
}
|
||||
|
||||
// check if we got a real pcm (ex: Clock Tower 3)
|
||||
if(vgmstream->coding_type==coding_PCM16LE)
|
||||
{
|
||||
check_offset=start_offset;
|
||||
do
|
||||
{
|
||||
if(read_8bit(check_offset+1,streamFile)>7)
|
||||
{
|
||||
isPCM=1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
check_offset+=0x10;
|
||||
}
|
||||
|
||||
} while (check_offset<get_streamfile_size(streamFile));
|
||||
if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28))
|
||||
{
|
||||
start_offset=0x800;
|
||||
|
||||
if(!isPCM)
|
||||
{
|
||||
vgmstream->num_samples=(get_streamfile_size(streamFile)-start_offset)/16*28/vgmstream->channels;
|
||||
vgmstream->coding_type=coding_PSX;
|
||||
}
|
||||
}
|
||||
for(i=0;i<0x1f6;i+=4)
|
||||
{
|
||||
if(read_32bitLE(0x28+(i*4),streamFile)!=0)
|
||||
{
|
||||
start_offset=0x28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* expect pcm format allways start @ 0x800, don't know if it's true :P */
|
||||
/*if(vgmstream->coding_type == coding_PCM16LE)
|
||||
start_offset=0x800;*/
|
||||
// check if we got a real pcm (ex: Clock Tower 3)
|
||||
if(vgmstream->coding_type==coding_PCM16LE)
|
||||
{
|
||||
check_offset=start_offset;
|
||||
do
|
||||
{
|
||||
if(read_8bit(check_offset+1,streamFile)>7)
|
||||
{
|
||||
isPCM=1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
check_offset+=0x10;
|
||||
}
|
||||
|
||||
} while (check_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 */
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue