Updated VGMStream to r1866-46-g883d796d

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2023-09-02 20:56:12 -07:00
parent c802dbfa45
commit 08c904c201
No known key found for this signature in database
71 changed files with 4050 additions and 3067 deletions

View file

@ -94,7 +94,7 @@
831BA6191EAC61A500CF89B0 /* ogl.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA60F1EAC61A500CF89B0 /* ogl.c */; };
831BA61A1EAC61A500CF89B0 /* ps2_vds_vdm.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */; };
831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6111EAC61A500CF89B0 /* sgxd.c */; };
831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6121EAC61A500CF89B0 /* sxd.c */; };
831BA61C1EAC61A500CF89B0 /* sndx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6121EAC61A500CF89B0 /* sndx.c */; };
831BA61D1EAC61A500CF89B0 /* ubi_raki.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6131EAC61A500CF89B0 /* ubi_raki.c */; };
831BA61F1EAC61A500CF89B0 /* cxs.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6151EAC61A500CF89B0 /* cxs.c */; };
831BA6211EAC61A500CF89B0 /* pasx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6171EAC61A500CF89B0 /* pasx.c */; };
@ -323,7 +323,7 @@
836F46AE28208735005B9B87 /* blocked_tt_ad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46AD28208735005B9B87 /* blocked_tt_ad.c */; };
836F46B22820874D005B9B87 /* tt_ad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46AF2820874D005B9B87 /* tt_ad.c */; };
836F46B32820874D005B9B87 /* esf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46B02820874D005B9B87 /* esf.c */; };
836F46B42820874D005B9B87 /* adm3.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46B12820874D005B9B87 /* adm3.c */; };
836F46B42820874D005B9B87 /* adm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46B12820874D005B9B87 /* adm.c */; };
836F46B7282087A6005B9B87 /* cri_utf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46B5282087A6005B9B87 /* cri_utf.c */; };
836F46B8282087A6005B9B87 /* cri_utf.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F46B6282087A6005B9B87 /* cri_utf.h */; };
836F6B4718BDB8880095E648 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836F6B4518BDB8880095E648 /* InfoPlist.strings */; };
@ -375,7 +375,7 @@
836F6F7918BDC2190095E648 /* dc_asd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3D18BDC2180095E648 /* dc_asd.c */; };
836F6F7B18BDC2190095E648 /* dc_idvi.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3F18BDC2180095E648 /* dc_idvi.c */; };
836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4018BDC2180095E648 /* dc_kcey.c */; };
836F6F7D18BDC2190095E648 /* dc_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4118BDC2180095E648 /* dc_str.c */; };
836F6F7D18BDC2190095E648 /* str_sega.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4118BDC2180095E648 /* str_sega.c */; };
836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4318BDC2180095E648 /* dmsg_segh.c */; };
836F6F8218BDC2190095E648 /* ea_schl.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4618BDC2180095E648 /* ea_schl.c */; };
836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4918BDC2180095E648 /* exakt_sc.c */; };
@ -385,7 +385,7 @@
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 */; };
836F6F8D18BDC2190095E648 /* gsp_gsb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5118BDC2180095E648 /* gsp_gsb.c */; };
836F6F8D18BDC2190095E648 /* gsnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5118BDC2180095E648 /* gsnd.c */; };
836F6F8E18BDC2190095E648 /* halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5218BDC2180095E648 /* halpst.c */; };
836F6F8F18BDC2190095E648 /* his.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5318BDC2180095E648 /* his.c */; };
836F6F9118BDC2190095E648 /* ios_psnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5518BDC2180095E648 /* ios_psnd.c */; };
@ -419,7 +419,6 @@
836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7918BDC2180095E648 /* ngc_pdt.c */; };
836F6FB618BDC2190095E648 /* ngc_sck_dsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7A18BDC2180095E648 /* ngc_sck_dsp.c */; };
836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7B18BDC2180095E648 /* ngc_ssm.c */; };
836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */; };
836F6FBA18BDC2190095E648 /* ymf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7E18BDC2180095E648 /* ymf.c */; };
836F6FBD18BDC2190095E648 /* nwa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8118BDC2180095E648 /* nwa.c */; };
836F6FBF18BDC2190095E648 /* otm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8318BDC2180095E648 /* otm.c */; };
@ -432,14 +431,14 @@
836F6FCB18BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8F18BDC2180095E648 /* ads.c */; };
836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9118BDC2180095E648 /* ps2_ass.c */; };
836F6FD018BDC2190095E648 /* ps2_b1s.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9418BDC2180095E648 /* ps2_b1s.c */; };
836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9518BDC2180095E648 /* ps2_bg00.c */; };
836F6FD118BDC2190095E648 /* bg00.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9518BDC2180095E648 /* bg00.c */; };
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9618BDC2180095E648 /* ps2_bmdx.c */; };
836F6FD418BDC2190095E648 /* hxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9818BDC2180095E648 /* hxd.c */; };
836F6FD518BDC2190095E648 /* lp_ap_lep.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9918BDC2180095E648 /* lp_ap_lep.c */; };
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9B18BDC2180095E648 /* ps2_filp.c */; };
836F6FD718BDC2190095E648 /* filp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9B18BDC2180095E648 /* filp.c */; };
836F6FD818BDC2190095E648 /* ps2_gbts.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9C18BDC2180095E648 /* ps2_gbts.c */; };
836F6FD918BDC2190095E648 /* ps2_gcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9D18BDC2180095E648 /* ps2_gcm.c */; };
836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9E18BDC2180095E648 /* ps2_hgc1.c */; };
836F6FDA18BDC2190095E648 /* hgc1.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9E18BDC2180095E648 /* hgc1.c */; };
836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9F18BDC2180095E648 /* ps2_hsf.c */; };
836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA018BDC2180095E648 /* ps2_iab.c */; };
836F6FDE18BDC2190095E648 /* ild.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA218BDC2180095E648 /* ild.c */; };
@ -452,7 +451,7 @@
836F6FF218BDC2190095E648 /* ps2_rnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB618BDC2180095E648 /* ps2_rnd.c */; };
836F6FF418BDC2190095E648 /* rws_80d.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB818BDC2180095E648 /* rws_80d.c */; };
836F6FF618BDC2190095E648 /* ster.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBA18BDC2180095E648 /* ster.c */; };
836F6FF718BDC2190095E648 /* ps2_sl3.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBB18BDC2180095E648 /* ps2_sl3.c */; };
836F6FF718BDC2190095E648 /* sl3.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBB18BDC2180095E648 /* sl3.c */; };
836F6FF818BDC2190095E648 /* smpl.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBC18BDC2180095E648 /* smpl.c */; };
836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBD18BDC2180095E648 /* ps2_snd.c */; };
836F6FFA18BDC2190095E648 /* spm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBE18BDC2190095E648 /* spm.c */; };
@ -465,7 +464,7 @@
836F700818BDC2190095E648 /* ps2_vms.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECC18BDC2190095E648 /* ps2_vms.c */; };
836F700918BDC2190095E648 /* voi.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECD18BDC2190095E648 /* voi.c */; };
836F700B18BDC2190095E648 /* ps2_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECF18BDC2190095E648 /* ps2_wad.c */; };
836F700C18BDC2190095E648 /* ps2_wb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED018BDC2190095E648 /* ps2_wb.c */; };
836F700C18BDC2190095E648 /* wb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED018BDC2190095E648 /* wb.c */; };
836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED118BDC2190095E648 /* ps2_wmus.c */; };
836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED318BDC2190095E648 /* ps2_xa30.c */; };
836F701518BDC2190095E648 /* ps3_past.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED918BDC2190095E648 /* ps3_past.c */; };
@ -497,8 +496,8 @@
836F703918BDC2190095E648 /* vgs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFD18BDC2190095E648 /* vgs.c */; };
836F703A18BDC2190095E648 /* vs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFE18BDC2190095E648 /* vs.c */; };
836F703B18BDC2190095E648 /* vsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFF18BDC2190095E648 /* vsf.c */; };
836F703C18BDC2190095E648 /* wii_bns.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0018BDC2190095E648 /* wii_bns.c */; };
836F703D18BDC2190095E648 /* wii_mus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0118BDC2190095E648 /* wii_mus.c */; };
836F703C18BDC2190095E648 /* bns.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0018BDC2190095E648 /* bns.c */; };
836F703D18BDC2190095E648 /* mus_krome.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0118BDC2190095E648 /* mus_krome.c */; };
836F703E18BDC2190095E648 /* wii_ras.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0218BDC2190095E648 /* wii_ras.c */; };
836F704018BDC2190095E648 /* wii_sng.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0418BDC2190095E648 /* wii_sng.c */; };
836F704218BDC2190095E648 /* sts.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0618BDC2190095E648 /* sts.c */; };
@ -663,6 +662,14 @@
83B69B222845A26600D2435A /* bw_mp3_riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 83B69B212845A26600D2435A /* bw_mp3_riff.c */; };
83B72E3A27904589006007A3 /* libfdk-aac.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83B72E342790452C006007A3 /* libfdk-aac.2.dylib */; };
83BAFB6C19F45EB3005DAB60 /* bfstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BAFB6B19F45EB3005DAB60 /* bfstm.c */; };
83C0C75D2AA435C60056AFD8 /* squeak.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C75C2AA435C60056AFD8 /* squeak.c */; };
83C0C7602AA436370056AFD8 /* layout_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C75E2AA436370056AFD8 /* layout_utils.c */; };
83C0C7612AA436370056AFD8 /* layout_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C0C75F2AA436370056AFD8 /* layout_utils.h */; };
83C0C7632AA436B90056AFD8 /* snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C7622AA436B90056AFD8 /* snds.c */; };
83C0C7682AA437E10056AFD8 /* mixing_priv.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C0C7642AA437E10056AFD8 /* mixing_priv.h */; };
83C0C7692AA437E10056AFD8 /* mixing_fades.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C0C7652AA437E10056AFD8 /* mixing_fades.h */; };
83C0C76A2AA437E10056AFD8 /* mixing_commands.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C7662AA437E10056AFD8 /* mixing_commands.c */; };
83C0C76B2AA437E10056AFD8 /* mixing_macros.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C7672AA437E10056AFD8 /* mixing_macros.c */; };
83C7280F22BC893D00678B4A /* xwb_xsb.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C727FB22BC893800678B4A /* xwb_xsb.h */; };
83C7281022BC893D00678B4A /* nps.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C727FC22BC893900678B4A /* nps.c */; };
83C7281122BC893D00678B4A /* 9tav_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C727FD22BC893900678B4A /* 9tav_streamfile.h */; };
@ -932,7 +939,7 @@
831BA60F1EAC61A500CF89B0 /* ogl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogl.c; sourceTree = "<group>"; };
831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vds_vdm.c; sourceTree = "<group>"; };
831BA6111EAC61A500CF89B0 /* sgxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sgxd.c; sourceTree = "<group>"; };
831BA6121EAC61A500CF89B0 /* sxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sxd.c; sourceTree = "<group>"; };
831BA6121EAC61A500CF89B0 /* sndx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sndx.c; sourceTree = "<group>"; };
831BA6131EAC61A500CF89B0 /* ubi_raki.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_raki.c; sourceTree = "<group>"; };
831BA6151EAC61A500CF89B0 /* cxs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cxs.c; sourceTree = "<group>"; };
831BA6171EAC61A500CF89B0 /* pasx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pasx.c; sourceTree = "<group>"; };
@ -1160,7 +1167,7 @@
836F46AD28208735005B9B87 /* blocked_tt_ad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_tt_ad.c; sourceTree = "<group>"; };
836F46AF2820874D005B9B87 /* tt_ad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tt_ad.c; sourceTree = "<group>"; };
836F46B02820874D005B9B87 /* esf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = esf.c; sourceTree = "<group>"; };
836F46B12820874D005B9B87 /* adm3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adm3.c; sourceTree = "<group>"; };
836F46B12820874D005B9B87 /* adm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adm.c; sourceTree = "<group>"; };
836F46B5282087A6005B9B87 /* cri_utf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cri_utf.c; sourceTree = "<group>"; };
836F46B6282087A6005B9B87 /* cri_utf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cri_utf.h; sourceTree = "<group>"; };
836F6B3918BDB8880095E648 /* libvgmstream.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libvgmstream.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1214,7 +1221,7 @@
836F6E3D18BDC2180095E648 /* dc_asd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_asd.c; sourceTree = "<group>"; };
836F6E3F18BDC2180095E648 /* dc_idvi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_idvi.c; sourceTree = "<group>"; };
836F6E4018BDC2180095E648 /* dc_kcey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_kcey.c; sourceTree = "<group>"; };
836F6E4118BDC2180095E648 /* dc_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_str.c; sourceTree = "<group>"; };
836F6E4118BDC2180095E648 /* str_sega.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_sega.c; sourceTree = "<group>"; };
836F6E4318BDC2180095E648 /* dmsg_segh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dmsg_segh.c; sourceTree = "<group>"; };
836F6E4618BDC2180095E648 /* ea_schl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_schl.c; sourceTree = "<group>"; };
836F6E4918BDC2180095E648 /* exakt_sc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exakt_sc.c; sourceTree = "<group>"; };
@ -1224,7 +1231,7 @@
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>"; };
836F6E5118BDC2180095E648 /* gsp_gsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsp_gsb.c; sourceTree = "<group>"; };
836F6E5118BDC2180095E648 /* gsnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsnd.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>"; };
836F6E5518BDC2180095E648 /* ios_psnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ios_psnd.c; sourceTree = "<group>"; };
@ -1258,7 +1265,6 @@
836F6E7918BDC2180095E648 /* ngc_pdt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_pdt.c; sourceTree = "<group>"; };
836F6E7A18BDC2180095E648 /* ngc_sck_dsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_sck_dsp.c; sourceTree = "<group>"; };
836F6E7B18BDC2180095E648 /* ngc_ssm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ssm.c; sourceTree = "<group>"; };
836F6E7C18BDC2180095E648 /* ngc_tydsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_tydsp.c; sourceTree = "<group>"; };
836F6E7E18BDC2180095E648 /* ymf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ymf.c; sourceTree = "<group>"; };
836F6E8118BDC2180095E648 /* nwa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nwa.c; sourceTree = "<group>"; };
836F6E8318BDC2180095E648 /* otm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = otm.c; sourceTree = "<group>"; };
@ -1271,14 +1277,14 @@
836F6E8F18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = "<group>"; };
836F6E9118BDC2180095E648 /* ps2_ass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ass.c; sourceTree = "<group>"; };
836F6E9418BDC2180095E648 /* ps2_b1s.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_b1s.c; sourceTree = "<group>"; };
836F6E9518BDC2180095E648 /* ps2_bg00.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bg00.c; sourceTree = "<group>"; };
836F6E9518BDC2180095E648 /* bg00.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bg00.c; sourceTree = "<group>"; };
836F6E9618BDC2180095E648 /* ps2_bmdx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bmdx.c; sourceTree = "<group>"; };
836F6E9818BDC2180095E648 /* hxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hxd.c; sourceTree = "<group>"; };
836F6E9918BDC2180095E648 /* lp_ap_lep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lp_ap_lep.c; sourceTree = "<group>"; };
836F6E9B18BDC2180095E648 /* ps2_filp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_filp.c; sourceTree = "<group>"; };
836F6E9B18BDC2180095E648 /* filp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filp.c; sourceTree = "<group>"; };
836F6E9C18BDC2180095E648 /* ps2_gbts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_gbts.c; sourceTree = "<group>"; };
836F6E9D18BDC2180095E648 /* ps2_gcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_gcm.c; sourceTree = "<group>"; };
836F6E9E18BDC2180095E648 /* ps2_hgc1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_hgc1.c; sourceTree = "<group>"; };
836F6E9E18BDC2180095E648 /* hgc1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hgc1.c; sourceTree = "<group>"; };
836F6E9F18BDC2180095E648 /* ps2_hsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_hsf.c; sourceTree = "<group>"; };
836F6EA018BDC2180095E648 /* ps2_iab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_iab.c; sourceTree = "<group>"; };
836F6EA218BDC2180095E648 /* ild.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ild.c; sourceTree = "<group>"; };
@ -1291,7 +1297,7 @@
836F6EB618BDC2180095E648 /* ps2_rnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rnd.c; sourceTree = "<group>"; };
836F6EB818BDC2180095E648 /* rws_80d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rws_80d.c; sourceTree = "<group>"; };
836F6EBA18BDC2180095E648 /* ster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ster.c; sourceTree = "<group>"; };
836F6EBB18BDC2180095E648 /* ps2_sl3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_sl3.c; sourceTree = "<group>"; };
836F6EBB18BDC2180095E648 /* sl3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sl3.c; sourceTree = "<group>"; };
836F6EBC18BDC2180095E648 /* smpl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = smpl.c; sourceTree = "<group>"; };
836F6EBD18BDC2180095E648 /* ps2_snd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_snd.c; sourceTree = "<group>"; };
836F6EBE18BDC2190095E648 /* spm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spm.c; sourceTree = "<group>"; };
@ -1304,7 +1310,7 @@
836F6ECC18BDC2190095E648 /* ps2_vms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vms.c; sourceTree = "<group>"; };
836F6ECD18BDC2190095E648 /* voi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = voi.c; sourceTree = "<group>"; };
836F6ECF18BDC2190095E648 /* ps2_wad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_wad.c; sourceTree = "<group>"; };
836F6ED018BDC2190095E648 /* ps2_wb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_wb.c; sourceTree = "<group>"; };
836F6ED018BDC2190095E648 /* wb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wb.c; sourceTree = "<group>"; };
836F6ED118BDC2190095E648 /* ps2_wmus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_wmus.c; sourceTree = "<group>"; };
836F6ED318BDC2190095E648 /* ps2_xa30.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xa30.c; sourceTree = "<group>"; };
836F6ED918BDC2190095E648 /* ps3_past.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_past.c; sourceTree = "<group>"; };
@ -1336,8 +1342,8 @@
836F6EFD18BDC2190095E648 /* vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vgs.c; sourceTree = "<group>"; };
836F6EFE18BDC2190095E648 /* vs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vs.c; sourceTree = "<group>"; };
836F6EFF18BDC2190095E648 /* vsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vsf.c; sourceTree = "<group>"; };
836F6F0018BDC2190095E648 /* wii_bns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_bns.c; sourceTree = "<group>"; };
836F6F0118BDC2190095E648 /* wii_mus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_mus.c; sourceTree = "<group>"; };
836F6F0018BDC2190095E648 /* bns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bns.c; sourceTree = "<group>"; };
836F6F0118BDC2190095E648 /* mus_krome.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mus_krome.c; sourceTree = "<group>"; };
836F6F0218BDC2190095E648 /* wii_ras.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_ras.c; sourceTree = "<group>"; };
836F6F0418BDC2190095E648 /* wii_sng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_sng.c; sourceTree = "<group>"; };
836F6F0618BDC2190095E648 /* sts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sts.c; sourceTree = "<group>"; };
@ -1504,6 +1510,14 @@
83B69B212845A26600D2435A /* bw_mp3_riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bw_mp3_riff.c; sourceTree = "<group>"; };
83B72E342790452C006007A3 /* libfdk-aac.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libfdk-aac.2.dylib"; path = "../../ThirdParty/fdk-aac/lib/libfdk-aac.2.dylib"; sourceTree = "<group>"; };
83BAFB6B19F45EB3005DAB60 /* bfstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfstm.c; sourceTree = "<group>"; };
83C0C75C2AA435C60056AFD8 /* squeak.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = squeak.c; sourceTree = "<group>"; };
83C0C75E2AA436370056AFD8 /* layout_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = layout_utils.c; sourceTree = "<group>"; };
83C0C75F2AA436370056AFD8 /* layout_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = layout_utils.h; sourceTree = "<group>"; };
83C0C7622AA436B90056AFD8 /* snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = snds.c; sourceTree = "<group>"; };
83C0C7642AA437E10056AFD8 /* mixing_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mixing_priv.h; sourceTree = "<group>"; };
83C0C7652AA437E10056AFD8 /* mixing_fades.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mixing_fades.h; sourceTree = "<group>"; };
83C0C7662AA437E10056AFD8 /* mixing_commands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mixing_commands.c; sourceTree = "<group>"; };
83C0C7672AA437E10056AFD8 /* mixing_macros.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mixing_macros.c; sourceTree = "<group>"; };
83C727FB22BC893800678B4A /* xwb_xsb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xwb_xsb.h; sourceTree = "<group>"; };
83C727FC22BC893900678B4A /* nps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nps.c; sourceTree = "<group>"; };
83C727FD22BC893900678B4A /* 9tav_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 9tav_streamfile.h; sourceTree = "<group>"; };
@ -1699,6 +1713,11 @@
children = (
833E82D92A2857F700CD0580 /* decode.c */,
833E82DC2A2857F700CD0580 /* decode.h */,
833E82C52A28562E00CD0580 /* info.c */,
83C0C7662AA437E10056AFD8 /* mixing_commands.c */,
83C0C7652AA437E10056AFD8 /* mixing_fades.h */,
83C0C7672AA437E10056AFD8 /* mixing_macros.c */,
83C0C7642AA437E10056AFD8 /* mixing_priv.h */,
833E82E02A2857F700CD0580 /* mixing.c */,
833E82DD2A2857F700CD0580 /* mixing.h */,
833E82DE2A2857F700CD0580 /* plugins.c */,
@ -1706,7 +1725,6 @@
833E82DA2A2857F700CD0580 /* render.c */,
833E82E12A2857F700CD0580 /* render.h */,
833E82DB2A2857F700CD0580 /* seek.c */,
833E82C52A28562E00CD0580 /* info.c */,
);
path = base;
sourceTree = "<group>";
@ -1993,7 +2011,7 @@
837CEAD623487E8300E62A4A /* acb.c */,
836F6E2B18BDC2180095E648 /* acm.c */,
83F2CCE125A5B41600F46FA8 /* acx.c */,
836F46B12820874D005B9B87 /* adm3.c */,
836F46B12820874D005B9B87 /* adm.c */,
83AA7F7A2519C042004C5298 /* adp_konami.c */,
83D26A7626E66D98001A9475 /* adp_wildfire.c */,
834FE0CF215C79E8000A5D3D /* adpcm_capcom.c */,
@ -2033,6 +2051,7 @@
836F6E3718BDC2180095E648 /* bcstm.c */,
83BAFB6B19F45EB3005DAB60 /* bfstm.c */,
83A5F75E198DF021009AF94C /* bfwav.c */,
836F6E9518BDC2180095E648 /* bg00.c */,
837CEAD723487E8300E62A4A /* bgw_streamfile.h */,
836F6E3818BDC2180095E648 /* bgw.c */,
8319018328F67F2B00B70711 /* bigrp.c */,
@ -2041,6 +2060,7 @@
837CEAD423487E8300E62A4A /* bmp_konami.c */,
839FBFFA26C354E70016A78A /* bnk_relic.c */,
834FE0CA215C79E7000A5D3D /* bnk_sony.c */,
836F6F0018BDC2190095E648 /* bns.c */,
8373342523F60CDC00DE14DC /* bnsf_keys.h */,
836F6E3918BDC2180095E648 /* bnsf.c */,
836F6E3A18BDC2180095E648 /* brstm.c */,
@ -2060,7 +2080,6 @@
836F6E3D18BDC2180095E648 /* dc_asd.c */,
836F6E3F18BDC2180095E648 /* dc_idvi.c */,
836F6E4018BDC2180095E648 /* dc_kcey.c */,
836F6E4118BDC2180095E648 /* dc_str.c */,
83C7280C22BC893D00678B4A /* dcs_wav.c */,
8373342123F60CDB00DE14DC /* deblock_streamfile.c */,
8373341E23F60CDB00DE14DC /* deblock_streamfile.h */,
@ -2095,6 +2114,7 @@
83C7280022BC893A00678B4A /* ffdl.c */,
838BDB6D1D3B043C0022CA6F /* ffmpeg.c */,
836F6E4B18BDC2180095E648 /* ffw.c */,
836F6E9B18BDC2180095E648 /* filp.c */,
8349A8FD1FE6257F00E26435 /* flx.c */,
83D20072248DDB760048BD24 /* fsb_encrypted_streamfile.h */,
83A21F81201D8981000F04B9 /* fsb_encrypted.c */,
@ -2112,7 +2132,7 @@
836F6E4F18BDC2180095E648 /* genh.c */,
83709DFF1ECBC1A4005C03D3 /* ghs.c */,
8375737421F950EC00F01AF5 /* gin.c */,
836F6E5118BDC2180095E648 /* gsp_gsb.c */,
836F6E5118BDC2180095E648 /* gsnd.c */,
8342469020C4D22F00926E48 /* h4m.c */,
836F6E5218BDC2180095E648 /* halpst.c */,
835B9B8D2730BF2D00F87EE3 /* hca_bf.h */,
@ -2120,6 +2140,7 @@
83AA5D211F6E2F9C0020821C /* hca_keys.h */,
8323894F1D2246C300482226 /* hca.c */,
834FE0DF215C79EB000A5D3D /* hd3_bd3.c */,
836F6E9E18BDC2180095E648 /* hgc1.c */,
836F6E5318BDC2180095E648 /* his.c */,
836F6E9818BDC2180095E648 /* hxd.c */,
834FE0E0215C79EB000A5D3D /* idsp_ie.c */,
@ -2185,6 +2206,7 @@
83D20073248DDB760048BD24 /* mups_streamfile.h */,
83D20077248DDB770048BD24 /* mups.c */,
836F6E6218BDC2180095E648 /* mus_acm.c */,
836F6F0118BDC2190095E648 /* mus_krome.c */,
83C7280622BC893B00678B4A /* mus_vc.c */,
836F6E6318BDC2180095E648 /* musc.c */,
836F6E6418BDC2180095E648 /* musx.c */,
@ -2207,7 +2229,6 @@
836F6E7A18BDC2180095E648 /* ngc_sck_dsp.c */,
836F6E7B18BDC2180095E648 /* ngc_ssm.c */,
8306B0BE2098458C000302D4 /* ngc_str_cauldron.c */,
836F6E7C18BDC2180095E648 /* ngc_tydsp.c */,
83C727FC22BC893900678B4A /* nps.c */,
837CEAE223487F2A00E62A4A /* nub.c */,
832BF81B21E0514B006F50F1 /* nus3audio.c */,
@ -2243,12 +2264,9 @@
836F6E8E18BDC2180095E648 /* ps2_adm.c */,
836F6E9118BDC2180095E648 /* ps2_ass.c */,
836F6E9418BDC2180095E648 /* ps2_b1s.c */,
836F6E9518BDC2180095E648 /* ps2_bg00.c */,
836F6E9618BDC2180095E648 /* ps2_bmdx.c */,
836F6E9B18BDC2180095E648 /* ps2_filp.c */,
836F6E9C18BDC2180095E648 /* ps2_gbts.c */,
836F6E9D18BDC2180095E648 /* ps2_gcm.c */,
836F6E9E18BDC2180095E648 /* ps2_hgc1.c */,
836F6E9F18BDC2180095E648 /* ps2_hsf.c */,
836F6EA018BDC2180095E648 /* ps2_iab.c */,
836F6EA418BDC2180095E648 /* ps2_joe.c */,
@ -2259,7 +2277,6 @@
836F6EB218BDC2180095E648 /* ps2_p2bt.c */,
8349A8F21FE6257D00E26435 /* ps2_pcm.c */,
836F6EB618BDC2180095E648 /* ps2_rnd.c */,
836F6EBB18BDC2180095E648 /* ps2_sl3.c */,
836F6EBD18BDC2180095E648 /* ps2_snd.c */,
836F6EBF18BDC2190095E648 /* ps2_sps.c */,
836F6EC518BDC2190095E648 /* ps2_tec.c */,
@ -2270,7 +2287,6 @@
836F6ECB18BDC2190095E648 /* ps2_vgv.c */,
836F6ECC18BDC2190095E648 /* ps2_vms.c */,
836F6ECF18BDC2190095E648 /* ps2_wad.c */,
836F6ED018BDC2190095E648 /* ps2_wb.c */,
836F6ED118BDC2190095E648 /* ps2_wmus.c */,
836F6ED318BDC2190095E648 /* ps2_xa30.c */,
836F6ED918BDC2190095E648 /* ps3_past.c */,
@ -2319,12 +2335,15 @@
831BA6111EAC61A500CF89B0 /* sgxd.c */,
83AA7F782519C042004C5298 /* silence.c */,
839E21EA1F2EDB0500EE54D7 /* sk_aud.c */,
836F6EBB18BDC2180095E648 /* sl3.c */,
836F6EF218BDC2190095E648 /* sli.c */,
8306B0D32098458F000302D4 /* smc_smh.c */,
837CEAEB23487F2B00E62A4A /* smk.c */,
83F0AA5C21E2028B004BBC04 /* smp.c */,
836F6EBC18BDC2180095E648 /* smpl.c */,
8306B0C72098458D000302D4 /* smv.c */,
83C0C7622AA436B90056AFD8 /* snds.c */,
831BA6121EAC61A500CF89B0 /* sndx.c */,
835559FB2869102B005FE93A /* sndz.c */,
836F6EBE18BDC2190095E648 /* spm.c */,
83A21F82201D8981000F04B9 /* sps_n1.c */,
@ -2333,6 +2352,7 @@
836F6EF418BDC2190095E648 /* sqex_scd.c */,
83A21F84201D8981000F04B9 /* sqex_sead.c */,
837CEAF023487F2C00E62A4A /* sqex_streamfile.h */,
83C0C75C2AA435C60056AFD8 /* squeak.c */,
8396BE782935FC2F00CD0580 /* sscf_encrypted.c */,
8396BE792935FC2F00CD0580 /* sscf_encrypted.h */,
834FE0D6215C79E9000A5D3D /* sscf.c */,
@ -2341,6 +2361,7 @@
836F6EBA18BDC2180095E648 /* ster.c */,
8306B0C12098458C000302D4 /* sthd.c */,
83AA5D231F6E2F9C0020821C /* stma.c */,
836F6E4118BDC2180095E648 /* str_sega.c */,
836F6EF718BDC2190095E648 /* str_snds.c */,
834FE0C2215C79E6000A5D3D /* str_wav.c */,
83C7280722BC893B00678B4A /* strm_abylight.c */,
@ -2350,7 +2371,6 @@
834FE0D7215C79EA000A5D3D /* svg.c */,
836F6EF918BDC2190095E648 /* svs.c */,
83D0381724A4129A004CF90F /* swav.c */,
831BA6121EAC61A500CF89B0 /* sxd.c */,
83E7FD6425EF2B2400683FD2 /* tac.c */,
8373342E23F60D4100DE14DC /* tgc.c */,
836F6EFA18BDC2190095E648 /* thp.c */,
@ -2395,9 +2415,8 @@
8306B0D02098458F000302D4 /* wave_segmented.c */,
8306B0C92098458E000302D4 /* wave.c */,
834FE0D0215C79E8000A5D3D /* wavebatch.c */,
836F6ED018BDC2190095E648 /* wb.c */,
83349715275DD2AC00302E21 /* wbk.c */,
836F6F0018BDC2190095E648 /* wii_bns.c */,
836F6F0118BDC2190095E648 /* wii_mus.c */,
836F6F0218BDC2190095E648 /* wii_ras.c */,
836F6F0418BDC2190095E648 /* wii_sng.c */,
836F6F0718BDC2190095E648 /* wpd.c */,
@ -2476,6 +2495,8 @@
836F46B5282087A6005B9B87 /* cri_utf.c */,
836F46B6282087A6005B9B87 /* cri_utf.h */,
83B46FD42707FB9A00847FC9 /* endianness.h */,
83C0C75E2AA436370056AFD8 /* layout_utils.c */,
83C0C75F2AA436370056AFD8 /* layout_utils.h */,
83D26A7D26E66DC2001A9475 /* log.c */,
83D26A7F26E66DC2001A9475 /* log.h */,
8315868826F586F900803A3A /* m2_psb.c */,
@ -2556,6 +2577,7 @@
836F46B8282087A6005B9B87 /* cri_utf.h in Headers */,
83A21F87201D8981000F04B9 /* fsb_keys.h in Headers */,
83E7FD6325EF2B0C00683FD2 /* tac_decoder_lib_data.h in Headers */,
83C0C7682AA437E10056AFD8 /* mixing_priv.h in Headers */,
83FBB17C2A4FF87200CD0580 /* sf_utils.h in Headers */,
832FC36C278FA4CB0056A860 /* ubi_ckd_cwav_streamfile.h in Headers */,
83E7FD6125EF2B0C00683FD2 /* tac_decoder_lib.h in Headers */,
@ -2574,6 +2596,7 @@
833E82F22A28587D00CD0580 /* paths.h in Headers */,
8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */,
83256CE128666C620036D9C0 /* sample.h in Headers */,
83C0C7612AA436370056AFD8 /* layout_utils.h in Headers */,
83D2007A248DDB770048BD24 /* fsb_encrypted_streamfile.h in Headers */,
833E82E52A2857F700CD0580 /* decode.h in Headers */,
836F6F2718BDC2190095E648 /* g72x_state.h in Headers */,
@ -2610,6 +2633,7 @@
83256CD128666C620036D9C0 /* mpg123lib_intern.h in Headers */,
83C7281622BC893D00678B4A /* xwma_konami_streamfile.h in Headers */,
839E21E81F2EDAF100EE54D7 /* mpeg_decoder.h in Headers */,
83C0C7692AA437E10056AFD8 /* mixing_fades.h in Headers */,
839E21E51F2EDAF100EE54D7 /* vorbis_custom_decoder.h in Headers */,
833E82C82A28566700CD0580 /* channel_mappings.h in Headers */,
83256CC028666C620036D9C0 /* synth_8bit.h in Headers */,
@ -2833,6 +2857,7 @@
8383A62C281203C60062E49E /* s3v.c in Sources */,
8301659B1F256BD000CA0941 /* ea_schl_fixed.c in Sources */,
8301659C1F256BD000CA0941 /* nds_strm_ffta2.c in Sources */,
83C0C7632AA436B90056AFD8 /* snds.c in Sources */,
837CEA7923487E2500E62A4A /* ubi_adpcm_decoder.c in Sources */,
834FE0EB215C79ED000A5D3D /* str_wav.c in Sources */,
83269DD32399F5DE00F49FE3 /* ivag.c in Sources */,
@ -2853,8 +2878,8 @@
836F6F7218BDC2190095E648 /* baf.c in Sources */,
83F5F8831908D0A400C8E65F /* fsb5.c in Sources */,
836F6FD418BDC2190095E648 /* hxd.c in Sources */,
836F700C18BDC2190095E648 /* ps2_wb.c in Sources */,
836F6F7D18BDC2190095E648 /* dc_str.c in Sources */,
836F700C18BDC2190095E648 /* wb.c in Sources */,
836F6F7D18BDC2190095E648 /* str_sega.c in Sources */,
83A5F75F198DF021009AF94C /* bfwav.c in Sources */,
8373341723F60C7B00DE14DC /* g7221_decoder_aes.c in Sources */,
83FBB1792A4FF71B00CD0580 /* rstm_rockstar.c in Sources */,
@ -2882,10 +2907,10 @@
836F6FA118BDC2190095E648 /* myspd.c in Sources */,
8315868726F586E200803A3A /* psb.c in Sources */,
837CEB0123487F2C00E62A4A /* xmu.c in Sources */,
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */,
836F6FD718BDC2190095E648 /* filp.c in Sources */,
8346D97925BF838C00D1A8B0 /* idtech.c in Sources */,
83FF0EBC1E93282100C58054 /* wwise.c in Sources */,
836F46B42820874D005B9B87 /* adm3.c in Sources */,
836F46B42820874D005B9B87 /* adm.c in Sources */,
836F6F7018BDC2190095E648 /* apple_caff.c in Sources */,
836F6FB618BDC2190095E648 /* ngc_sck_dsp.c in Sources */,
836F6F2818BDC2190095E648 /* ima_decoder.c in Sources */,
@ -2915,7 +2940,7 @@
8396BE7A2935FC2F00CD0580 /* sscf_encrypted.c in Sources */,
832389521D224C0800482226 /* hca_decoder.c in Sources */,
836F6F9418BDC2190095E648 /* ivb.c in Sources */,
836F6F8D18BDC2190095E648 /* gsp_gsb.c in Sources */,
836F6F8D18BDC2190095E648 /* gsnd.c in Sources */,
836F704518BDC2190095E648 /* wvs.c in Sources */,
839FBFFB26C354E70016A78A /* wxd_wxh.c in Sources */,
83EDE5D91A70951A005F5D84 /* btsnd.c in Sources */,
@ -2943,7 +2968,7 @@
8349A91F1FE6258200E26435 /* naac.c in Sources */,
83AFABBE23795202002F3947 /* isb.c in Sources */,
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */,
836F703C18BDC2190095E648 /* wii_bns.c in Sources */,
836F703C18BDC2190095E648 /* bns.c in Sources */,
830EBE132004656E0023AA10 /* xnb.c in Sources */,
835027131ED119E000C25929 /* mta2_decoder.c in Sources */,
83A8BAE725667AA8000F5F3F /* sdrh.c in Sources */,
@ -3032,6 +3057,7 @@
836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */,
839FBFFC26C354E70016A78A /* mp4_faac.c in Sources */,
832BF81D21E0514B006F50F1 /* msf_tamasoft.c in Sources */,
83C0C75D2AA435C60056AFD8 /* squeak.c in Sources */,
832BF7FF21E050B7006F50F1 /* circus_decoder.c in Sources */,
83709E071ECBC1A4005C03D3 /* mss.c in Sources */,
836F6F8F18BDC2190095E648 /* his.c in Sources */,
@ -3081,7 +3107,7 @@
8306B0F120984590000302D4 /* ppst.c in Sources */,
832BF81C21E0514B006F50F1 /* xpcm.c in Sources */,
836F702B18BDC2190095E648 /* sdt.c in Sources */,
836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */,
836F6FDA18BDC2190095E648 /* hgc1.c in Sources */,
836F702C18BDC2190095E648 /* seg.c in Sources */,
836F700918BDC2190095E648 /* voi.c in Sources */,
836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */,
@ -3111,6 +3137,7 @@
8373342823F60CDC00DE14DC /* fda.c in Sources */,
836F6F6D18BDC2190095E648 /* aifc.c in Sources */,
836F702218BDC2190095E648 /* rsd.c in Sources */,
83C0C7602AA436370056AFD8 /* layout_utils.c in Sources */,
8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */,
83C7281D22BC893D00678B4A /* ikm.c in Sources */,
834FE0BB215C798C000A5D3D /* celt_fsb_decoder.c in Sources */,
@ -3126,7 +3153,7 @@
83C7281022BC893D00678B4A /* nps.c in Sources */,
83E7FD6025EF2B0C00683FD2 /* tac_decoder_lib.c in Sources */,
83C7281E22BC893D00678B4A /* msf.c in Sources */,
836F6FF718BDC2190095E648 /* ps2_sl3.c in Sources */,
836F6FF718BDC2190095E648 /* sl3.c in Sources */,
8351F32D2212B57000A606E4 /* 208.c in Sources */,
836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */,
836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */,
@ -3156,7 +3183,6 @@
83AA5D271F6E2F9C0020821C /* stma.c in Sources */,
831BA61D1EAC61A500CF89B0 /* ubi_raki.c in Sources */,
8306B0A520984552000302D4 /* blocked_ea_wve_au00.c in Sources */,
836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */,
836F701518BDC2190095E648 /* ps3_past.c in Sources */,
832BF80621E050DC006F50F1 /* blocked_vs_square.c in Sources */,
836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */,
@ -3190,10 +3216,10 @@
832BF81F21E0514B006F50F1 /* ps2_va3.c in Sources */,
8349A91C1FE6258200E26435 /* mogg.c in Sources */,
834FE0F5215C79ED000A5D3D /* wv2.c in Sources */,
836F703D18BDC2190095E648 /* wii_mus.c in Sources */,
836F703D18BDC2190095E648 /* mus_krome.c in Sources */,
836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */,
83031EC8243C50A800C3F3E0 /* circus_decoder_lib.c in Sources */,
831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */,
831BA61C1EAC61A500CF89B0 /* sndx.c in Sources */,
836F6F9618BDC2190095E648 /* lsf.c in Sources */,
8306B0AB20984552000302D4 /* layered.c in Sources */,
833E82E92A2857F700CD0580 /* mixing.c in Sources */,
@ -3245,6 +3271,7 @@
8306B0B220984552000302D4 /* blocked_mxch.c in Sources */,
837CEAFA23487F2C00E62A4A /* xa_04sw.c in Sources */,
836F6F8618BDC2190095E648 /* excitebots.c in Sources */,
83C0C76B2AA437E10056AFD8 /* mixing_macros.c in Sources */,
8385D4E6245174C700FF8E67 /* diva.c in Sources */,
836F6FF418BDC2190095E648 /* rws_80d.c in Sources */,
834FE100215C79ED000A5D3D /* svg.c in Sources */,
@ -3267,6 +3294,7 @@
832BF82621E0514B006F50F1 /* nwav.c in Sources */,
836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */,
8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */,
83C0C76A2AA437E10056AFD8 /* mixing_commands.c in Sources */,
83852B0B2680247900378854 /* rxws.c in Sources */,
831BA6181EAC61A500CF89B0 /* adx.c in Sources */,
832BF82321E0514B006F50F1 /* imc.c in Sources */,
@ -3340,7 +3368,7 @@
834FE111215C79ED000A5D3D /* ck.c in Sources */,
83D2007C248DDB770048BD24 /* ktsr.c in Sources */,
836F704E18BDC2190095E648 /* xss.c in Sources */,
836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */,
836F6FD118BDC2190095E648 /* bg00.c in Sources */,
83AA7F7F2519C042004C5298 /* bsf.c in Sources */,
836F6F4118BDC2190095E648 /* blocked.c in Sources */,
836F6F3B18BDC2190095E648 /* ws_decoder.c in Sources */,

View file

@ -367,6 +367,7 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) {
case coding_PCMFLOAT:
case coding_PCM24LE:
case coding_PCM24BE:
case coding_PCM32LE:
return 1;
#ifdef VGM_USE_VORBIS
case coding_OGG_VORBIS:
@ -422,10 +423,11 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) {
case coding_APPLE_IMA4:
return 64;
case coding_MS_IMA:
case coding_REF_IMA:
return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;/* +1 from header sample */
return ((vgmstream->frame_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1; /* +1 from header sample */
case coding_MS_IMA_mono:
return ((vgmstream->frame_size - 0x04) * 2) + 1; /* +1 from header sample */
case coding_REF_IMA:
return ((vgmstream->interleave_block_size - 0x04 * vgmstream->channels) * 2 / vgmstream->channels) + 1; /* +1 from header sample */
case coding_RAD_IMA:
return (vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels;
case coding_NDS_IMA:
@ -593,6 +595,7 @@ int decode_get_frame_size(VGMSTREAM* vgmstream) {
case coding_ALAW:
return 0x01;
case coding_PCMFLOAT:
case coding_PCM32LE:
return 0x04;
case coding_PCM24LE:
case coding_PCM24BE:
@ -787,7 +790,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_adx(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do,
vgmstream->interleave_block_size, vgmstream->coding_type);
vgmstream->interleave_block_size, vgmstream->coding_type, vgmstream->codec_config);
}
break;
case coding_NGC_DSP:
@ -906,6 +909,13 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
}
break;
case coding_PCM32LE:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_pcm32le(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
}
break;
case coding_NDS_IMA:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_nds_ima(&vgmstream->ch[ch], buffer+ch,

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,254 @@
#include "../vgmstream.h"
#include "../util/channel_mappings.h"
#include "mixing.h"
#include "mixing_priv.h"
#include <math.h>
#include <limits.h>
static int add_mixing(VGMSTREAM* vgmstream, mix_command_data *mix) {
mixing_data *data = vgmstream->mixing_data;
if (!data) return 0;
if (data->mixing_on) {
VGM_LOG("MIX: ignoring new mixes when mixing active\n");
return 0; /* to avoid down/upmixing after activation */
}
if (data->mixing_count + 1 > data->mixing_size) {
VGM_LOG("MIX: too many mixes\n");
return 0;
}
data->mixing_chain[data->mixing_count] = *mix; /* memcpy */
data->mixing_count++;
if (mix->command == MIX_FADE) {
data->has_fade = 1;
}
else {
data->has_non_fade = 1;
}
//;VGM_LOG("MIX: total %i\n", data->mixing_count);
return 1;
}
void mixing_push_swap(VGMSTREAM* vgmstream, int ch_dst, int ch_src) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
if (ch_dst < 0 || ch_src < 0 || ch_dst == ch_src) return;
if (!data || ch_dst >= data->output_channels || ch_src >= data->output_channels) return;
mix.command = MIX_SWAP;
mix.ch_dst = ch_dst;
mix.ch_src = ch_src;
add_mixing(vgmstream, &mix);
}
void mixing_push_add(VGMSTREAM* vgmstream, int ch_dst, int ch_src, double volume) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
if (!data) return;
//if (volume < 0.0) return; /* negative volume inverts the waveform */
if (volume == 0.0) return; /* ch_src becomes silent and nothing is added */
if (ch_dst < 0 || ch_src < 0) return;
if (!data || ch_dst >= data->output_channels || ch_src >= data->output_channels) return;
mix.command = (volume == 1.0) ? MIX_ADD_COPY : MIX_ADD;
mix.ch_dst = ch_dst;
mix.ch_src = ch_src;
mix.vol = volume;
//;VGM_LOG("MIX: add %i+%i*%f\n", ch_dst,ch_src,volume);
add_mixing(vgmstream, &mix);
}
void mixing_push_volume(VGMSTREAM* vgmstream, int ch_dst, double volume) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
//if (ch_dst < 0) return; /* means all channels */
//if (volume < 0.0) return; /* negative volume inverts the waveform */
if (volume == 1.0) return; /* no change */
if (!data || ch_dst >= data->output_channels) return;
mix.command = MIX_VOLUME; //if (volume == 0.0) MIX_VOLUME0 /* could simplify */
mix.ch_dst = ch_dst;
mix.vol = volume;
//;VGM_LOG("MIX: volume %i*%f\n", ch_dst,volume);
add_mixing(vgmstream, &mix);
}
void mixing_push_limit(VGMSTREAM* vgmstream, int ch_dst, double volume) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
//if (ch_dst < 0) return; /* means all channels */
if (volume < 0.0) return;
if (volume == 1.0) return; /* no actual difference */
if (!data || ch_dst >= data->output_channels) return;
//if (volume == 0.0) return; /* dumb but whatevs */
mix.command = MIX_LIMIT;
mix.ch_dst = ch_dst;
mix.vol = volume;
add_mixing(vgmstream, &mix);
}
void mixing_push_upmix(VGMSTREAM* vgmstream, int ch_dst) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
int ok;
if (ch_dst < 0) return;
if (!data || ch_dst > data->output_channels || data->output_channels +1 > VGMSTREAM_MAX_CHANNELS) return;
/* dst can be == output_channels here, since we are inserting */
mix.command = MIX_UPMIX;
mix.ch_dst = ch_dst;
ok = add_mixing(vgmstream, &mix);
if (ok) {
data->output_channels += 1;
if (data->mixing_channels < data->output_channels)
data->mixing_channels = data->output_channels;
}
}
void mixing_push_downmix(VGMSTREAM* vgmstream, int ch_dst) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
int ok;
if (ch_dst < 0) return;
if (!data || ch_dst >= data->output_channels || data->output_channels - 1 < 1) return;
mix.command = MIX_DOWNMIX;
mix.ch_dst = ch_dst;
ok = add_mixing(vgmstream, &mix);
if (ok) {
data->output_channels -= 1;
}
}
void mixing_push_killmix(VGMSTREAM* vgmstream, int ch_dst) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
int ok;
if (ch_dst <= 0) return; /* can't kill from first channel */
if (!data || ch_dst >= data->output_channels) return;
mix.command = MIX_KILLMIX;
mix.ch_dst = ch_dst;
//;VGM_LOG("MIX: killmix %i\n", ch_dst);
ok = add_mixing(vgmstream, &mix);
if (ok) {
data->output_channels = ch_dst; /* clamp channels */
}
}
static mix_command_data* get_last_fade(mixing_data *data, int target_channel) {
int i;
for (i = data->mixing_count; i > 0; i--) {
mix_command_data *mix = &data->mixing_chain[i-1];
if (mix->command != MIX_FADE)
continue;
if (mix->ch_dst == target_channel)
return mix;
}
return NULL;
}
void mixing_push_fade(VGMSTREAM* vgmstream, int ch_dst, double vol_start, double vol_end, char shape,
int32_t time_pre, int32_t time_start, int32_t time_end, int32_t time_post) {
mixing_data *data = vgmstream->mixing_data;
mix_command_data mix = {0};
mix_command_data *mix_prev;
//if (ch_dst < 0) return; /* means all channels */
if (!data || ch_dst >= data->output_channels) return;
if (time_pre > time_start || time_start > time_end || (time_post >= 0 && time_end > time_post)) return;
if (time_start < 0 || time_end < 0) return;
//if (time_pre < 0 || time_post < 0) return; /* special meaning of file start/end */
//if (vol_start == vol_end) /* weird but let in case of being used to cancel others fades... maybe? */
if (shape == '{' || shape == '}')
shape = 'E';
if (shape == '(' || shape == ')')
shape = 'H';
mix.command = MIX_FADE;
mix.ch_dst = ch_dst;
mix.vol_start = vol_start;
mix.vol_end = vol_end;
mix.shape = shape;
mix.time_pre = time_pre;
mix.time_start = time_start;
mix.time_end = time_end;
mix.time_post = time_post;
/* cancel fades and optimize a bit when using negative pre/post:
* - fades work like this:
* <----------|----------|---------->
* pre1 start1 end1 post1
* - when pre and post are set nothing is done (fade is exact and multiple fades may overlap)
* - when previous fade's post or current fade's pre are negative (meaning file end/start)
* they should cancel each other (to allow chaining fade-in + fade-out + fade-in + etc):
* <----------|----------|----------| |----------|----------|---------->
* pre1 start1 end1 post1 pre2 start2 end2 post2
* - other cases (previous fade is actually after/in-between current fade) are ignored
* as they're uncommon and hard to optimize
* fades cancel fades of the same channel, and 'all channel' (-1) fades also cancel 'all channels'
*/
mix_prev = get_last_fade(data, mix.ch_dst);
if (mix_prev == NULL) {
if (vol_start == 1.0 && time_pre < 0)
time_pre = time_start; /* fade-out helds default volume before fade start can be clamped */
if (vol_end == 1.0 && time_post < 0)
time_post = time_end; /* fade-in helds default volume after fade end can be clamped */
}
else if (mix_prev->time_post < 0 || mix.time_pre < 0) {
int is_prev = 1;
/* test if prev is really cancelled by this */
if ((mix_prev->time_end > mix.time_start) ||
(mix_prev->time_post >= 0 && mix_prev->time_post > mix.time_start) ||
(mix.time_pre >= 0 && mix.time_pre < mix_prev->time_end))
is_prev = 0;
if (is_prev) {
/* change negative values to actual points */
if (mix_prev->time_post < 0 && mix.time_pre < 0) {
mix_prev->time_post = mix_prev->time_end;
mix.time_pre = mix_prev->time_post;
}
if (mix_prev->time_post >= 0 && mix.time_pre < 0) {
mix.time_pre = mix_prev->time_post;
}
else if (mix_prev->time_post < 0 && mix.time_pre >= 0) {
mix_prev->time_post = mix.time_pre;
}
/* else: both define start/ends, do nothing */
}
/* should only modify prev if add_mixing but meh */
}
//;VGM_LOG("MIX: fade %i^%f~%f=%c@%i~%i~%i~%i\n", ch_dst, vol_start, vol_end, shape, time_pre, time_start, time_end, time_post);
add_mixing(vgmstream, &mix);
}

View file

@ -0,0 +1,171 @@
#ifndef _MIXING_FADE_H_
#define _MIXING_FADE_H_
#include "mixing_priv.h"
#include <math.h>
#include <limits.h>
#define MIXING_PI 3.14159265358979323846f
static inline int is_fade_active(mixing_data *data, int32_t current_start, int32_t current_end) {
int i;
for (i = 0; i < data->mixing_count; i++) {
mix_command_data *mix = &data->mixing_chain[i];
int32_t fade_start, fade_end;
float vol_start = mix->vol_start;
if (mix->command != MIX_FADE)
continue;
/* check is current range falls within a fade
* (assuming fades were already optimized on add) */
if (mix->time_pre < 0 && vol_start == 1.0) {
fade_start = mix->time_start; /* ignore unused */
}
else {
fade_start = mix->time_pre < 0 ? 0 : mix->time_pre;
}
fade_end = mix->time_post < 0 ? INT_MAX : mix->time_post;
//;VGM_LOG("MIX: fade test, tp=%i, te=%i, cs=%i, ce=%i\n", mix->time_pre, mix->time_post, current_start, current_end);
if (current_start < fade_end && current_end > fade_start) {
//;VGM_LOG("MIX: fade active, cs=%i < fe=%i and ce=%i > fs=%i\n", current_start, fade_end, current_end, fade_start);
return 1;
}
}
return 0;
}
static inline int32_t get_current_pos(VGMSTREAM* vgmstream, int32_t sample_count) {
int32_t current_pos;
if (vgmstream->config_enabled) {
return vgmstream->pstate.play_position;
}
if (vgmstream->loop_flag && vgmstream->loop_count > 0) {
int loop_pre = vgmstream->loop_start_sample; /* samples before looping */
int loop_into = (vgmstream->current_sample - vgmstream->loop_start_sample); /* samples after loop */
int loop_samples = (vgmstream->loop_end_sample - vgmstream->loop_start_sample); /* looped section */
current_pos = loop_pre + (loop_samples * vgmstream->loop_count) + loop_into - sample_count;
}
else {
current_pos = (vgmstream->current_sample - sample_count);
}
return current_pos;
}
static inline float get_fade_gain_curve(char shape, float index) {
float gain;
/* don't bother doing calcs near 0.0/1.0 */
if (index <= 0.0001f || index >= 0.9999f) {
return index;
}
//todo optimizations: interleave calcs, maybe use cosf, powf, etc? (with extra defines)
/* (curve math mostly from SoX/FFmpeg) */
switch(shape) {
/* 2.5f in L/E 'pow' is the attenuation factor, where 5.0 (100db) is common but a bit fast
* (alt calculations with 'exp' from FFmpeg use (factor)*ln(0.1) = -NN.N... */
case 'E': /* exponential (for fade-outs, closer to natural decay of sound) */
//gain = pow(0.1f, (1.0f - index) * 2.5f);
gain = exp(-5.75646273248511f * (1.0f - index));
break;
case 'L': /* logarithmic (inverse of the above, maybe for crossfades) */
//gain = 1 - pow(0.1f, (index) * 2.5f);
gain = 1 - exp(-5.75646273248511f * (index));
break;
case 'H': /* raised sine wave or cosine wave (for more musical crossfades) */
gain = (1.0f - cos(index * MIXING_PI)) / 2.0f;
break;
case 'Q': /* quarter of sine wave (for musical fades) */
gain = sin(index * MIXING_PI / 2.0f);
break;
case 'p': /* parabola (maybe for crossfades) */
gain = 1.0f - sqrt(1.0f - index);
break;
case 'P': /* inverted parabola (maybe for fades) */
gain = (1.0f - (1.0f - index) * (1.0f - index));
break;
case 'T': /* triangular/linear (simpler/sharper fades) */
default:
gain = index;
break;
}
return gain;
}
static int get_fade_gain(mix_command_data *mix, float *out_cur_vol, int32_t current_subpos) {
float cur_vol = 0.0f;
if ((current_subpos >= mix->time_pre || mix->time_pre < 0) && current_subpos < mix->time_start) {
cur_vol = mix->vol_start; /* before */
}
else if (current_subpos >= mix->time_end && (current_subpos < mix->time_post || mix->time_post < 0)) {
cur_vol = mix->vol_end; /* after */
}
else if (current_subpos >= mix->time_start && current_subpos < mix->time_end) {
/* in between */
float range_vol, range_dur, range_idx, index, gain;
if (mix->vol_start < mix->vol_end) { /* fade in */
range_vol = mix->vol_end - mix->vol_start;
range_dur = mix->time_end - mix->time_start;
range_idx = current_subpos - mix->time_start;
index = range_idx / range_dur;
} else { /* fade out */
range_vol = mix->vol_end - mix->vol_start;
range_dur = mix->time_end - mix->time_start;
range_idx = mix->time_end - current_subpos;
index = range_idx / range_dur;
}
/* Fading is done like this:
* - find current position within fade duration
* - get linear % (or rather, index from 0.0 .. 1.0) of duration
* - apply shape to % (from linear fade to curved fade)
* - get final volume for that point
*
* Roughly speaking some curve shapes are better for fades (decay rate is more natural
* sounding in that highest to mid/low happens faster but low to lowest takes more time,
* kinda like a gunshot or bell), and others for crossfades (decay of fade-in + fade-out
* is adjusted so that added volume level stays constant-ish).
*
* As curves can fade in two ways ('normal' and curving 'the other way'), they are adjusted
* to get 'normal' shape on both fades (by reversing index and making 1 - gain), thus some
* curves are complementary (exponential fade-in ~= logarithmic fade-out); the following
* are described taking fade-in = normal.
*/
gain = get_fade_gain_curve(mix->shape, index);
if (mix->vol_start < mix->vol_end) { /* fade in */
cur_vol = mix->vol_start + range_vol * gain;
} else { /* fade out */
cur_vol = mix->vol_end - range_vol * gain; //mix->vol_start - range_vol * (1 - gain);
}
}
else {
/* fade is outside reach */
goto fail;
}
*out_cur_vol = cur_vol;
return 1;
fail:
return 0;
}
#endif

View file

@ -0,0 +1,578 @@
#include "../vgmstream.h"
#include "../util/channel_mappings.h"
#include "mixing.h"
#include "mixing_priv.h"
#include <math.h>
#include <limits.h>
#define MIX_MACRO_VOCALS 'v'
#define MIX_MACRO_EQUAL 'e'
#define MIX_MACRO_BGM 'b'
void mixing_macro_volume(VGMSTREAM* vgmstream, double volume, uint32_t mask) {
mixing_data *data = vgmstream->mixing_data;
int ch;
if (!data)
return;
if (mask == 0) {
mixing_push_volume(vgmstream, -1, volume);
return;
}
for (ch = 0; ch < data->output_channels; ch++) {
if (!((mask >> ch) & 1))
continue;
mixing_push_volume(vgmstream, ch, volume);
}
}
void mixing_macro_track(VGMSTREAM* vgmstream, uint32_t mask) {
mixing_data *data = vgmstream->mixing_data;
int ch;
if (!data)
return;
if (mask == 0) {
return;
}
/* reverse remove all channels (easier this way as when removing channels numbers change) */
for (ch = data->output_channels - 1; ch >= 0; ch--) {
if ((mask >> ch) & 1)
continue;
mixing_push_downmix(vgmstream, ch);
}
}
/* get highest channel count */
static int get_layered_max_channels(VGMSTREAM* vgmstream) {
int i, max;
layered_layout_data* data;
if (vgmstream->layout_type != layout_layered)
return 0;
data = vgmstream->layout_data;
max = 0;
for (i = 0; i < data->layer_count; i++) {
int output_channels = 0;
mixing_info(data->layers[i], NULL, &output_channels);
if (max < output_channels)
max = output_channels;
}
return max;
}
static int is_layered_auto(VGMSTREAM* vgmstream, int max, char mode) {
int i;
mixing_data *data = vgmstream->mixing_data;
layered_layout_data* l_data;
if (vgmstream->layout_type != layout_layered)
return 0;
/* no channels set and only vocals for now */
if (max > 0 || mode != MIX_MACRO_VOCALS)
return 0;
/* no channel down/upmixing (cannot guess output) */
for (i = 0; i < data->mixing_count; i++) {
mix_command_t mix = data->mixing_chain[i].command;
if (mix == MIX_UPMIX || mix == MIX_DOWNMIX || mix == MIX_KILLMIX) /*mix == MIX_SWAP || ??? */
return 0;
}
/* only previsible cases */
l_data = vgmstream->layout_data;
for (i = 0; i < l_data->layer_count; i++) {
int output_channels = 0;
mixing_info(l_data->layers[i], NULL, &output_channels);
if (output_channels > 8)
return 0;
}
return 1;
}
/* special layering, where channels are respected (so Ls only go to Ls), also more optimized */
static void mixing_macro_layer_auto(VGMSTREAM* vgmstream, int max, char mode) {
layered_layout_data* ldata = vgmstream->layout_data;
int i, ch;
int target_layer = 0, target_chs = 0, ch_max, target_ch = 0, target_silence = 0;
int ch_num;
/* With N layers like: (ch1 ch2) (ch1 ch2 ch3 ch4) (ch1 ch2), output is normally 2+4+2=8ch.
* We want to find highest layer (ch1..4) = 4ch, add other channels to it and drop them */
/* find target "main" channels (will be first most of the time) */
ch_num = 0;
ch_max = 0;
for (i = 0; i < ldata->layer_count; i++) {
int layer_chs = 0;
mixing_info(ldata->layers[i], NULL, &layer_chs);
if (ch_max < layer_chs || (ch_max == layer_chs && target_silence)) {
target_ch = ch_num;
target_chs = layer_chs;
target_layer = i;
ch_max = layer_chs;
/* avoid using silence as main if possible for minor optimization */
target_silence = (ldata->layers[i]->coding_type == coding_SILENCE);
}
ch_num += layer_chs;
}
/* all silences? */
if (!target_chs) {
target_ch = 0;
target_chs = 0;
target_layer = 0;
mixing_info(ldata->layers[0], NULL, &target_chs);
}
/* add other channels to target (assumes standard channel mapping to simplify)
* most of the time all layers will have same number of channels though */
ch_num = 0;
for (i = 0; i < ldata->layer_count; i++) {
int layer_chs = 0;
if (target_layer == i) {
ch_num += target_chs;
continue;
}
mixing_info(ldata->layers[i], NULL, &layer_chs);
if (ldata->layers[i]->coding_type == coding_SILENCE) {
ch_num += layer_chs;
continue; /* unlikely but sometimes in Wwise */
}
if (layer_chs == target_chs) {
/* 1:1 mapping */
for (ch = 0; ch < layer_chs; ch++) {
mixing_push_add(vgmstream, target_ch + ch, ch_num + ch, 1.0);
}
}
else {
const double vol_sqrt = 1 / sqrt(2);
/* extra mixing for better sound in some cases (assumes layer_chs is lower than target_chs) */
switch(layer_chs) {
case 1:
mixing_push_add(vgmstream, target_ch + 0, ch_num + 0, vol_sqrt);
mixing_push_add(vgmstream, target_ch + 1, ch_num + 0, vol_sqrt);
break;
case 2:
mixing_push_add(vgmstream, target_ch + 0, ch_num + 0, 1.0);
mixing_push_add(vgmstream, target_ch + 1, ch_num + 1, 1.0);
break;
default: /* less common */
//TODO add other mixes, depends on target_chs + mapping (ex. 4.0 to 5.0 != 5.1, 2.1 xiph to 5.1 != 5.1 xiph)
for (ch = 0; ch < layer_chs; ch++) {
mixing_push_add(vgmstream, target_ch + ch, ch_num + ch, 1.0);
}
break;
}
}
ch_num += layer_chs;
}
/* drop non-target channels */
ch_num = 0;
for (i = 0; i < ldata->layer_count; i++) {
if (i < target_layer) { /* least common, hopefully (slower to drop chs 1 by 1) */
int layer_chs = 0;
mixing_info(ldata->layers[i], NULL, &layer_chs);
for (ch = 0; ch < layer_chs; ch++) {
mixing_push_downmix(vgmstream, ch_num); //+ ch
}
//ch_num += layer_chs; /* dropped channels change this */
}
else if (i == target_layer) {
ch_num += target_chs;
}
else { /* most common, hopefully (faster) */
mixing_push_killmix(vgmstream, ch_num);
break;
}
}
}
void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, char mode) {
mixing_data *data = vgmstream->mixing_data;
int current, ch, output_channels, selected_channels;
if (!data)
return;
if (is_layered_auto(vgmstream, max, mode)) {
//;VGM_LOG("MIX: auto layer mode\n");
mixing_macro_layer_auto(vgmstream, max, mode);
return;
}
//;VGM_LOG("MIX: regular layer mode\n");
if (max == 0) /* auto calculate */
max = get_layered_max_channels(vgmstream);
if (max <= 0 || data->output_channels <= max)
return;
/* set all channels (non-existant channels will be ignored) */
if (mask == 0) {
mask = ~mask;
}
/* save before adding fake channels */
output_channels = data->output_channels;
/* count possibly set channels */
selected_channels = 0;
for (ch = 0; ch < output_channels; ch++) {
selected_channels += (mask >> ch) & 1;
}
/* make N fake channels at the beginning for easier calcs */
for (ch = 0; ch < max; ch++) {
mixing_push_upmix(vgmstream, 0);
}
/* add all layers in this order: ch0: 0, 0+N, 0+N*2 ... / ch1: 1, 1+N ... */
current = 0;
for (ch = 0; ch < output_channels; ch++) {
double volume = 1.0;
if (!((mask >> ch) & 1))
continue;
/* MIX_MACRO_VOCALS: same volume for all layers (for layered vocals) */
/* MIX_MACRO_EQUAL: volume adjusted equally for all layers (for generic downmixing) */
/* MIX_MACRO_BGM: volume adjusted depending on layers (for layered bgm) */
if (mode == MIX_MACRO_BGM && ch < max) {
/* reduce a bit main channels (see below) */
int channel_mixes = selected_channels / max;
if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */
channel_mixes += 1;
channel_mixes -= 1; /* better formula? */
if (channel_mixes <= 0) /* ??? */
channel_mixes = 1;
volume = 1 / sqrt(channel_mixes);
}
if ((mode == MIX_MACRO_BGM && ch >= max) || (mode == MIX_MACRO_EQUAL)) {
/* find how many will be mixed in current channel (earlier channels receive more
* mixes than later ones, ex: selected 8ch + max 3ch: ch0=0+3+6, ch1=1+4+7, ch2=2+5) */
int channel_mixes = selected_channels / max;
if (channel_mixes <= 0) /* ??? */
channel_mixes = 1;
if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */
channel_mixes += 1;
volume = 1 / sqrt(channel_mixes); /* "power" add */
}
//;VGM_LOG("MIX: layer ch=%i, cur=%i, v=%f\n", ch, current, volume);
mixing_push_add(vgmstream, current, max + ch, volume); /* ch adjusted considering upmixed channels */
current++;
if (current >= max)
current = 0;
}
/* remove all mixed channels */
mixing_push_killmix(vgmstream, max);
}
void mixing_macro_crosstrack(VGMSTREAM* vgmstream, int max) {
mixing_data *data = vgmstream->mixing_data;
int current, ch, track, track_ch, track_num, output_channels;
int32_t change_pos, change_next, change_time;
if (!data)
return;
if (max <= 0 || data->output_channels <= max)
return;
if (!vgmstream->loop_flag) /* maybe force loop? */
return;
/* this probably only makes sense for even channels so upmix before if needed) */
output_channels = data->output_channels;
if (output_channels % 2) {
mixing_push_upmix(vgmstream, output_channels);
output_channels += 1;
}
/* set loops to hear all track changes */
track_num = output_channels / max;
if (vgmstream->config.loop_count < track_num) {
vgmstream->config.loop_count = track_num;
vgmstream->config.loop_count_set = 1;
vgmstream->config.config_set = 1;
}
ch = 0;
for (track = 0; track < track_num; track++) {
double volume = 1.0; /* won't play at the same time, no volume change needed */
int loop_pre = vgmstream->loop_start_sample;
int loop_samples = vgmstream->loop_end_sample - vgmstream->loop_start_sample;
change_pos = loop_pre + loop_samples * track;
change_next = loop_pre + loop_samples * (track + 1);
change_time = 15.0 * vgmstream->sample_rate; /* in secs */
for (track_ch = 0; track_ch < max; track_ch++) {
if (track > 0) { /* fade-in when prev track fades-out */
mixing_push_fade(vgmstream, ch + track_ch, 0.0, volume, '(', -1, change_pos, change_pos + change_time, -1);
}
if (track + 1 < track_num) { /* fade-out when next track fades-in */
mixing_push_fade(vgmstream, ch + track_ch, volume, 0.0, ')', -1, change_next, change_next + change_time, -1);
}
}
ch += max;
}
/* mix all tracks into first */
current = 0;
for (ch = max; ch < output_channels; ch++) {
mixing_push_add(vgmstream, current, ch, 1.0); /* won't play at the same time, no volume change needed */
current++;
if (current >= max)
current = 0;
}
/* remove unneeded channels */
mixing_push_killmix(vgmstream, max);
}
void mixing_macro_crosslayer(VGMSTREAM* vgmstream, int max, char mode) {
mixing_data *data = vgmstream->mixing_data;
int current, ch, layer, layer_ch, layer_num, loop, output_channels;
int32_t change_pos, change_time;
if (!data)
return;
if (max <= 0 || data->output_channels <= max)
return;
if (!vgmstream->loop_flag) /* maybe force loop? */
return;
/* this probably only makes sense for even channels so upmix before if needed) */
output_channels = data->output_channels;
if (output_channels % 2) {
mixing_push_upmix(vgmstream, output_channels);
output_channels += 1;
}
/* set loops to hear all track changes */
layer_num = output_channels / max;
if (vgmstream->config.loop_count < layer_num) {
vgmstream->config.loop_count = layer_num;
vgmstream->config.loop_count_set = 1;
vgmstream->config.config_set = 1;
}
/* MIX_MACRO_VOCALS: constant volume
* MIX_MACRO_EQUAL: sets fades to successively lower/equalize volume per loop for each layer
* (to keep final volume constant-ish), ex. 3 layers/loops, 2 max:
* - layer0 (ch0+1): loop0 --[1.0]--, loop1 )=1.0..0.7, loop2 )=0.7..0.5, loop3 --[0.5/end]--
* - layer1 (ch2+3): loop0 --[0.0]--, loop1 (=0.0..0.7, loop2 )=0.7..0.5, loop3 --[0.5/end]--
* - layer2 (ch4+5): loop0 --[0.0]--, loop1 ---[0.0]--, loop2 (=0.0..0.5, loop3 --[0.5/end]--
* MIX_MACRO_BGM: similar but 1st layer (main) has higher/delayed volume:
* - layer0 (ch0+1): loop0 --[1.0]--, loop1 )=1.0..1.0, loop2 )=1.0..0.7, loop3 --[0.7/end]--
*/
for (loop = 1; loop < layer_num; loop++) {
double volume1 = 1.0;
double volume2 = 1.0;
int loop_pre = vgmstream->loop_start_sample;
int loop_samples = vgmstream->loop_end_sample - vgmstream->loop_start_sample;
change_pos = loop_pre + loop_samples * loop;
change_time = 10.0 * vgmstream->sample_rate; /* in secs */
if (mode == MIX_MACRO_EQUAL) {
volume1 = 1 / sqrt(loop + 0);
volume2 = 1 / sqrt(loop + 1);
}
ch = 0;
for (layer = 0; layer < layer_num; layer++) {
char type;
if (mode == MIX_MACRO_BGM) {
if (layer == 0) {
volume1 = 1 / sqrt(loop - 1 <= 0 ? 1 : loop - 1);
volume2 = 1 / sqrt(loop + 0);
}
else {
volume1 = 1 / sqrt(loop + 0);
volume2 = 1 / sqrt(loop + 1);
}
}
if (layer > loop) { /* not playing yet (volume is implicitly 0.0 from first fade in) */
continue;
} else if (layer == loop) { /* fades in for the first time */
volume1 = 0.0;
type = '(';
} else { /* otherwise fades out to match other layers's volume */
type = ')';
}
//;VGM_LOG("MIX: loop=%i, layer %i, vol1=%f, vol2=%f\n", loop, layer, volume1, volume2);
for (layer_ch = 0; layer_ch < max; layer_ch++) {
mixing_push_fade(vgmstream, ch + layer_ch, volume1, volume2, type, -1, change_pos, change_pos + change_time, -1);
}
ch += max;
}
}
/* mix all tracks into first */
current = 0;
for (ch = max; ch < output_channels; ch++) {
mixing_push_add(vgmstream, current, ch, 1.0);
current++;
if (current >= max)
current = 0;
}
/* remove unneeded channels */
mixing_push_killmix(vgmstream, max);
}
typedef enum {
pos_FL = 0,
pos_FR = 1,
pos_FC = 2,
pos_LFE = 3,
pos_BL = 4,
pos_BR = 5,
pos_FLC = 6,
pos_FRC = 7,
pos_BC = 8,
pos_SL = 9,
pos_SR = 10,
} mixing_position_t;
void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/) {
mixing_data *data = vgmstream->mixing_data;
int ch, output_channels, mp_in, mp_out, ch_in, ch_out;
channel_mapping_t input_mapping, output_mapping;
const double vol_max = 1.0;
const double vol_sqrt = 1 / sqrt(2);
const double vol_half = 1 / 2;
double matrix[16][16] = {{0}};
if (!data)
return;
if (max <= 1 || data->output_channels <= max || max >= 8)
return;
/* assume WAV defaults if not set */
input_mapping = vgmstream->channel_layout;
if (input_mapping == 0) {
switch(data->output_channels) {
case 1: input_mapping = mapping_MONO; break;
case 2: input_mapping = mapping_STEREO; break;
case 3: input_mapping = mapping_2POINT1; break;
case 4: input_mapping = mapping_QUAD; break;
case 5: input_mapping = mapping_5POINT0; break;
case 6: input_mapping = mapping_5POINT1; break;
case 7: input_mapping = mapping_7POINT0; break;
case 8: input_mapping = mapping_7POINT1; break;
default: return;
}
}
/* build mapping matrix[input channel][output channel] = volume,
* using standard WAV/AC3 downmix formulas
* - https://www.audiokinetic.com/library/edge/?source=Help&id=downmix_tables
* - https://www.audiokinetic.com/library/edge/?source=Help&id=standard_configurations
*/
switch(max) {
case 1:
output_mapping = mapping_MONO;
matrix[pos_FL][pos_FC] = vol_sqrt;
matrix[pos_FR][pos_FC] = vol_sqrt;
matrix[pos_FC][pos_FC] = vol_max;
matrix[pos_SL][pos_FC] = vol_half;
matrix[pos_SR][pos_FC] = vol_half;
matrix[pos_BL][pos_FC] = vol_half;
matrix[pos_BR][pos_FC] = vol_half;
break;
case 2:
output_mapping = mapping_STEREO;
matrix[pos_FL][pos_FL] = vol_max;
matrix[pos_FR][pos_FR] = vol_max;
matrix[pos_FC][pos_FL] = vol_sqrt;
matrix[pos_FC][pos_FR] = vol_sqrt;
matrix[pos_SL][pos_FL] = vol_sqrt;
matrix[pos_SR][pos_FR] = vol_sqrt;
matrix[pos_BL][pos_FL] = vol_sqrt;
matrix[pos_BR][pos_FR] = vol_sqrt;
break;
default:
/* not sure if +3ch would use FC/LFE, SL/BR and whatnot without passing extra config, so ignore for now */
return;
}
/* save and make N fake channels at the beginning for easier calcs */
output_channels = data->output_channels;
for (ch = 0; ch < max; ch++) {
mixing_push_upmix(vgmstream, 0);
}
/* downmix */
ch_in = 0;
for (mp_in = 0; mp_in < 16; mp_in++) {
/* read input mapping (ex. 5.1) and find channel */
if (!(input_mapping & (1<<mp_in)))
continue;
ch_out = 0;
for (mp_out = 0; mp_out < 16; mp_out++) {
/* read output mapping (ex. 2.0) and find channel */
if (!(output_mapping & (1<<mp_out)))
continue;
mixing_push_add(vgmstream, ch_out, max + ch_in, matrix[mp_in][mp_out]);
ch_out++;
if (ch_out > max)
break;
}
ch_in++;
if (ch_in >= output_channels)
break;
}
/* remove unneeded channels */
mixing_push_killmix(vgmstream, max);
}

View file

@ -0,0 +1,52 @@
#ifndef _MIXING_PRIV_H_
#define _MIXING_PRIV_H_
#include "../vgmstream.h"
#define VGMSTREAM_MAX_MIXING 512
/* mixing info */
typedef enum {
MIX_SWAP,
MIX_ADD,
MIX_ADD_COPY,
MIX_VOLUME,
MIX_LIMIT,
MIX_UPMIX,
MIX_DOWNMIX,
MIX_KILLMIX,
MIX_FADE
} mix_command_t;
typedef struct {
mix_command_t command;
/* common */
int ch_dst;
int ch_src;
float vol;
/* fade envelope */
float vol_start; /* volume from pre to start */
float vol_end; /* volume from end to post */
char shape; /* curve type */
int32_t time_pre; /* position before time_start where vol_start applies (-1 = beginning) */
int32_t time_start; /* fade start position where vol changes from vol_start to vol_end */
int32_t time_end; /* fade end position where vol changes from vol_start to vol_end */
int32_t time_post; /* position after time_end where vol_end applies (-1 = end) */
} mix_command_data;
typedef struct {
int mixing_channels; /* max channels needed to mix */
int output_channels; /* resulting channels after mixing */
int mixing_on; /* mixing allowed */
int mixing_count; /* mixing number */
size_t mixing_size; /* mixing max */
mix_command_data mixing_chain[VGMSTREAM_MAX_MIXING]; /* effects to apply (could be alloc'ed but to simplify...) */
float* mixbuf; /* internal mixing buffer */
/* fades only apply at some points, other mixes are active */
int has_non_fade;
int has_fade;
} mixing_data;
#endif

View file

@ -274,7 +274,6 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) {
case layout_blocked_wsi:
case layout_blocked_str_snds:
case layout_blocked_ws_aud:
case layout_blocked_matx:
case layout_blocked_dec:
case layout_blocked_vs:
case layout_blocked_mul:

View file

@ -1,7 +1,7 @@
#include "coding.h"
#include "../util.h"
void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_size, coding_t coding_type) {
void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_size, coding_t coding_type, uint32_t codec_config) {
uint8_t frame[0x12] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
@ -9,6 +9,7 @@ void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
int scale, coef1, coef2;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int version = codec_config;
/* external interleave (fixed size), mono */
@ -50,7 +51,7 @@ void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
break;
case coding_CRI_ADX_enc_8:
case coding_CRI_ADX_enc_9:
scale = ((scale ^ stream->adx_xor) & 0x1fff) + 1;
scale = ((scale ^ stream->adx_xor) & 0x1fff) + 1; /* this seems to be used even in unencrypted ADX (compatible) */
coef1 = stream->adpcm_coef[0];
coef2 = stream->adpcm_coef[1];
break;
@ -69,7 +70,13 @@ void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
sample = i&1 ? /* high nibble first */
get_low_nibble_signed(nibbles):
get_high_nibble_signed(nibbles);
sample = sample * scale + (coef1 * hist1 >> 12) + (coef2 * hist2 >> 12);
/* Early (v3 ADX only) libs decode slightly differently (quieter?), while later libs (v4 ADX) tweaked it. V4 libs playing v3 files
* seem to behave like V4 though, so it's not detectable but not that common (ex. ports of old games reusing v3 ADX) */
if (version == 0x0300)
sample = sample * scale + ((coef1 * hist1) >> 12) + ((coef2 * hist2) >> 12); /* V3 lib */
else
sample = sample * scale + ((coef1 * hist1 + coef2 * hist2) >> 12); /* V4 lib */
sample = clamp16(sample);
outbuf[sample_count] = sample;

View file

@ -8,7 +8,7 @@
#include "hca_decoder_clhca.h"
/* adx_decoder */
void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_bytes, coding_t coding_type);
void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_bytes, coding_t coding_type, uint32_t codec_config);
void adx_next_key(VGMSTREAMCHANNEL* stream);
@ -96,6 +96,7 @@ void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm24be(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm32le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
int32_t pcm24_bytes_to_samples(size_t bytes, int channels);
int32_t pcm16_bytes_to_samples(size_t bytes, int channels);
@ -588,6 +589,7 @@ void free_celt_fsb(celt_codec_data* data);
typedef struct speex_codec_data speex_codec_data;
speex_codec_data* init_speex_ea(int channels);
speex_codec_data* init_speex_torus(int channels);
void decode_speex(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do);
void reset_speex(speex_codec_data* data);
void seek_speex(VGMSTREAM* vgmstream, int32_t num_sample);

View file

@ -238,11 +238,26 @@ void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspaci
}
}
void decode_pcm32le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t offset = stream->offset + i * 0x04;
int32_t v = read_s32le(offset, stream->streamfile);
outbuf[sample_count] = (v >> 16);
}
}
int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) {
if (channels <= 0 || bits_per_sample <= 0) return 0;
return ((int64_t)bytes * 8) / channels / bits_per_sample;
}
int32_t pcm32_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 32);
}
int32_t pcm24_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 24);
}

View file

@ -10,15 +10,19 @@
#define SPEEX_DECODE_OK 0 /* -1 for end of stream, -2 corrupt stream */
typedef enum { EA, TORUS } type_t;
/* opaque struct */
struct speex_codec_data {
type_t type;
/* config */
int channels;
int samples_discard;
int encoder_delay;
uint8_t buf[SPEEX_MAX_FRAME_SIZE];
uint8_t frame_size;
int frame_size;
int16_t* samples;
int frame_samples;
@ -32,7 +36,7 @@ struct speex_codec_data {
/* raw SPEEX */
speex_codec_data* init_speex_ea(int channels) {
static speex_codec_data* init_speex(type_t type, int channels) {
int res, sample_rate;
speex_codec_data* data = NULL;
@ -40,7 +44,9 @@ speex_codec_data* init_speex_ea(int channels) {
data = calloc(1, sizeof(speex_codec_data));
if (!data) goto fail;
//TODO: EA uses N decoders, unknown layout (known samples are mono)
data->type = type;
//TODO: unknown layout (known samples are mono, EA: N decoders, Torus: N too?)
data->channels = channels;
if (channels != 1)
goto fail;
@ -78,6 +84,14 @@ fail:
return NULL;
}
speex_codec_data* init_speex_ea(int channels) {
return init_speex(EA, channels);
}
speex_codec_data* init_speex_torus(int channels) {
return init_speex(TORUS, channels);
}
static int decode_frame(speex_codec_data* data) {
int res;
@ -102,8 +116,18 @@ fail:
static int read_frame(speex_codec_data* data, VGMSTREAMCHANNEL* stream) {
size_t bytes;
switch(data->type) {
case EA:
data->frame_size = read_u8(stream->offset, stream->streamfile);
stream->offset += 0x01;
break;
case TORUS:
data->frame_size = read_u16le(stream->offset, stream->streamfile);
stream->offset += 0x02;
break;
default:
break;
}
if (data->frame_size == 0) goto fail;
bytes = read_streamfile(data->buf, stream->offset, data->frame_size, stream->streamfile);

View file

@ -16,11 +16,6 @@ static const int scale_step_capcom[8] = {
58982, 58982, 58982, 58982, 78643, 104858, 131072, 157286,
};
/* look-up for 'mul' IMA's sign*((code&7) * 2 + 1) for every code */
static const int scale_delta[16] = {
1, 3, 5, 7, 9, 11, 13, 15,
-1, -3, -5, -7, -9,-11,-13,-15
};
/* Yamaha ADPCM-B (aka DELTA-T) expand used in YM2608/YM2610/etc (cross referenced with various sources and .so) */
static void yamaha_adpcmb_expand_nibble(uint8_t byte, int shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) {
@ -43,14 +38,22 @@ static void yamaha_adpcmb_expand_nibble(uint8_t byte, int shift, int32_t* hist1,
}
/* Yamaha AICA expand, slightly filtered vs "ACM" Yamaha ADPCM, same as Creative ADPCM
* (some info from https://github.com/vgmrips/vgmplay, https://wiki.multimedia.cx/index.php/Creative_ADPCM) */
static void yamaha_aica_expand_nibble(uint8_t byte, int shift, int32_t* hist1, int32_t* step_size, int16_t *out_sample) {
* (some info from https://github.com/superctr/adpcm/blob/master/ymz_codec.c, https://wiki.multimedia.cx/index.php/Creative_ADPCM) */
static void yamaha_aica_expand_nibble(uint8_t byte, int shift, int16_t* hist1, int32_t* step_size, int16_t *out_sample) {
int code, delta, sample;
*hist1 = *hist1 * 254 / 256; /* hist filter is vital to get correct waveform but not done in many emus */
*hist1 = *hist1 * 254 / 256; /* hist filter seems used but may not be needed? (clamping delta is enough?)*/
code = (byte >> shift) & 0xf;
delta = (*step_size * scale_delta[code]) / 8; /* 'mul' IMA with table (not sure if part of encoder) */
delta = ((((code & 0x7) * 2) + 1) * (*step_size)) >> 3; /* like 'mul' IMA */
/* supposedly from official encoder but possibly all YM chips do this,
* matters in some games to avoid random glitches (early/buggy encoders?), ex. GTA2 */
if (delta > 32767)
delta = 32767;
if (code & 8)
delta = -delta;
sample = *hist1 + delta;
sample = clamp16(sample); /* apparently done by official encoder */
@ -112,7 +115,7 @@ static void yamaha_capcom_expand_nibble(uint8_t byte, int shift, int32_t* hist1,
void decode_aica(VGMSTREAMCHANNEL * stream, sample_t * 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;
int16_t out_sample;
int32_t hist1 = stream->adpcm_history1_16;
int16_t hist1 = stream->adpcm_history1_16;
int step_size = stream->adpcm_step_index;
/* no header (external setup), pre-clamp for wrong values */

View file

@ -189,6 +189,7 @@ static const char* extension_list[] = {
"fda",
"ffw",
"filp",
"fish",
//"flac", //common
"flx",
"fsb",
@ -204,10 +205,11 @@ static const char* extension_list[] = {
"gcw",
"genh",
"gin",
"gmd", //txth/semi [High Voltage games: Charlie and the Chocolate Factory (GC), Zathura (GC)]
"gms",
"grn",
"gsb",
"gsf",
"gsp",
"gtd",
"gwm",
@ -217,7 +219,6 @@ static const char* extension_list[] = {
"hd3",
"hdr",
"hdt",
"hgc1",
"his",
"hps",
"hsf",
@ -326,7 +327,6 @@ static const char* extension_list[] = {
"mab",
"mad",
"map",
"matx",
"mc3",
"mca",
"mcadpcm",
@ -500,8 +500,6 @@ static const char* extension_list[] = {
"sgb",
"sgd",
"sgt",
"sgx",
"sl3",
"slb", //txth/reserved [THE Nekomura no Hitobito (PS2)]
"sli",
"smc",
@ -562,10 +560,10 @@ static const char* extension_list[] = {
"tmx",
"tra",
"trk",
"trs", //txth/semi [Kamiwaza (PS2), Shinobido (PS2)]
"tun",
"txth",
"txtp",
"tydsp",
"u0",
"ue4opus",
@ -653,6 +651,7 @@ static const char* extension_list[] = {
"xa",
"xa2",
"xa30",
"xai",
"xag", //txth/reserved [Tamsoft's PS2 games]
"xau",
"xav",
@ -769,6 +768,7 @@ static const coding_info coding_info_list[] = {
{coding_PCMFLOAT, "32-bit float PCM"},
{coding_PCM24LE, "24-bit Little Endian PCM"},
{coding_PCM24BE, "24-bit Big Endian PCM"},
{coding_PCM32LE, "32-bit Little Endian PCM"},
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
{coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM (fixed coefficients)"},
@ -932,7 +932,6 @@ static const layout_info layout_info_list[] = {
{layout_blocked_xvas, "blocked (.xvas)"},
{layout_blocked_str_snds, "blocked (.str SNDS)"},
{layout_blocked_ws_aud, "blocked (Westwood Studios .aud)"},
{layout_blocked_matx, "blocked (Matrix .matx)"},
{layout_blocked_dec, "blocked (DEC)"},
{layout_blocked_vs, "blocked (Melbourne House VS)"},
{layout_blocked_mul, "blocked (MUL)"},
@ -966,16 +965,16 @@ static const meta_info meta_info_list[] = {
{meta_SILENCE, "Silence"},
{meta_RSTM, "Nintendo RSTM header"},
{meta_STRM, "Nintendo STRM header"},
{meta_ADX_03, "CRI ADX header type 03"},
{meta_ADX_04, "CRI ADX header type 04"},
{meta_ADX_05, "CRI ADX header type 05"},
{meta_ADX_03, "CRI ADX header (type 03)"},
{meta_ADX_04, "CRI ADX header (type 04)"},
{meta_ADX_05, "CRI ADX header (type 05)"},
{meta_AIX, "CRI AIX header"},
{meta_AAX, "CRI AAX header"},
{meta_UTF_DSP, "CRI ADPCM_WII header"},
{meta_AGSC, "Retro Studios AGSC header"},
{meta_CSMP, "Retro Studios CSMP header"},
{meta_RFRM, "Retro Studios RFRM header"},
{meta_DTK, "Nintendo DTK raw header"},
{meta_DTK, "Nintendo .DTK raw header"},
{meta_RSF, "Retro Studios .RSF raw header"},
{meta_AFC, "Nintendo .AFC header"},
{meta_AST, "Nintendo .AST header"},
@ -1016,7 +1015,7 @@ static const meta_info meta_info_list[] = {
{meta_PWB, "Double Fine WB header"},
{meta_RAW_WAVM, "Xbox .wavm raw header"},
{meta_DSP_STR, "Cauldron .STR header"},
{meta_EA_SCHL, "Electronic Arts SCHl header (variable)"},
{meta_EA_SCHL, "Electronic Arts SCHl header"},
{meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"},
{meta_CAF, "tri-Crescendo CAF Header"},
{meta_VPK, "SCE America VPK Header"},
@ -1025,19 +1024,19 @@ static const meta_info meta_info_list[] = {
{meta_SADL, "Procyon Studio SADL header"},
{meta_PS2_BMDX, "Beatmania .bmdx header"},
{meta_DSP_WSI, "Alone in the Dark .WSI header"},
{meta_AIFC, "Apple AIFF-C (Audio Interchange File Format) header"},
{meta_AIFF, "Apple AIFF (Audio Interchange File Format) header"},
{meta_AIFC, "Apple AIFF-C header"},
{meta_AIFF, "Apple AIFF header"},
{meta_STR_SNDS, "3DO SNDS header"},
{meta_WS_AUD, "Westwood Studios .AUD header"},
{meta_PS2_IVB, "IVB/BVII header"},
{meta_SVS, "Square SVS header"},
{meta_RIFF_WAVE, "RIFF WAVE header"},
{meta_RIFF_WAVE_POS, "RIFF WAVE header and .pos for looping"},
{meta_RIFF_WAVE_POS, "RIFF WAVE header (.pos looping)"},
{meta_NWA, "VisualArt's NWA header"},
{meta_NWA_NWAINFOINI, "VisualArt's NWA header (NWAINFO.INI looping)"},
{meta_NWA_GAMEEXEINI, "VisualArt's NWA header (Gameexe.ini looping)"},
{meta_XSS, "Dino Crisis 3 XSS File"},
{meta_HGC1, "Knights of the Temple 2 hgC1 Header"},
{meta_HGC1, "Cauldron HGC1 header"},
{meta_AUS, "Capcom AUS Header"},
{meta_RWS, "RenderWare RWS header"},
{meta_EA_1SNH, "Electronic Arts 1SNh header"},
@ -1053,37 +1052,35 @@ static const meta_info meta_info_list[] = {
{meta_PS2_XA30, "Reflections XA30 PS2 header"},
{meta_MUSC, "Krome MUSC header"},
{meta_MUSX, "Eurocom MUSX header"},
{meta_FILP, "Bio Hazard - Gun Survivor FILp Header"},
{meta_FILP, "cavia FILp Header"},
{meta_IKM, "MiCROViSiON IKM header"},
{meta_STER, "ALCHEMY STER header"},
{meta_SAT_DVI, "Konami KCEN DVI. header"},
{meta_DC_KCEY, "Konami KCEY KCEYCOMP header"},
{meta_BG00, "Falcom BG00 Header"},
{meta_SAT_DVI, "Konami DVI. header"},
{meta_DC_KCEY, "Konami KCEY header"},
{meta_BG00, "Cave BG00 header"},
{meta_RSTM_ROCKSTAR, "Rockstar Games RSTM Header"},
{meta_ACM, "InterPlay ACM Header"},
{meta_MUS_ACM, "InterPlay MUS ACM header"},
{meta_PS2_KCES, "Konami KCES Header"},
{meta_HXD, "Tecmo HXD Header"},
{meta_VSV, "Square Enix .vsv Header"},
{meta_RIFF_WAVE_labl, "RIFF WAVE header with loop markers"},
{meta_RIFF_WAVE_smpl, "RIFF WAVE header with sample looping info"},
{meta_RIFF_WAVE_wsmp, "RIFF WAVE header with wsmp looping info"},
{meta_RIFF_WAVE_labl, "RIFF WAVE header (labl looping)"},
{meta_RIFF_WAVE_smpl, "RIFF WAVE header (smpl looping)"},
{meta_RIFF_WAVE_wsmp, "RIFF WAVE header (wsmp looping)"},
{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_RIFX_WAVE_smpl, "RIFX WAVE header (smpl looping)"},
{meta_XNB, "Microsoft XNA Game Studio header"},
{meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"},
{meta_PS2_PCM, "Konami KCEJ East .PCM header"},
{meta_PS2_PCM, "Konami .PCM header"},
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV PS2 header"},
{meta_PS2_VAS, "Konami .VAS header"},
{meta_LP_AP_LEP, "Konami LP/AP/LEP header"},
{meta_SDT, "High Voltage .sdt header"},
{meta_NGC_TYDSP, ".tydsp Header"},
{meta_WVS, "Swingin' Ape .WVS header"},
{meta_XBOX_MATX, "assumed Matrix file by .matx extension"},
{meta_DEC, "Falcom DEC RIFF header"},
{meta_DEC, "Falcom .DEC RIFF header"},
{meta_VS, "Melbourne House .VS header"},
{meta_DC_STR, "Sega Stream Asset Builder header"},
{meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"},
{meta_STR_SEGA, "Sega Stream Asset Builder header"},
{meta_STR_SEGA_custom, "Sega Stream Asset Builder header (custom)"},
{meta_XMU, "Outrage XMU header"},
{meta_XVAS, "Konami .XVAS header"},
{meta_XA2_ACCLAIM, "Acclaim .XA2 Header"},
@ -1093,7 +1090,7 @@ static const meta_info meta_info_list[] = {
{meta_YMF, "Yuke's .YMF Header"},
{meta_FAG, "Radical .FAG Header"},
{meta_PS2_MIHB, "Sony MultiStream MIC header"},
{meta_DSP_WII_MUS, "mus header"},
{meta_MUS_KROME, "Krome .MUS header"},
{meta_WII_SNG, "SNG DSP Header"},
{meta_RSD, "Radical RSD header"},
{meta_DC_ASD, "ASD Header"},
@ -1112,7 +1109,7 @@ static const meta_info meta_info_list[] = {
{meta_GCA, "GCA DSP Header"},
{meta_SPT_SPD, "SPT+SPD DSP Header"},
{meta_ISH_ISD, "ISH+ISD DSP Header"},
{meta_GSP_GSB, "Tecmo GSP+GSB Header"},
{meta_GSND, "Tecmo GSND Header"},
{meta_YDSP, "Yuke's YDSP Header"},
{meta_NGC_SSM, "SSM DSP Header"},
{meta_PS2_JOE, "Asobo Studio .JOE header"},
@ -1125,7 +1122,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_P2BT, "Pop'n'Music 7 Header"},
{meta_PS2_GBTS, "Pop'n'Music 9 Header"},
{meta_NGC_DSP_IADP, "IADP Header"},
{meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"},
{meta_RIFF_WAVE_MWV, "RIFF WAVE header (ctrl looping)"},
{meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"},
{meta_SAT_BAKA, "Konami BAKA header"},
{meta_SWAV, "Nintendo SWAV header"},
@ -1155,7 +1152,7 @@ static const meta_info meta_info_list[] = {
{meta_SAB, "Sensaura SAB header"},
{meta_MAXIS_XA, "Maxis XA Header"},
{meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"},
{meta_WII_BNS, "Nintendo BNS header"},
{meta_BNS, "Nintendo BNS header"},
{meta_WII_WAS, "Sumo Digital iSWS header"},
{meta_XBOX_HLWAV, "Half-Life 2 .WAV header"},
{meta_MYSPD, "Punchers Impact .MYSPD header"},
@ -1168,7 +1165,7 @@ static const meta_info meta_info_list[] = {
{meta_NGC_DSP_AAAP, "Acclaim Austin AAAp DSP header"},
{meta_NGC_DSP_KONAMI, "Konami DSP header"},
{meta_BNSF, "Namco Bandai BNSF header"},
{meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"},
{meta_WB, "Triangle Service .WB header"},
{meta_S14, "Namco .S14 raw header"},
{meta_SSS, "Namco .SSS raw header"},
{meta_PS2_GCM, "Namco GCM header"},
@ -1183,7 +1180,6 @@ static const meta_info meta_info_list[] = {
{meta_DSP_STR_IG, "Infogrames .DSP header"},
{meta_EA_SWVR, "Electronic Arts SWVR header"},
{meta_PS2_B1S, "B1S header"},
{meta_PS2_WAD, "WAD header"},
{meta_DSP_XIII, "XIII dsp header"},
{meta_DSP_CABELAS, "Cabelas games .DSP header"},
{meta_PS2_ADM, "Dragon Quest V .ADM raw header"},
@ -1233,7 +1229,7 @@ static const meta_info meta_info_list[] = {
{meta_KT_WIIBGM, "Koei Tecmo WiiBGM Header"},
{meta_KTSS, "Koei Tecmo KTSS header"},
{meta_IDSP_NAMCO, "Namco IDSP header"},
{meta_WIIU_BTSND, "Nintendo Wii U Menu Boot Sound"},
{meta_BTSND, "Nintendo Wii U Menu Boot Sound header"},
{meta_MCA, "Capcom MCA header"},
{meta_ADX_MONSTER, "Monster Games .ADX header"},
{meta_HCA, "CRI HCA header"},
@ -1248,7 +1244,7 @@ static const meta_info meta_info_list[] = {
{meta_ASTB, "Capcom ASTB header"},
{meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"},
{meta_UBI_RAKI, "Ubisoft RAKI header"},
{meta_SXD, "Sony SXD header"},
{meta_SNDX, "Sony SNDX header"},
{meta_OGL, "Shin'en OGL header"},
{meta_MC3, "Paradigm MC3 header"},
{meta_GHS, "Hexadrive GHS/S_P_STH header"},
@ -1409,13 +1405,16 @@ static const meta_info meta_info_list[] = {
{meta_SSPF, "Konami SSPF header"},
{meta_S3V, "Konami S3V header"},
{meta_ESF, "Eurocom ESF header"},
{meta_ADM3, "Crankcase ADM3 header"},
{meta_ADM, "Crankcase ADMx header"},
{meta_TT_AD, "Traveller's Tales AUDIO_DATA header"},
{meta_SNDZ, "Sony SNDZ header"},
{meta_VAB, "Sony VAB header"},
{meta_BIGRP, "Inti Creates .BIGRP header"},
{meta_DIC1, "Codemasters DIC1 header"},
{meta_AWD, "RenderWare Audio Wave Dictionary header"},
{meta_SQUEAKSTREAM, "Torus SqueakStream header"},
{meta_SQUEAKSAMPLE, "Torus SqueakSample header"},
{meta_SNDS, "Sony SNDS header"},
};
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {

View file

@ -123,9 +123,6 @@ void block_update(off_t block_offset, VGMSTREAM* vgmstream) {
case layout_blocked_ws_aud:
block_update_ws_aud(block_offset,vgmstream);
break;
case layout_blocked_matx:
block_update_matx(block_offset,vgmstream);
break;
case layout_blocked_dec:
block_update_dec(block_offset,vgmstream);
break;

View file

@ -1,18 +0,0 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void block_update_matx(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 = vgmstream->current_block_offset + vgmstream->current_block_size + 8;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + 8;
}
}

View file

@ -20,7 +20,6 @@ void block_update_caf(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_wsi(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_str_snds(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ws_aud(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_matx(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_dec(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vs(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_mul(off_t block_offset, VGMSTREAM* vgmstream);

View file

@ -0,0 +1,219 @@
#include "meta.h"
#include "../coding/coding.h"
typedef struct {
int total_subsongs;
int target_subsong;
int version;
uint32_t stream_offset;
uint32_t stream_size;
int loop_flag;
int sample_rate;
int channels;
int32_t num_samples;
} adm_header_t;
static int parse_adm(adm_header_t* adm, STREAMFILE* sf);
static VGMSTREAM* init_vgmstream_adm(STREAMFILE* sf, int version);
/* ADM2 - Crankcase Audio REV plugin file [The Grand Tour Game (PC)] */
VGMSTREAM* init_vgmstream_adm2(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00,sf, "ADM2"))
return NULL;
if (!check_extensions(sf, "wem"))
return NULL;
return init_vgmstream_adm(sf, 2);
}
/* ADM3 - Crankcase Audio REV plugin file [Cyberpunk 2077 (PC), MotoGP 21 (PC)] */
VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00,sf, "ADM3"))
return NULL;
if (!check_extensions(sf, "wem"))
return NULL;
return init_vgmstream_adm(sf, 3);
}
static VGMSTREAM* init_vgmstream_adm(STREAMFILE* sf, int version) {
VGMSTREAM* vgmstream = NULL;
adm_header_t adm = {0};
/* ADMx are files used with the Wwise Crankaudio plugin, that simulate engine noises with
* base internal samples and some internal RPM config (probably). Actual file seems to
* define some combo of samples, this only plays those separate samples.
* Decoder is basically Apple's IMA (internally just "ADPCMDecoder") but transforms to float
* each sample during decode by multiplying by 0.000030518509 */
adm.target_subsong = sf->stream_index;
if (adm.target_subsong == 0) adm.target_subsong = 1;
adm.version = version;
if (!parse_adm(&adm, sf))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(adm.channels, adm.loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_ADM;
vgmstream->sample_rate = adm.sample_rate;
vgmstream->num_samples = adm.num_samples; /* slightly lower than bytes-to-samples */
vgmstream->num_streams = adm.total_subsongs;
vgmstream->stream_size = adm.stream_size;
vgmstream->coding_type = coding_APPLE_IMA4;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x22;
if (!vgmstream_open_stream(vgmstream, sf, adm.stream_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
static int parse_type(adm_header_t* adm, STREAMFILE* sf, uint32_t offset) {
/* ADM2 chunks */
if (is_id32be(offset, sf, "GRN1")) {
/* 0x74: offset to floats? */
offset = read_u32le(offset + 0x78, sf); /* to SMP1 */
if (!parse_type(adm, sf, offset))
goto fail;
}
else if (is_id32be(offset, sf, "SMP1")) {
adm->total_subsongs++;
if (adm->target_subsong == adm->total_subsongs) {
/* 0x04 always 0 */
/* 0x08 version? (0x00030000) */
adm->channels = read_u16le(offset + 0x0c, sf);
/* 0x0e 0x0001? */
/* 0x10 header size (0x2c) */
adm->sample_rate = read_s32le(offset + 0x14, sf);
adm->num_samples = read_s32le(offset + 0x18, sf);
adm->stream_size = read_u32le(offset + 0x1c, sf);
adm->stream_offset = read_u32le(offset + 0x20, sf);
/* rest: null */
VGM_LOG("so=%x %x\n", adm->stream_size, adm->stream_offset);
}
}
/* ADM3 chunks */
else if (is_id32be(offset, sf, "RMP1")) {
offset = read_u32le(offset + 0x1c, sf);
if (!parse_type(adm, sf, offset))
goto fail;
/* 0x24: offset to GRN1 */
}
else if (is_id32be(offset, sf, "SMB1")) {
uint32_t table_count = read_u32le(offset + 0x10, sf);
uint32_t table_offset = read_u32le(offset + 0x18, sf);
int i;
for (i = 0; i < table_count; i++) {
uint32_t smp2_unk = read_u32le(table_offset + i * 0x08 + 0x00, sf);
uint32_t smp2_offset = read_u32le(table_offset + i * 0x08 + 0x04, sf);
if (smp2_unk != 1)
goto fail;
if (!parse_type(adm, sf, smp2_offset)) /* SMP2 */
goto fail;
}
}
else if (is_id32be(offset, sf, "SMP2")) {
adm->total_subsongs++;
if (adm->target_subsong == adm->total_subsongs) {
/* 0x04 always 0 */
/* 0x08 version? (0x00040000) */
adm->channels = read_u32le(offset + 0x0c, sf); /* usually 4, with different sounds*/
/* 0x10 float pitch? */
/* 0x14 int pitch? */
/* 0x18 0x0001? */
/* 0x1a header size (0x30) */
adm->sample_rate = read_s32le(offset + 0x1c, sf);
adm->num_samples = read_s32le(offset + 0x20, sf);
adm->stream_size = read_u32le(offset + 0x24, sf);
/* 0x28 1? */
adm->stream_offset = read_u32le(offset + 0x2c, sf);
}
}
else {
VGM_LOG("ADM: unknown at %x\n", offset);
goto fail;
}
return 1;
fail:
return 0;
}
static int parse_adm(adm_header_t* adm, STREAMFILE* sf) {
uint32_t offset;
/* 0x04: null */
/* 0x08: version? (ADM2: 0x00050000, ADM3: 0x00060000) */
/* 0x0c: header size */
/* 0x10: data start */
/* rest unknown, looks mostly the same between files (some floats and stuff) */
switch(adm->version) {
case 2:
/* low to high */
offset = read_u32le(0x104, sf);
if (!parse_type(adm, sf, offset)) goto fail; /* GRN1 */
/* high to low */
offset = read_u32le(0x108, sf);
if (!parse_type(adm, sf, offset)) goto fail; /* GRN1 */
/* idle engine */
offset = read_u32le(0x10c, sf);
if (!parse_type(adm, sf, offset)) goto fail; /* SMP1 */
break;
case 3:
/* higher ramp, N samples from low to high */
offset = read_u32le(0x0FC, sf);
if (!parse_type(adm, sf, offset)) goto fail; /* RMP1 */
if (read_u32le(0x100, sf) != 1) goto fail;
/* lower ramp, also N samples */
offset = read_u32le(0x104, sf);
if (!parse_type(adm, sf, offset)) goto fail; /* RMP1 */
if (read_u32le(0x108, sf) != 1) goto fail;
/* idle engine */
offset = read_u32le(0x10c, sf);
if (!parse_type(adm, sf, offset)) goto fail; /* SMP2 */
if (read_u32le(0x110, sf) != 1) goto fail;
break;
default:
goto fail;
}
if (adm->target_subsong < 0 || adm->target_subsong > adm->total_subsongs || adm->total_subsongs < 1)
goto fail;
return 1;
fail:
return 0;
}

View file

@ -1,152 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
typedef struct {
int total_subsongs;
int target_subsong;
uint32_t stream_offset;
uint32_t stream_size;
int loop_flag;
int sample_rate;
int channels;
int32_t num_samples;
} adm3_header_t;
static int parse_adm3(adm3_header_t* adm3, STREAMFILE* sf);
/* ADM3 - Crankcase Audio REV plugin file [Cyberpunk 2077 (PC), MotoGP 21 (PC)] */
VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
adm3_header_t adm3 = {0};
/* checks */
if (!is_id32be(0x00,sf, "ADM3"))
goto fail;
if (!check_extensions(sf, "wem"))
goto fail;
adm3.target_subsong = sf->stream_index;
if (adm3.target_subsong == 0) adm3.target_subsong = 1;
/* ADM3 are files used with the Wwise Crankaudio plugin, that simulate engine noises with
* base internal samples and some internal RPM config (probably). Actual file seems to
* define some combo of samples, this only plays those separate samples.
* Decoder is basically Apple's IMA (internally just "ADPCMDecoder") but transforms to float
* each sample during decode by multiplying by 0.000030518509 */
if (!parse_adm3(&adm3, sf))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(adm3.channels, adm3.loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_ADM3;
vgmstream->sample_rate = adm3.sample_rate;
vgmstream->num_samples = adm3.num_samples; /* slightly lower than bytes-to-samples */
vgmstream->num_streams = adm3.total_subsongs;
vgmstream->stream_size = adm3.stream_size;
vgmstream->coding_type = coding_APPLE_IMA4;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x22;
if (!vgmstream_open_stream(vgmstream, sf, adm3.stream_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
static int parse_type(adm3_header_t* adm3, STREAMFILE* sf, uint32_t offset) {
if (is_id32be(offset, sf, "RMP1")) {
offset = read_u32le(offset + 0x1c, sf);
if (!parse_type(adm3, sf, offset))
goto fail;
/* 0x24: offset to GRN1 */
}
else if (is_id32be(offset, sf, "SMB1")) {
uint32_t table_count = read_u32le(offset + 0x10, sf);
uint32_t table_offset = read_u32le(offset + 0x18, sf);
int i;
for (i = 0; i < table_count; i++) {
uint32_t smp2_unk = read_u32le(table_offset + i * 0x08 + 0x00, sf);
uint32_t smp2_offset = read_u32le(table_offset + i * 0x08 + 0x04, sf);
if (smp2_unk != 1)
goto fail;
if (!parse_type(adm3, sf, smp2_offset)) /* SMP2 */
goto fail;
}
}
else if (is_id32be(offset, sf, "SMP2")) {
adm3->total_subsongs++;
if (adm3->target_subsong == adm3->total_subsongs) {
/* 0x04 always 0 */
/* 0x08 always 0x00040000 */
adm3->channels = read_u32le(offset + 0x0c, sf);
/* 0x10 float pitch? */
/* 0x14 int pitch? */
/* 0x18 0x0001? */
/* 0x1a 0x0030? (header size?) */
adm3->sample_rate = read_s32le(offset + 0x1c, sf);
adm3->num_samples = read_s32le(offset + 0x20, sf);
adm3->stream_size = read_u32le(offset + 0x24, sf);
/* 0x28 1? */
adm3->stream_offset = read_u32le(offset + 0x2c, sf);
}
}
else {
VGM_LOG("ADM3: unknown at %x\n", offset);
goto fail;
}
return 1;
fail:
return 0;
}
static int parse_adm3(adm3_header_t* adm3, STREAMFILE* sf) {
uint32_t offset;
/* 0x04: null */
/* 0x08: version? */
/* 0x0c: header size */
/* 0x10: data start */
/* rest unknown, looks mostly the same between files */
/* higher ramp, N samples from low to high */
offset = read_u32le(0x0FC, sf);
if (!parse_type(adm3, sf, offset)) goto fail; /* RMP1 */
if (read_u32le(0x100, sf) != 1) goto fail;
/* lower ramp, also N samples */
offset = read_u32le(0x104, sf);
if (!parse_type(adm3, sf, offset)) goto fail; /* RMP1 */
if (read_u32le(0x108, sf) != 1) goto fail;
/* idle engine */
offset = read_u32le(0x10c, sf);
if (!parse_type(adm3, sf, offset)) goto fail; /* SMP2 */
if (read_u32le(0x110, sf) != 1) goto fail;
if (adm3->target_subsong < 0 || adm3->target_subsong > adm3->total_subsongs || adm3->total_subsongs < 1)
goto fail;
return 1;
fail:
return 0;
}

View file

@ -183,6 +183,7 @@ VGMSTREAM* init_vgmstream_adx_subkey(STREAMFILE* sf, uint16_t subkey) {
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->codec_config = version;
vgmstream->coding_type = coding_type;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = frame_size;

View file

@ -0,0 +1,46 @@
#include "meta.h"
#include "../coding/coding.h"
/* BG00 - from Cave games [Ibara (PS2), Mushihime-sama (PS2)] */
VGMSTREAM* init_vgmstream_bg00(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset;
int channels, loop_flag = 0;
/* check */
if (!is_id32be(0x00,sf, "BG00"))
return NULL;
/* .bg00: header ID (no filenames or debug strings) */
if (!check_extensions(sf,"bg00"))
return NULL;
if (!is_id32be(0x40,sf, "VAGp"))
return NULL;
if (!is_id32be(0x70,sf, "VAGp"))
return NULL;
loop_flag = 0; /* flag at 0x08? loop points seem external */
channels = 2; /* mono files use regular VAG */
start_offset = 0x800;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_BG00;
vgmstream->sample_rate = read_s32be(0x80,sf);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,sf), 1);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x10,sf);
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
#include "../util.h"
/* BNS - Wii "Banner Sound" disc jingle */
VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) {
VGMSTREAM* init_vgmstream_bns(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t bns_offset;
uint32_t info_offset = 0, data_offset = 0;
@ -15,7 +15,7 @@ VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) {
/* .bin: actual extension
* .bns: header id */
if (!check_extensions(sf, "bin,lbin,bns"))
goto fail;
return NULL;
bns_offset = 0;
if (is_id32be(bns_offset + 0x40, sf, "IMET")) {
@ -32,9 +32,9 @@ VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) {
}
if (!is_id32be(bns_offset + 0x00,sf, "BNS "))
goto fail;
return NULL;
if (read_u32be(bns_offset + 0x04,sf) != 0xFEFF0100u)
goto fail;
return NULL;
/* find chunks */
{
@ -110,7 +110,7 @@ VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) {
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_WII_BNS;
vgmstream->meta_type = meta_BNS;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = sample_count;
vgmstream->loop_start_sample = loop_start;

View file

@ -11,30 +11,37 @@ VGMSTREAM* init_vgmstream_btsnd(STREAMFILE* sf) {
/* checks */
if (!check_extensions(sf, "btsnd"))
goto fail;
return NULL;
if (read_u32be(0x00,sf) != 0x02)
goto fail;
uint32_t type = read_u32be(0x00,sf);
if (type == 0x00) {
loop_flag = 0;
}
else if (type == 0x02) {
loop_flag = 1;
}
else {
return NULL;
}
loop_start = read_s32be(0x04, sf);
loop_start = read_s32be(0x04, sf); /* non-looping: 0 or some number lower than samples */
start_offset = 0x08;
channels = 2;
loop_flag = loop_start > 0;
/* extra check since format is so simple */
/* extra checks since format is so simple */
data_size = get_streamfile_size(sf);
num_samples = pcm16_bytes_to_samples(data_size - start_offset, channels);
if (loop_start >= num_samples)
goto fail;
return NULL;
if (num_samples > 960000) /* known max reached by various games, encoder/Wii U limit? */
return NULL;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_WIIU_BTSND;
vgmstream->meta_type = meta_BTSND;
vgmstream->sample_rate = 48000;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;

View file

@ -1,165 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
/* SEGA Stream Asset Builder...
this meta handles only V1 and V3... */
VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int interleave;
int channel_count;
int samples;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0xD5,streamFile) != 0x53656761) /* "Sega" */
goto fail;
interleave = read_32bitLE(0xC,streamFile);
if ((get_streamfile_size(streamFile)-0x800) != (read_32bitLE(0x10,streamFile) *
((read_32bitLE(0x0,streamFile)*(read_32bitLE(0x18,streamFile))))*interleave))
goto fail;
loop_flag = 0; /* (read_32bitLE(0x00,streamFile)!=0x00000000); */
samples = read_32bitLE(0x08,streamFile);
channel_count = (read_32bitLE(0x0,streamFile))*(read_32bitLE(0x18,streamFile));
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
switch (samples) {
case 4:
vgmstream->coding_type = coding_AICA_int;
vgmstream->num_samples = read_32bitLE(0x14,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile);
}
break;
case 16:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = read_32bitLE(0x14,streamFile)/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile)/2/channel_count;
}
break;
default:
goto fail;
}
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
if (vgmstream->channels == 1) {
vgmstream->layout_type = layout_none;
} else if (vgmstream->channels > 1) {
vgmstream->interleave_block_size = interleave;
vgmstream->layout_type = layout_interleave;
}
vgmstream->meta_type = meta_DC_STR;
/* 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;
}
/* This handles V2, not sure if it is really V2, cause the header is always
the same, not like in V1 and V3, only found in "102 Dalmatians - Puppies to the Rescue"
until now... */
VGMSTREAM * init_vgmstream_dc_str_v2(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("str",filename_extension(filename))) goto fail;
/* check header */
if ((read_32bitLE(0x00,streamFile) != 0x2))
goto fail;
if ((read_32bitLE(0x10,streamFile) != 0x10000))
goto fail;
if ((read_32bitLE(0x1C,streamFile) != 0x1F))
goto fail;
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 = read_32bitLE(0x4,streamFile);
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)/2/channel_count;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0xC,streamFile);
vgmstream->meta_type = meta_DC_STR_V2;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -0,0 +1,55 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* FILp - from Resident Evil: Dead Aim (PS2) */
VGMSTREAM* init_vgmstream_filp(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset;
int channels, loop_flag;
/* checks */
if (!is_id32be(0x00,sf, "FILp"))
return NULL;
/* .fil: extension in bigfile */
if (!check_extensions(sf,"fil"))
return NULL;
channels = read_s32le(0x04,sf); /* stereo only though */
if (read_32bitLE(0x0C,sf) != get_streamfile_size(sf))
goto fail;
loop_flag = (read_u32le(0x34,sf) == 0x00); /* 00/01/02 */
if (!is_id32be(0x100,sf, "VAGp"))
return NULL;
if (!is_id32be(0x130,sf, "VAGp"))
return NULL;
start_offset = 0x00; /* multiple FILp blocks pasted together (each including VAGps, but their sizes refer to the whole thing) */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_FILP;
vgmstream->sample_rate = read_s32le(0x110,sf);
vgmstream->num_samples = ps_bytes_to_samples(read_u32le(0x10C,sf), 1); /* channel size for the whole stream */
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_blocked_filp;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
block_update(start_offset, vgmstream);
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -18,12 +18,12 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00,sf, "RIFF"))
goto fail;
return NULL;
if (!is_id32be(0x08,sf, "FEV "))
goto fail;
return NULL;
if (!check_extensions(sf, "bank"))
goto fail;
return NULL;
version = read_u32le(0x14,sf); /* newer FEV have some kind of sub-version at 0x18 */
@ -102,8 +102,10 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) {
off_t fsb5_offset = read_u32le(bank_offset + 0x04 + entry_size*i + 0x00,sf);
size_t fsb5_size = read_u32le(bank_offset+0x08 + entry_size*i,sf);
int fsb5_subsongs = get_subsongs(sf, fsb5_offset, fsb5_size);
if (!fsb5_subsongs)
if (!fsb5_subsongs) {
vgm_logi("FSB: couldn't load bank (encrypted?)\n");
goto fail;
}
/* target in range */
if (target_subsong >= total_subsongs + 1 && target_subsong < total_subsongs + 1 + fsb5_subsongs) {
@ -140,7 +142,10 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) {
vgmstream = (read_u32be(0x00, temp_sf) == 0x46534235) ? /* "FSB5" (better flag?)*/
init_vgmstream_fsb5(temp_sf) :
init_vgmstream_fsb_encrypted(temp_sf);
if (!vgmstream) goto fail;
if (!vgmstream) {
vgm_logi("FSB: couldn't load bank (encrypted?)\n");
goto fail;
}
vgmstream->stream_index = sf->stream_index; //target_subsong; /* 0-index matters */
vgmstream->num_streams = total_subsongs;

View file

@ -58,6 +58,7 @@ static const fsbkey_info fsbkey_list[] = {
{ MODE_FSB4_ALT, FSBKEY_ADD("truck/impact/carbody") },// Monster Jam (PS2) [FSB3]
{ MODE_FSB4_ALT, FSBKEY_ADD("\xFC\xF9\xE4\xB3\xF5\x57\x5C\xA5\xAC\x13\xEC\x4A\x43\x19\x58\xEB\x4E\xF3\x84\x0B\x8B\x78\xFA\xFD\xBB\x18\x46\x7E\x31\xFB\xD0") }, // Guitar Hero 5 (X360)
{ MODE_FSB4_ALT, FSBKEY_ADD("\x8C\xFA\xF3\x14\xB1\x53\xDA\xAB\x2B\x82\x6B\xD5\x55\x16\xCF\x01\x90\x20\x28\x14\xB1\x53\xD8") }, // Guitar Hero: Metallica (X360)
{ MODE_FSB4_STD, FSBKEY_ADD("\xd2\x37\x70\x39\xa9\x86\xc5\xaf\x5b\x7f\xa2\x23\x98\x7e\xb6\xc2\x7e\x18\x7b\x2d\xd9\x31\x4b\x20\xb0\xc1\x8d\x06\xf2\xa7\xcd") }, // Guitar Hero: Metallica (PS3) [FSB4]
{ MODE_FSB5_STD, FSBKEY_ADD("G0KTrWjS9syqF7vVD6RaVXlFD91gMgkC") }, // Sekiro: Shadows Die Twice (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("BasicEncryptionKey") }, // SCP: Unity (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("FXnTffGJ9LS855Gc") }, // Worms Rumble Beta (PC)
@ -71,6 +72,7 @@ static const fsbkey_info fsbkey_list[] = {
{ MODE_FSB5_STD, FSBKEY_ADD("281ad163160cfc16f9a22c6755a64fad") }, // Ash Echoes beta (Android)
{ MODE_FSB5_STD, FSBKEY_ADD("Aurogon666") }, // Afterimage demo (PC)
{ MODE_FSB5_STD, FSBKEY_ADD("IfYouLikeThosesSoundsWhyNotRenumerateTheir2Authors?") }, // Blanc (PC/Switch)
{ MODE_FSB5_STD, FSBKEY_ADD("L36nshM520") }, // Nishuihan Mobile (Android)
};
static const int fsbkey_list_count = sizeof(fsbkey_list) / sizeof(fsbkey_list[0]);

View file

@ -4,55 +4,55 @@
#include "../util/chunks.h"
/* GSP+GSB - from Tecmo's Super Swing Golf 1 & 2 (Wii), Quantum Theory (PS3/X360) */
VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
VGMSTREAM* init_vgmstream_gsnd(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_head = NULL;
STREAMFILE* sb = NULL;
int loop_flag, channel_count, sample_rate, num_samples, loop_start, loop_end;
off_t start_offset, chunk_offset, first_offset;
size_t data_size;
int codec;
/* checks */
if (!check_extensions(sf,"gsb"))
if (!is_id32be(0x00,sf, "GSND"))
goto fail;
sf_head = open_streamfile_by_ext(sf, "gsp");
if (!sf_head) goto fail;
if (!is_id32be(0x00,sf_head, "GSND"))
if (!check_extensions(sf,"gsp"))
goto fail;
sb = open_streamfile_by_ext(sf, "gsb");
if (!sb) goto fail;
/* 0x04: version? */
/* 0x08: 1? */
/* 0x0c: 0? */
first_offset = read_32bitBE(0x10,sf_head); /* usually 0x14 */
first_offset = read_32bitBE(0x10,sf); /* usually 0x14 */
if (!find_chunk_be(sf_head, 0x48454144,first_offset,1, &chunk_offset,NULL)) /* "HEAD" */
if (!find_chunk_be(sf, get_id32be("HEAD"),first_offset,1, &chunk_offset,NULL))
goto fail;
/* 0x00: header size */
/* 0x04: num_chunks */
if (!find_chunk_be(sf_head, 0x44415441,first_offset,1, &chunk_offset,NULL)) /* "DATA" */
if (!find_chunk_be(sf, get_id32be("DATA"),first_offset,1, &chunk_offset,NULL))
goto fail;
data_size = read_32bitBE(chunk_offset + 0x00,sf_head);
codec = read_32bitBE(chunk_offset + 0x04,sf_head);
sample_rate = read_32bitBE(chunk_offset + 0x08,sf_head);
data_size = read_32bitBE(chunk_offset + 0x00,sf);
codec = read_32bitBE(chunk_offset + 0x04,sf);
sample_rate = read_32bitBE(chunk_offset + 0x08,sf);
/* 0x0c: always 16? */
channel_count = read_16bitBE(chunk_offset + 0x0e,sf_head);
channel_count = read_16bitBE(chunk_offset + 0x0e,sf);
/* 0x10: always 0? */
num_samples = read_32bitBE(chunk_offset + 0x14,sf_head);
num_samples = read_32bitBE(chunk_offset + 0x14,sf);
/* 0x18: always 0? */
/* 0x1c: unk (varies with codec_id) */
if (!find_chunk_be(sf_head, 0x42534943,first_offset,1, &chunk_offset,NULL)) /* "BSIC" */
if (!find_chunk_be(sf, get_id32be("BSIC"),first_offset,1, &chunk_offset,NULL))
goto fail;
/* 0x00/0x04: probably volume/pan/etc floats (1.0) */
/* 0x08: null? */
loop_flag = read_8bit(chunk_offset+0x0c,sf_head);
loop_start = read_32bitBE(chunk_offset+0x10,sf_head);
loop_end = read_32bitBE(chunk_offset+0x14,sf_head);
loop_flag = read_8bit(chunk_offset+0x0c,sf);
loop_start = read_32bitBE(chunk_offset+0x10,sf);
loop_end = read_32bitBE(chunk_offset+0x14,sf);
//if (!find_chunk_be(streamHeader, 0x4E414D45,first_offset,1, &chunk_offset,NULL)) /* "NAME" */
//if (!find_chunk_be(streamHeader, get_id32be("NAME"),first_offset,1, &chunk_offset,NULL))
// goto fail;
/* 0x00: name_size */
/* 0x04+: name (same as filename) */
@ -65,7 +65,7 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_GSP_GSB;
vgmstream->meta_type = meta_GSND;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
@ -80,16 +80,16 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_gsb;
if (!find_chunk_be(sf_head, 0x47434558,first_offset,1, &chunk_offset,NULL)) /* "GCEX" */
if (!find_chunk_be(sf, get_id32be("GCEX"),first_offset,1, &chunk_offset,NULL))
goto fail;
//vgmstream->current_block_size = read_32bitBE(chunk_offset+0x00,streamHeader);
block_header_size = read_32bitBE(chunk_offset+0x04,sf_head);
num_blocks = read_32bitBE(chunk_offset+0x08,sf_head);
block_header_size = read_32bitBE(chunk_offset+0x04,sf);
num_blocks = read_32bitBE(chunk_offset+0x08,sf);
vgmstream->num_samples = (data_size - block_header_size * num_blocks) / 8 / vgmstream->channels * 14;
/* 0x0c+: unk */
dsp_read_coefs_be(vgmstream, sf_head, chunk_offset+0x18, 0x30);
dsp_read_coefs_be(vgmstream, sf, chunk_offset+0x18, 0x30);
break;
}
#ifdef VGM_USE_FFMPEG
@ -101,7 +101,7 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay;
/* fix num_samples as header samples seem to be modified to match altered (49999/48001) sample rates somehow */
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sb, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -112,18 +112,18 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
break;
}
case 0x09: { /* XMA2 [Quantum Theory (PS3)] */
if (!find_chunk_be(sf_head, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
case 0x09: { /* XMA2 [Quantum Theory (X360)] */
if (!find_chunk_be(sf, get_id32be("XMEX"),first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
goto fail;
/* 0x00: fmt0x166 header (BE) */
/* 0x34: seek table */
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf_head, sf, start_offset, data_size, chunk_offset, 0x34);
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf, sb, start_offset, data_size, chunk_offset, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */
xma_fix_raw_samples(vgmstream, sb, start_offset,data_size, 0, 0,0); /* samples are ok */
break;
}
#endif
@ -132,13 +132,13 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
if (!vgmstream_open_stream(vgmstream, sb, start_offset))
goto fail;
close_streamfile(sf_head);
close_streamfile(sb);
return vgmstream;
fail:
close_streamfile(sf_head);
close_streamfile(sb);
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -424,6 +424,9 @@ static const hcakey_info hcakey_list[] = {
{0xc4276ffaee4aadec}, //music_0000005
{0x683d739be9679e61}, //music_0000006
{0xa3adc531c32bb128}, //music_0000007
{0xbb8f42a806d1fa6}, //music_0000008
{0xfd6e5a721921d936}, //music_0000009
{0x7749847207a5f0da}, //music_0000010
{0x52d065d9ccdb8696}, //music_0110001
{0xba26e58923a5da5d}, //music_0110002
{0x5b877af6e52af19b}, //music_0110003
@ -454,6 +457,7 @@ static const hcakey_info hcakey_list[] = {
{0x22c6b455883b1c28}, //music_0110030
{0xff2ae68fa067f80a}, //music_0110031
{0x422ca19b0fa5c7c0}, //music_0110032
{0x3b11592a696da747}, //music_0110033
{0xfb647d074e53fab6}, //music_0120001
{0xc24049b9f7ed3105}, //music_0120002
{0xdc128f2fd48bf4b}, //music_0120003
@ -495,6 +499,7 @@ static const hcakey_info hcakey_list[] = {
{0xe38b758bcadfc621}, //music_0210018
{0x3399e970670db2ba}, //music_0210019
{0x1cb76530af356c05}, //music_0210020
{0x2ae40b627c7125d7}, //music_0210021
{0x15bb78c31db0a0b6}, //music_0220001
{0x59b1257242c40109}, //music_0220002
{0xdb402bd08d522f34}, //music_0220003
@ -576,6 +581,7 @@ static const hcakey_info hcakey_list[] = {
{0x685b5601a43b6c60}, //music_0410018
{0x75927596a180f3e3}, //music_0410019
{0xc3d36676d54255c5}, //music_0410020
{0x41283c6f06db3cdd}, //music_0410021
{0x5d1f3fdbbb036f8d}, //music_0420001
{0xc04264e8f34ad5c0}, //music_0420002
{0x8f0e96b4f71f724f}, //music_0420003
@ -615,6 +621,8 @@ static const hcakey_info hcakey_list[] = {
{0xb069a5c5e2d93edf}, //music_0510019
{0x30f9dcefa450733a}, //music_0510020
{0xf85695960e2dcb7f}, //music_0510021
{0x212604f36a4ddb0c}, //music_0510022
{0xef7ee9169b194770}, //music_0510023
{0x15f82c1617013c36}, //music_0520001
{0xc7da8e6f0e2fe399}, //music_0520002
{0xe350bffcdc9cb686}, //music_0520003
@ -655,6 +663,8 @@ static const hcakey_info hcakey_list[] = {
{0x7aece54359beac21}, //music_0610021
{0x7c9332be25e5c95a}, //music_0610022
{0x415eef25f84e8c2e}, //music_0610023
{0xfd2237157af70152}, //music_0610024
{0xf6c91cba66c3fe68}, //music_0610025
{0x8258ddd6a1d0849b}, //music_0620001
{0x1dd21a1244ca12f1}, //music_0620002
{0xfdec74b23d8b494b}, //music_0620003
@ -674,15 +684,23 @@ static const hcakey_info hcakey_list[] = {
{0x5c1195d8afcb1901}, //music_0620017
{0x1ad8db767d9ba4a7}, //music_0620018
{0x9bc820aa161b0f08}, //music_0620019
{0x85f26fa7befc2b5a}, //music_0810000
{0xd1df27a57399613e}, //music_0810001
{0xd37ec4cb304e16ae}, //music_0810002
{0x4582fedda6a62aa8}, //music_0810003
{0xb31ea911ea8aba81}, //music_0810004
{0x1e99d14d97ab82c5}, //music_0820001
{0x5bf7cefecda8bcb2}, //music_0820002
{0x9cf7ab0ccafa374e}, //music_0820003
{0x7a9e4b710716a8e2}, //music_0910000
{0x972b52f3dfaa387a}, //music_0910001
{0x407a4b6c3dcf2509}, //music_0910002
{0x838be1aa4dc372bb}, //music_0910003
{0xc03bac003c24471d}, //music_0910004
{0xf864df0abe22ec49}, //music_0910005
{0x4683c57919dbdeee}, //music_0920001
{0x126d0d20ad7f0401}, //music_0920002
{0x1652eb8bf3cea8f5}, //music_0920003
{0x2a47feac8dc3ca9c}, //music_3010001
{0x9ebbaf63ffe9d9ef}, //music_3010002
{0xe553dba6592293d8}, //music_3010003
@ -700,10 +718,16 @@ static const hcakey_info hcakey_list[] = {
{0x5e23d8a2488bc715}, //music_3010016
{0x198cc607e20dd264}, //music_3010017
{0x31a9ab25b5dff424}, //music_3010018
{0x86e823895bb0bec6}, //music_3010019
{0x17f53cfa841f41b5}, //music_3010020
{0x4992a33be3ba81dd}, //music_3010021
{0x86d0ab836f09a599}, //music_3010022
{0x2a5eefc1987bf7fb}, //music_3010023
{0x157f20b466d75228}, //music_3010024
{0x13cada13f45f432b}, //music_3010025
{0xe0f08378be17633b}, //music_3010026
{0xaf81e107cd20ba90}, //music_3010027
{0x4efe51d362dcb6b1}, //music_3010028
{0xfd3ea450350d666f}, //music_3020001
{0x5e91a3790c32e2b3}, //music_3020002
{0x358adfd1bbd3a95e}, //music_3020003
@ -719,11 +743,18 @@ static const hcakey_info hcakey_list[] = {
{0x3d01826fe053ddda}, //music_3020014
{0xa6a6426caed68f7c}, //music_3020015
{0x34cc16f635101f02}, //music_3020016
{0xc92c94fdc988b8fa}, //music_3020017
{0x4429ed54ca45a36d}, //music_3020018
{0xcc935f3ebbb7bb94}, //music_3020019
{0x4a1d57f0db140c12}, //music_3020020
{0x8ddea25a12f93099}, //music_3020022
{0xf754248dcd46287e}, //music_3020023
{0xa3c06ffa7775a274}, //music_3020024
{0x427be43aa233382c}, //music_3020025
{0x4ec96dd7db2adfd7}, //music_3020026
{0x9f12a5003f112aaa}, //music_3020028
{0x38edf73f19401e1c}, //music_3020030
{0xfa2c72797fa3e388}, //music_3020031
{0xdfad847a86a126bb}, //music_5030001
{0x711ef85045b8c26e}, //music_5030002
{0xff7640b46d72b337}, //music_5030003
@ -989,6 +1020,7 @@ static const hcakey_info hcakey_list[] = {
{0x1be3e8255dde31e3}, //music_5050147
{0x58b735f1a68c9a81}, //music_5050148
{0x5b3cb281d89019db}, //music_5050149
{0x74f39448d2b75d4d}, //music_5050150
{0x2b1a0269a3d890d4}, //music_5050151
{0x74e058fd628364c9}, //music_5050152
{0x3ade68d4857395c0}, //music_5050153
@ -1042,6 +1074,29 @@ static const hcakey_info hcakey_list[] = {
{0x929ca6a5e8e0445}, //music_5050206
{0xf0de6097ea78513c}, //music_5050207
{0xcde0de0e1216bdea}, //music_5050208
{0xb496e9301bfc57c4}, //music_5050209
{0xff4db63086831e8f}, //music_5050210
{0x21cd7a36d33daae9}, //music_5050211
{0x88fe1d5592979a66}, //music_5050212
{0x1782668d98097f3b}, //music_5050213
{0xb174215f3ed746e3}, //music_5050214
{0x445aa44e5029d76b}, //music_5050215
{0x39b3d29fc04211ed}, //music_5050216
{0x6856a8773f3e7712}, //music_5050217
{0x7f08330d7d971292}, //music_5050218
{0x6ac19245cd7e8de0}, //music_5050219
{0x7a0ed12fd8b5a9e8}, //music_5050220
{0xc13b8037e2be01bf}, //music_5050221
{0x5856576aa5c0a59f}, //music_5050222
{0xe8286a95b8f38dd1}, //music_5050223
{0x48015b291de44ff3}, //music_5050224
{0x4521644fd1682bc0}, //music_5050226
{0x808e307ec28b9ef0}, //music_5050227
{0x6a4493f6e7dcce6c}, //music_5050228
{0xd6bc23de632b00e0}, //music_5050229
{0x7268ea33e33cbcfa}, //music_5050230
{0x2de61d98bc2cea48}, //music_5050231
{0xd8bdb31ab72c355b}, //music_5050242
{0x52c250eade92393b}, //music_9010001
{0xf66e6bb5b0599b07}, //music_9010002
{0x8582b5a60dbbf948}, //music_9010003
@ -1187,6 +1242,18 @@ static const hcakey_info hcakey_list[] = {
// Disney Star Smash (Android)
{3941111674189632}, // 000E006B915C3740
// Final Fantasy VII: Ever Crisis (beta) (Android)
{19629307353822}, // 000011DA4DE45ADE
// Tower of Sky (Android)
{5893902754391672}, // 0014F0792C042678
// The Irregular at Magic High School: Reloaded Memory (Android)
{7181280307767738368}, // 63A9086451010000
// BlazBlue Entropy Effect (Early Access) (PC)
{29814655674508831}, // 0069EC457894661F
};
#endif/*_HCA_KEYS_H_*/

View file

@ -0,0 +1,41 @@
#include "meta.h"
#include "../coding/coding.h"
/* hgC1 - from Knights of the Temple 2 (PS2) */
VGMSTREAM* init_vgmstream_hgc1(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset;
int channels, loop_flag = 0;
/* checks */
if (!is_id32be(0x00,sf, "hgC1"))
return NULL;
if (!is_id32be(0x04,sf, "strm"))
return NULL;
if (!check_extensions(sf,"str"))
return NULL;
start_offset = 0x20;
loop_flag = 0;
channels = read_s32le(0x08,sf); /* always stereo? */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_HGC1;
vgmstream->sample_rate = read_s32le(0x10,sf);
vgmstream->num_samples = ps_bytes_to_samples(read_u32le(0x0C,sf) * 0x10, 1); /* mono frames*/
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -303,26 +303,30 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, offset, extra_offset;
size_t stream_size;
int loop_flag, channels, codec, sample_rate; //, block_size = 0, bps = 0;
int target_subsong = sf->stream_index, num_languages,
loop_flag, channels, codec, sample_rate; //, block_size = 0, bps = 0;
int32_t num_samples, loop_start = 0;
char language[0x10];
STREAMFILE* sb = NULL;
const char* suffix = NULL;
const char* extension = NULL;
/* checks */
if (!is_id32be(0x00,sf, "bsnf")) /* null-terminated string */
goto fail;
if (read_u32be(0x05, sf) != 0x00000100) /* version */
if (!is_id32be(0x00, sf, "bsnf"))
goto fail;
if (!check_extensions(sf, "bsnd"))
goto fail;
offset = 0x18;
num_languages = read_u32be(0x04, sf);
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > num_languages || num_languages < 1)
goto fail;
stream_size = read_u32be(offset + 0x00,sf);
offset = read_u32be(offset + 0x04,sf); /* absolute but typically right after this */
offset = 0x08 + (target_subsong - 1) * 0x18;
read_string(language, 0x10, offset + 0x00, sf);
stream_size = read_u32be(offset + 0x10, sf);
offset = read_u32be(offset + 0x14, sf); /* absolute but typically right after this */
/* 0x00: crc? */
/* 0x04: CBR samples or 0 if VBR */
@ -337,56 +341,49 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) {
//bps = read_u16le(offset + 0x22, sf);
extra_offset = offset + 0x24;
extension = "ogg"; /* same for all codecs */
switch(codec) {
case 0x0055: /* msf */
/* extra data per codec */
/* 0x0055 - msf */
/* 0x00: table entries */
/* 0x04: seek table, format: frame size (16b) + frame samples (16b) */
suffix = "_msf.bsnd";
break;
case 0x0166: /* xma */
/* 0x0166 - xma */
/* 0x00: extra size */
/* 0x02: xma config and block table */
suffix = "_xma.bsnd";
break;
case 0x674F: /* vorbis */
/* 0x674F - vorbis */
/* 0x00: extra size */
/* 0x02: num samples */
suffix = "_vorbis.bsnd";
goto fail; //untested
//break;
case 0x42D2: /* at9 */
/* 0x42D2 - at9 */
/* 0x00: extra size */
/* 0x02: encoder delay */
/* 0x04: channel config */
/* 0x08: ATRAC9 GUID */
/* 0x1c: ATRAC9 config */
suffix = "_at9.bsnd";
break;
default:
goto fail;
}
{
int suffix_len = strlen(suffix);
int filename_len;
char filename[PATH_LIMIT];
get_streamfile_basename(sf, filename, sizeof(filename));
get_streamfile_filename(sf, filename, sizeof(filename));
filename_len = strlen(filename);
if (filename_len < suffix_len)
goto fail;
filename[filename_len - suffix_len + 0] = '.';
filename[filename_len - suffix_len + 1] = '\0';
strcat(filename, extension);
if (language[0] != '\0') {
strcat(filename, "_");
strcat(filename, language);
}
sb = open_streamfile_by_filename(sf, filename);
if (!sb) goto fail;
if (!sb) {
if (language[0] != '\0') {
// fill missing languages with blanks
vgmstream = init_vgmstream_silence(channels, sample_rate, num_samples);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_BSNF;
vgmstream->num_streams = num_languages;
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s (missing)", language);
return vgmstream;
}
goto fail;
}
}
if (stream_size != get_streamfile_size(sb))
@ -395,7 +392,6 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) {
loop_flag = (loop_start > 0);
start_offset = 0x00;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
@ -405,6 +401,8 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) {
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = num_samples;
vgmstream->num_streams = num_languages;
strncpy(vgmstream->stream_name, language, STREAM_NAME_SIZE);
switch (codec) {
@ -429,7 +427,7 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) {
case 0x0166: {
int block_size = 0x800;
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, stream_size, num_samples, channels, sample_rate, block_size, 0);
vgmstream->codec_data = init_ffmpeg_xma2_raw(sb, start_offset, stream_size, num_samples, channels, sample_rate, block_size, 0);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View file

@ -1,6 +1,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
typedef struct {
int is_music;
@ -31,13 +32,13 @@ VGMSTREAM* init_vgmstream_ivaud(STREAMFILE* sf) {
int loop_flag;
/* checks */
/* (hashed filenames are likely extensionless and .ivaud is added by tools) */
/* (hashed filenames are likely extensionless, .ivaud is added by tools) */
if (!check_extensions(sf, "ivaud,"))
goto fail;
return NULL;
/* check header */
if (!parse_ivaud_header(sf, &ivaud))
goto fail;
return NULL;
loop_flag = 0;
@ -121,9 +122,9 @@ fail:
/* Parse Rockstar's .ivaud header (much info from SparkIV). */
static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) {
int target_subsong = sf->stream_index;
uint64_t (*read_u64)(off_t,STREAMFILE*);
uint32_t (*read_u32)(off_t,STREAMFILE*);
uint16_t (*read_u16)(off_t,STREAMFILE*);
read_u64_t read_u64;
read_u32_t read_u32;
read_u16_t read_u16;
ivaud->big_endian = read_u32be(0x00, sf) == 0; /* table offset at 0x04 > BE (64b) */
@ -131,6 +132,10 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) {
read_u32 = ivaud->big_endian ? read_u32be : read_u32le;
read_u16 = ivaud->big_endian ? read_u16be : read_u16le;
uint64_t table_offset = read_u64(0x00,sf);
if (table_offset > 0x10000) /* arbitrary max, typically 0x1c~0x1000 */
return 0;
/* use bank's stream count to detect */
ivaud->is_music = (read_u32(0x10,sf) == 0);
@ -138,7 +143,7 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) {
off_t block_table_offset, channel_table_offset, channel_info_offset;
/* music header */
block_table_offset = read_u64(0x00,sf);
block_table_offset = table_offset;
ivaud->block_count = read_u32(0x08,sf);
ivaud->block_size = read_u32(0x0c,sf); /* uses padded blocks */
/* 0x10(4): stream count */
@ -185,7 +190,7 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) {
off_t stream_table_offset, stream_info_offset, stream_entry_offset, offset;
/* bank header */
stream_table_offset = read_u64(0x00,sf);
stream_table_offset = table_offset;
/* 0x08(8): header size? start offset? */
ivaud->total_subsongs = read_u32(0x10,sf);
/* 0x14(4): unknown */

View file

@ -257,15 +257,11 @@ VGMSTREAM * init_vgmstream_sdt(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_aix(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_tydsp(STREAMFILE * streamFile);
VGMSTREAM* init_vgmstream_wvs_xbox(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_wvs_ngc(STREAMFILE* sf);
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_str_sega(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_str_sega_custom(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile);
@ -300,7 +296,7 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE * streamFile);
VGMSTREAM* init_vgmstream_mus_krome(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_rsd(STREAMFILE * streamFile);
@ -332,7 +328,7 @@ VGMSTREAM * init_vgmstream_ish_isd(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ydsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE * streamFile);
VGMSTREAM* init_vgmstream_gsnd(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ngc_ssm(STREAMFILE * streamFile);
@ -412,7 +408,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_exakt_sc(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_wii_bns(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_bns(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile);
@ -433,7 +429,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_konami(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_bnsf(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_wb(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_wb(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_raw_s14_sss(STREAMFILE* sf);
@ -455,8 +451,6 @@ VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_adm(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_lpcm_shade(STREAMFILE* sf);
@ -578,7 +572,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_pasx(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sndx(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile);
@ -959,6 +953,7 @@ VGMSTREAM* init_vgmstream_s3v(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_esf(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_adm2(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_tt_ad(STREAMFILE* sf);
@ -982,4 +977,9 @@ VGMSTREAM* init_vgmstream_rws_809(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_snds(STREAMFILE* sf);
#endif /*_META_H*/

View file

@ -0,0 +1,56 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* .mus - from Krome games [Ty: The Tasmanian Tiger 2 (GC), Star Wars: The Force Unleashed (Wii)] */
VGMSTREAM* init_vgmstream_mus_krome(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, data_size;
int channels, loop_flag, interleave;
int32_t num_samples;
/* checks */
num_samples = read_s32be(0x00,sf);
interleave = read_s32be(0x04,sf);
start_offset = read_u32be(0x08,sf);
data_size = read_u32be(0x0c,sf);
if (interleave != 0x8000)
return NULL;
if (start_offset != 0x80)
return NULL;
if (data_size + start_offset != get_streamfile_size(sf))
return NULL;
/* could test gain/initial ps at 0x10 + 0x20 too */
if (!check_extensions(sf,"mus"))
return NULL;
channels = 2;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_MUS_KROME;
vgmstream->num_samples = num_samples;
vgmstream->sample_rate = read_u16be(0x6c,sf);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave; /* no last block size unlike similar DSPs */
dsp_read_coefs_be(vgmstream, sf, 0x10, 0x2e);
dsp_read_hist_be(vgmstream, sf, 0x10 + 0x24, 0x2e);
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,72 +0,0 @@
#include "meta.h"
#include "../util.h"
/* TYDSP (Ty - The Tasmanian Tiger) */
VGMSTREAM * init_vgmstream_ngc_tydsp(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("tydsp",filename_extension(filename))) goto fail;
loop_flag = 1;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitBE(0x08,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = (uint16_t)(read_16bitBE(0x6C,streamFile));
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x00,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitBE(0x00,streamFile);
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile);
vgmstream->meta_type = meta_NGC_TYDSP;
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+i*2,streamFile);
}
if (vgmstream->channels) {
for (i=0;i<16;i++) {
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x3E +i*2,streamFile);
}
}
}
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -302,6 +302,34 @@ static int _init_vgmstream_ogg_vorbis_tests(STREAMFILE* sf, ogg_vorbis_io_config
return 1;
}
/* .fish: Wonder Boy: The Dragon's Trap (PC) */
if (read_u32be(0x00,sf) == 0x4E7C0F0E) {
/* init big-ish table on startup, based on original unrolled code (sub_7FF7670FD990) */
cfg->key_len = 0x400;
if (sizeof(cfg->key) < cfg->key_len)
goto fail;
for (int i = 0; i < 0x400 / 4; i++) {
uint32_t key = i;
for (int round = 0; round < 8; round++) {
uint32_t tmp1 = (key >> 1);
uint32_t tmp2 = -(key & 1) & 0xEDB88324;
key = tmp1 ^ tmp2;
}
if (key == 0)
key = 0xEDB88324;
put_u32le(cfg->key + (i ^ 0x2A) * 4, key);
}
cfg->is_encrypted = 1;
if (!check_extensions(sf,"fish"))
goto fail;
return 1;
}
/***************************************/
/* harder to check (could be improved) */
@ -614,6 +642,7 @@ static VGMSTREAM* _init_vgmstream_ogg_vorbis_config(STREAMFILE* sf, off_t start,
const char* comment = NULL;
while (ogg_vorbis_get_comment(data, &comment)) {
;VGM_LOG("OGG: user_comment=%s\n", comment);
if (strstr(comment,"loop_start=") == comment || /* Phantasy Star Online: Blue Burst (PC) (no loop_end pair) */
strstr(comment,"LOOP_START=") == comment || /* Phantasy Star Online: Blue Burst (PC), common */
@ -702,18 +731,26 @@ static VGMSTREAM* _init_vgmstream_ogg_vorbis_config(STREAMFILE* sf, off_t start,
force_seek = 1;
}
else if (strstr(comment,"COMMENT=*loopsample,") == comment) { /* Tsuki ni Yorisou Otome no Sahou (PC) */
int unk0; // always 0 (delay?)
int unk1; // always -1 (loop flag? but non-looped files have no comment)
int m = sscanf(comment,"COMMENT=*loopsample,%d,%d,%d,%d", &unk0, &loop_start, &loop_end, &unk1);
if (m == 4) {
loop_flag = 1;
loop_end_found = 1;
}
}
/* Hatsune Miku Project DIVA games, though only 'Arcade Future Tone' has >4ch files
* ENCODER tag is common but ogg_vorbis_encode looks unique enough
* (arcade ends with "2010-11-26" while consoles have "2011-02-07" */
if (strstr(comment, "ENCODER=ogg_vorbis_encode/") == comment) {
else if (strstr(comment, "ENCODER=ogg_vorbis_encode/") == comment) {
disable_reordering = 1;
}
if (strstr(comment, "TITLE=") == comment) {
else if (strstr(comment, "TITLE=") == comment) {
strncpy(name, comment + 6, sizeof(name) - 1);
}
;VGM_LOG("OGG: user_comment=%s\n", comment);
}
}

View file

@ -1,65 +0,0 @@
#include "meta.h"
#include "../util.h"
/* BG0 (from Ibara, Mushihimesama)
Note: Seems the Loop Infos are stored external... */
VGMSTREAM * init_vgmstream_bg00(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("bg00",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x42473030) /* "BG00" */
goto fail;
loop_flag = (read_32bitLE(0x08,streamFile)!=0);
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 = read_32bitBE(0x80,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitBE(0x4C,streamFile)*2)*28/16/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitBE(0x4C,streamFile)*2)*28/16/channel_count;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
vgmstream->meta_type = meta_BG00;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,67 +0,0 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* FILp (Resident Evil - Dead Aim) */
VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("filp",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x46494C70) /* "FILp" */
goto fail;
if (read_32bitBE(0x100,streamFile) != 0x56414770) /* "VAGp" */
goto fail;
if (read_32bitBE(0x130,streamFile) != 0x56414770) /* "VAGp" */
goto fail;
if (get_streamfile_size(streamFile) != read_32bitLE(0xC,streamFile))
goto fail;
loop_flag = (read_32bitLE(0x34,streamFile) == 0);
channel_count = read_32bitLE(0x4,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x0;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x110,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_blocked_filp;
vgmstream->meta_type = meta_FILP;
/* open the file for reading */
{
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;
}
}
block_update_filp(start_offset,vgmstream);
vgmstream->num_samples = read_32bitLE(0x10C,streamFile)/16*28;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,64 +0,0 @@
#include "meta.h"
#include "../util.h"
/* hgC1 (from Knights of the Temple 2) */
VGMSTREAM * init_vgmstream_hgc1(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("hgc1",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x68674331) /* "hgC1" */
goto fail;
loop_flag = 0;
channel_count = read_32bitLE(0x08,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x40;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)*32)/channel_count/16*28;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x0C,streamFile)*32)/channel_count/16*28;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_HGC1;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,45 +0,0 @@
#include "meta.h"
#include "../coding/coding.h"
/* SL3 - Atari Melbourne House games [ Test Drive Unlimited (PS2), Transformers (PS2)] */
VGMSTREAM * init_vgmstream_sl3(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count;
/* checks */
/* .ms: actual extension, sl3: header id */
if (!check_extensions(streamFile, "ms,sl3"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x534C3300) /* "SL3\0" */
goto fail;
loop_flag = 0;
channel_count = read_32bitLE(0x14,streamFile);
start_offset = 0x8000; /* also at 0x24? */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(streamFile)-start_offset,channel_count);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
}
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x20,streamFile);
vgmstream->meta_type = meta_SL3;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,71 +0,0 @@
#include "meta.h"
#include "../util.h"
/* WAD (from The golden Compass) */
VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag = 0;
int channel_count;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("wad",filename_extension(filename))) goto fail;
/* check header */
if ((read_32bitLE(0x00,streamFile)+0x40) != get_streamfile_size(streamFile))
goto fail;
loop_flag = 0;
channel_count = (uint16_t) read_16bitLE(0x4,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x40;
vgmstream->channels = channel_count;
vgmstream->sample_rate = (uint16_t) read_16bitLE(0x6,streamFile);;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x0,streamFile)/channel_count/16*28;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x0,streamFile)/channel_count/16*28;
}
if (channel_count == 1)
{
vgmstream->layout_type = layout_none;
}
else
{
goto fail;
}
vgmstream->meta_type = meta_PS2_WAD;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,64 +0,0 @@
#include "meta.h"
#include "../util.h"
/* WB (from Shooting Love. ~TRIZEAL~) */
VGMSTREAM * init_vgmstream_ps2_wb(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("wb",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0,streamFile) != 0x00000000)
goto fail;
loop_flag = read_32bitLE(0x4,streamFile);
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x10;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 48000;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = read_32bitLE(0xC,streamFile)/4;
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x4,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x8,streamFile);
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 2;
vgmstream->meta_type = meta_PS2_WB;
/* 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;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -146,6 +146,9 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
case 0x0001: /* PCM */
switch (fmt->bps) {
case 32:
fmt->coding_type = coding_PCM32LE;
break;
case 24: /* Omori (PC) */
fmt->coding_type = coding_PCM24LE;
break;
@ -177,6 +180,14 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
goto fail;
}
break;
case 0x003: /* floating point PCM */
if (fmt->bps == 32) {
fmt->coding_type = coding_PCMFLOAT;
} else {
goto fail;
}
fmt->interleave = fmt->block_size / fmt->channels;
break;
case 0x0011: /* MS-IMA ADPCM [Layton Brothers: Mystery Room (iOS/Android)] */
if (fmt->bps != 4) goto fail;
@ -701,9 +712,11 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
/* samples, codec init (after setting coding to ensure proper close on failure) */
switch (fmt.coding_type) {
case coding_PCM32LE:
case coding_PCM24LE:
case coding_PCM16LE:
case coding_PCM8_U:
case coding_PCMFLOAT:
vgmstream->num_samples = pcm_bytes_to_samples(data_size, fmt.channels, fmt.bps);
break;

View file

@ -216,6 +216,7 @@ VGMSTREAM* init_vgmstream_sdrh_old(STREAMFILE* sf) {
* 0x30: file name in a custom 40-char (RADIX style) encoding
* others: ? (change in old/new)
*/
/* there is also an older version in Shadow Hearts 2, more basic (no section table) and may contain sequences */
/* parse section */
{

View file

@ -3,16 +3,15 @@
#include "../util/chunks.h"
/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */
/* SGXD - Sony/SCEI's SGX lib (cousin of RXWS) */
VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_head = NULL;
STREAMFILE* sf_body = NULL;
off_t start_offset, data_offset, chunk_offset, name_offset = 0;
size_t stream_size;
uint32_t base1_offset, base2_offset, base3_offset;
int is_sgx, is_sgd = 0;
uint32_t /*base1_offset,*/ base2_offset, base3_offset;
int is_sgd = 0;
int loop_flag, channels, codec, sample_rate;
int32_t num_samples, loop_start_sample, loop_end_sample;
int total_subsongs, target_subsong = sf->stream_index;
@ -28,35 +27,31 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
}
if (!is_id32be(0x00,sf_head, "SGXD"))
goto fail;
return NULL;
/* checks */
/* .sgx: header+data (Genji)
* .sgd: header+data (common)
/* .sgd: header+data (common)
* .sgh+sgd: header+data (streams) */
if (!check_extensions(sf,"sgx,sgd,sgb"))
goto fail;
if (!check_extensions(sf,"sgd,sgb"))
return NULL;
/* SGXD base (size 0x10), always LE even on PS3 */
/* 0x04: SGX = full header size
SGD/SGH = bank name offset (part of NAME table, usually same as filename) */
/* 0x08: SGX = first chunk offset? (0x10)
SGD/SGH = full header size */
/* 0x0c: SGX/SGH = full data size with padding /
SGD = full data size ^ (1<<31) with padding */
base1_offset = read_u32le(0x04, sf_head);
/* 0x04: SGD/SGH = bank name offset (part of NAME table, usually same as filename) */
/* 0x08: SGD/SGH = full header size */
/* 0x0c: SGH = full data size with padding
* SGD = full data size ^ (1<<31) with padding */
//base1_offset = read_u32le(0x04, sf_head);
base2_offset = read_u32le(0x08, sf_head);
base3_offset = read_u32le(0x0c, sf_head);
is_sgx = base2_offset == 0x10; /* fixed size */
is_sgd = base3_offset & (1 << 31); /* flag */
/* Ogg SGXD don't have flag (probably due to codec hijack, or should be split), allow since it's not so obvious */
if (!(is_sgx || is_sgd) && get_streamfile_size(sf_head) != base2_offset) /* sgh but wrong header size must be sgd */
if (!(is_sgd) && get_streamfile_size(sf_head) != base2_offset) /* sgh but wrong header size must be sgd */
is_sgd = 1;
/* for plugins that start with .sgh (and don't check extensions) */
if (!(is_sgx || is_sgd) && sf == sf_head) {
if (!(is_sgd) && sf == sf_head) {
sf_body = open_streamfile_by_ext(sf, "sgb");
if (!sf_body) goto fail;
}
@ -65,9 +60,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
}
if (is_sgx) {
data_offset = base1_offset;
} else if (is_sgd) {
if (is_sgd) {
data_offset = base2_offset;
} else {
data_offset = 0x00;
@ -76,7 +69,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
/* Format per chunk:
* - 0x00: id
* - 0x04: SGX: unknown; SGD/SGH: chunk length
* - 0x04: chunk length
* - 0x08: null
* - 0x0c: entries */
@ -103,14 +96,8 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
* - BUSS: bus config? */
/* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */
if (is_sgx) { /* position after chunk+size */
if (!is_id32be(0x10,sf_head, "WAVE"))
goto fail;
chunk_offset = 0x18;
} else {
if (!find_chunk_le(sf_head, get_id32be("WAVE"),0x10,0, &chunk_offset, NULL))
goto fail;
}
/* check multi-streams (usually only SE containers; Puppeteer) */
total_subsongs = read_s32le(chunk_offset+0x04,sf_head);
@ -123,7 +110,6 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/
/* 0x00: ? (00/01/02) */
if (!is_sgx) /* meaning unknown in .sgx; offset 0 = not a stream (a RGND sample) */
name_offset = read_u32le(chunk_offset+0x04,sf_head);
codec = read_u8(chunk_offset+0x08,sf_head);
channels = read_u8(chunk_offset+0x09,sf_head);
@ -141,13 +127,9 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
loop_end_sample = read_s32le(chunk_offset+0x28,sf_head);
stream_size = read_u32le(chunk_offset+0x2c,sf_head); /* stream size (without padding) / interleave (for type3) */
if (is_sgx) {
stream_offset = 0x0;
} else{
stream_offset = read_u32le(chunk_offset+0x30,sf_head);
}
/* 0x34: SGX = unknown
* SGD/SGH = stream size (with padding) / interleave */
/* 0x34: SGD/SGH = stream size (with padding) / interleave */
loop_flag = loop_start_sample != -1 && loop_end_sample != -1;
start_offset = data_offset + stream_offset;

View file

@ -0,0 +1,41 @@
#include "meta.h"
#include "../coding/coding.h"
/* SL3 - Sirens Sound Library (Winky Soft / Atari Melbourne House) games [Test Drive Unlimited (PS2), Transformers 2003/2004 (PS2)] */
VGMSTREAM* init_vgmstream_sl3(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channels;
/* checks */
if (!is_id32be(0x00,sf, "SL3\0"))
goto fail;
/* .ms: actual extension */
if (!check_extensions(sf, "ms"))
goto fail;
loop_flag = 0;
channels = read_32bitLE(0x14,sf);
start_offset = 0x8000; /* also at 0x24? */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SL3;
vgmstream->sample_rate = read_32bitLE(0x18,sf);
vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(sf)-start_offset,channels);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x20,sf);
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -0,0 +1,112 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* SSDD - Sony/SCE's SNDS lib format (cousin of SGXD/SNDX) */
VGMSTREAM* init_vgmstream_snds(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t stream_offset, stream_size;
int loop_flag, channels, codec, sample_rate;
int32_t num_samples, loop_start, loop_end, encoder_delay;
uint32_t at9_config = 0;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!is_id32be(0x00, sf, "SSDD"))
return NULL;
if (read_u32le(0x04, sf) != get_streamfile_size(sf))
return NULL;
/* 0x10: file name */
/* (extensionless): no apparent extension in debug strings, though comparing other SCE libs possibly ".ssd" */
if (!check_extensions(sf,""))
return NULL;
/* from debug info seems to have free chunks but known files always use the same and 1 subsong */
off_t base_offset = 0x60, wavs_offset = 0;
if (!find_chunk_le(sf, get_id32be("WAVS"),base_offset,0, &wavs_offset,NULL))
return NULL;
if (read_u16le(wavs_offset + 0x00, sf) != 0x2c) /* entry size? */
return NULL;
total_subsongs = read_s16le(wavs_offset + 0x02, sf);
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) return NULL;
if (total_subsongs != 1) return NULL; /* not seen */
/* read stream header */
{
uint32_t head_offset = wavs_offset + 0x04 + 0x2c * (target_subsong - 1);
/* 0x00: null/flags? */
/* 0x04: null/offset? */
/* 0x0c: null/offset? */
codec = read_u8(head_offset + 0x0c, sf);
channels = read_u16le(head_offset + 0x0d, sf);
/* 0x0e: null? */
sample_rate = read_u32le(head_offset + 0x10, sf);
at9_config = read_u32le(head_offset + 0x14, sf); /* !!! (only known use of this lib is Android/iOS) */
num_samples = read_s32le(head_offset + 0x18, sf);
loop_start = read_s32le(head_offset + 0x1c, sf);
loop_end = read_s32le(head_offset + 0x20, sf);
encoder_delay = read_s32le(head_offset + 0x24, sf);
stream_size = read_u32le(head_offset + 0x28, sf);
loop_flag = loop_end > 0;
}
/* CUES chunk: cues (various fields, also names) */
/* CUNS chunk: cue names (flags + hash + offset, then names) */
off_t wavd_offset = 0;
if (!find_chunk_le(sf, get_id32be("WAVD"),wavs_offset - 0x08,0, &wavd_offset,NULL))
return NULL;
stream_offset = wavd_offset + 0x08;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SNDS;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size;
switch (codec) {
#ifdef VGM_USE_ATRAC9
case 0x41: {
atrac9_config cfg = {0};
cfg.channels = channels;
cfg.config_data = at9_config;
cfg.encoder_delay = encoder_delay;
vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none;
break;
}
#endif
default:
VGM_LOG("SNDS: unknown codec 0x%x\n", codec);
goto fail;
}
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream, sf, stream_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -3,8 +3,8 @@
#include "../util/chunks.h"
/* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */
VGMSTREAM* init_vgmstream_sxd(STREAMFILE* sf) {
/* SXDF/SXDS - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */
VGMSTREAM* init_vgmstream_sndx(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_sxd1 = NULL, *sf_sxd2 = NULL, *sf_data = NULL, *sf_h = NULL, *sf_b = NULL;
off_t start_offset, chunk_offset, first_offset = 0x60, name_offset = 0;
@ -180,7 +180,7 @@ VGMSTREAM* init_vgmstream_sxd(STREAMFILE* sf) {
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SXD;
vgmstream->meta_type = meta_SNDX;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;

View file

@ -11,27 +11,29 @@ VGMSTREAM* init_vgmstream_spsd(STREAMFILE *sf) {
/* checks */
if (!is_id32be(0x00,sf, "SPSD"))
goto fail;
return NULL;
/* .str: actual extension, rare [Shenmue (DC)]
* .spsd: header id (maybe real ext is .PSD, similar to "SMLT" > .MLT) */
if (!check_extensions(sf, "str,spsd"))
goto fail;
return NULL;
if (read_32bitBE(0x04,sf) != 0x01010004 && /* standard version */
read_32bitBE(0x04,sf) != 0x00010004) /* uncommon version [Crazy Taxi (Naomi)] */
goto fail;
if (read_u32be(0x04,sf) != 0x01010004 && /* standard version */
read_u32be(0x04,sf) != 0x00010004) /* uncommon version [Crazy Taxi (Naomi)] */
return NULL;
codec = read_8bit(0x08,sf);
flags = read_8bit(0x09,sf);
index = read_16bitLE(0x0a,sf);
data_size = read_32bitLE(0x0c,sf);
codec = read_u8(0x08,sf);
flags = read_u8(0x09,sf);
index = read_u16le(0x0a,sf);
data_size = read_u32le(0x0c,sf);
//if (data_size + start_offset != get_streamfile_size(streamFile))
// goto fail; /* some rips out there have incorrect padding */
/* At 0x30(4*ch) is some config per channel but doesn't seem to affect ADPCM (found with PCM too) */
//todo with 0x80 seems 0x2c is a loop_start_sample but must be adjusted to +1 block? (uncommon flag though)
loop_flag = (flags & 0x80);
channels = ((flags & 0x01) || (flags & 0x02)) ? 2 : 1; /* 0x02 is rare but looks normal (Virtua Tennis 2) */
channels = ((flags & 0x01) || (flags & 0x02)) ? 2 : 1; /* 0x02 is rare (Virtua Tennis 2) */
start_offset = 0x40;
@ -39,21 +41,21 @@ VGMSTREAM* init_vgmstream_spsd(STREAMFILE *sf) {
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,sf);
vgmstream->sample_rate = read_u16le(0x2A,sf);
vgmstream->meta_type = meta_SPSD;
switch (codec) {
case 0x00: /* [Virtua Tennis 2 (Naomi), Club Kart: European Session (Naomi)] */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = pcm_bytes_to_samples(data_size,channels,16);
vgmstream->loop_start_sample = read_32bitLE(0x2c,sf) + pcm_bytes_to_samples(0x2000*channels,channels,16);
vgmstream->num_samples = pcm16_bytes_to_samples(data_size, channels);
vgmstream->loop_start_sample = read_s32le(0x2c,sf) + pcm16_bytes_to_samples(0x2000,1);
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
case 0x01: /* [Virtua Tennis 2 (Naomi)] */
vgmstream->coding_type = coding_PCM8;
vgmstream->num_samples = pcm_bytes_to_samples(data_size,channels,8);
vgmstream->loop_start_sample = read_32bitLE(0x2c,sf) + pcm_bytes_to_samples(0x2000*channels,channels,8);
vgmstream->num_samples = pcm8_bytes_to_samples(data_size, channels);
vgmstream->loop_start_sample = read_s32le(0x2c,sf) + pcm8_bytes_to_samples(0x2000,1);
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
@ -61,7 +63,7 @@ VGMSTREAM* init_vgmstream_spsd(STREAMFILE *sf) {
case 0x03: /* standard */
vgmstream->coding_type = coding_AICA_int;
vgmstream->num_samples = yamaha_bytes_to_samples(data_size, channels);
vgmstream->loop_start_sample = /*read_32bitLE(0x2c,streamFile) +*/ yamaha_bytes_to_samples(0x2000*channels,channels);
vgmstream->loop_start_sample = /*read_s32le(0x2c,streamFile) +*/ yamaha_bytes_to_samples(0x2000,1);
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
@ -92,9 +94,6 @@ VGMSTREAM* init_vgmstream_spsd(STREAMFILE *sf) {
goto fail;
}
/* todo seems to decode slightly incorrectly in after certain data (loop section start?)
* may depend on values in 0x20 or 0x2c [ex. Marvel vs Capcom 2 (Naomi)]
* at 0x30(4*ch) is some config per channel but doesn't seem to affect ADPCM (found with PCM too) */
{
int i;
for (i = 0; i < channels; i++) {

View file

@ -0,0 +1,446 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "../util/layout_utils.h"
#define SQUEAK_MAX_CHANNELS 6 /* seen 3 in some voices */
typedef enum { PCM16LE, PCM16BE, PCM8, DSP, PSX, MSIMA, IMA, XMA2, VORBIS, SPEEX } squeak_type_t;
typedef struct {
squeak_type_t type;
int version;
int channels;
int codec;
int sample_rate;
uint32_t interleave;
uint32_t extb_offset;
uint32_t name_offset;
int32_t num_samples;
int32_t loop_start;
int32_t loop_end;
uint32_t data_offset;
uint32_t coef_offset;
uint32_t coef_spacing;
uint32_t data_offsets[SQUEAK_MAX_CHANNELS];
uint32_t coef_offsets[SQUEAK_MAX_CHANNELS];
uint32_t data_size;
bool big_endian;
bool external_info;
bool external_data;
bool stream;
} squeak_header_t;
static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h);
/* SqueakStream - from Torus games (name/engine as identified in .hnk subdirs) */
VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) {
squeak_header_t h = {0};
bool is_old = false;
/* checks */
if (is_id32be(0x00,sf, "RAWI") || is_id32be(0x00,sf, "VORB") || is_id32be(0x00,sf, "SPEX")) {
h.big_endian = false; /* VORB/SPEX only use vorbis/speex but no apparent diffs */
}
else if (is_id32be(0x00,sf, "IWAR")) {
h.big_endian = true; /* Wii/PS3/X360 */
}
else {
/* no header id in early version so test codec in dumb endian */
if ((read_u32le(0x00,sf) & 0x00FFFFFF) > 9 || (read_u32be(0x00,sf) & 0x00FFFFFF) > 9)
return NULL;
is_old = true;
h.big_endian = guess_endian32(0x04, sf);
}
if (get_streamfile_size(sf) > 0x1000) /* arbitrary max */
return NULL;
/* (extensionless): no known extension */
if (!check_extensions(sf,""))
return NULL;
read_s32_t read_s32 = h.big_endian ? read_s32be : read_s32le;
read_u32_t read_u32 = h.big_endian ? read_u32be : read_u32le;
/* base header (with extra checks for old version since format is a bit simple) */
if (!is_old) {
h.version = read_u8(0x04,sf);
if (h.version != 0x01) return NULL;
h.codec = read_u8(0x05,sf);
h.channels = read_u8(0x06,sf);
/* 07: null */
h.num_samples = read_s32(0x08, sf);
h.sample_rate = read_s32(0x0c, sf);
h.loop_start = read_s32(0x10, sf);
h.loop_end = read_s32(0x14, sf);
h.extb_offset = read_u32le(0x18, sf); /* LE! */
h.name_offset = read_u32le(0x1c, sf);
/* 20: null, unknown values (sometimes floats) */
h.interleave = read_u32(0x38, sf);
h.data_offset = 0; /* implicit... */
/* XX: extra values (may depend on codec/channels) */
/* XX: DSP coefs / fmt headers (optional) */
/* XX: extra table with offset to fmt headers / DSP coefs /etc (per channel) */
/* XX: asset name */
}
else {
h.codec = read_s32(0x00,sf);
if (h.codec > 0x09) return NULL;
h.channels = read_s32(0x04,sf);
if (h.channels > SQUEAK_MAX_CHANNELS) return NULL;
h.interleave = read_u32(0x08, sf);
if (h.interleave > 0xFFFFFF) return NULL;
h.loop_start = read_s32(0x0c, sf);
h.loop_end = read_s32(0x10, sf);
h.num_samples = read_s32(0x14, sf);
if (h.loop_start > h.loop_end || h.loop_end > h.num_samples) return NULL;
/* 18: float/value */
/* 1c: float/value */
/* 20: cue table entries (optional) */
/* 22: unknown */
/* 24: cues offset */
/* 26: cues flags */
h.extb_offset = read_u32le(0x28, sf); /* LE! */
h.name_offset = read_u32le(0x2c, sf);
h.data_offset = read_u32(0x30, sf); /* PS2 uses a few big .raw rather than separate per header */
/* XX: DSP coefs / fmt headers (optional) */
/* XX: cue table (00=null + 04=sample start per entry) */
/* XX: extra table (00=null + 00=sample rate, 04=samples, per channel) */
/* XX: asset name */
//sample_rate = ...; // read later after opening external info
/* not ideal but... */
if (h.data_offset && h.codec == 0x03) {
h.data_size = (h.num_samples / 28) * 0x10 * h.channels;
}
}
/* Wii streams uses a separate info file, check external flags */
/* (possibly every section may be separate or not but only seen all at once) */
h.stream = true;
h.external_info = (h.name_offset & 0xF0000000);
h.external_data = true;
h.name_offset = h.name_offset & 0x0FFFFFFF;
h.extb_offset = h.extb_offset & 0x0FFFFFFF;
if (h.extb_offset > h.name_offset) return NULL;
switch(h.codec) {
case 0x00: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */
case 0x01: h.type = PCM16LE; break; /* Falling Skies The Game (PC) */
case 0x02: h.type = h.big_endian ? PCM16BE : PCM16LE; break; /* Falling Skies The Game (X360)-be, Scooby Doo and the Spooky Swamp (PC)-le */
case 0x03: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */
case 0x04: h.type = MSIMA; break; /* Barbie Dreamhouse Party (DS) */
case 0x05: h.type = PCM8; break; /* Scooby Doo and the Spooky Swamp (DS), Scooby Doo! First Frights (DS) */
case 0x07: h.type = SPEEX; break; /* Scooby Doo and the Spooky Swamp (PC) */
case 0x08: h.type = VORBIS; break; /* Scooby Doo and the Spooky Swamp (PC) */
case 0x09: h.type = MSIMA; break; /* Turbo Super Stunt Squad (DS) */
default:
VGM_LOG("SqueakStream: unknown codec %x\n", h.codec);
return NULL;
}
return init_vgmstream_squeak_common(sf, &h);
}
/* SqueakSample - from Torus games (name/engine as identified in .hnk subdirs) */
VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) {
squeak_header_t h = {0};
/* checks */
if (read_u32le(0x00,sf) != 0x20 && read_u32le(0x00,sf) != 0x1c) /* even on BE */
return NULL;
//if (get_streamfile_size(sf) > 0x1000) /* not correct for non-external files */
// return NULL;
/* (extensionless): no known extension */
if (!check_extensions(sf,""))
return NULL;
h.big_endian = guess_endian32(0x04, sf);
read_s32_t read_s32 = h.big_endian ? read_s32be : read_s32le;
/* base header (with extra checks since format is a bit simple) */
uint32_t offset = read_u32le(0x00, sf); /* old versions use 0x1c, new 0x20, but otherwise don't look different */
h.channels = read_s32(0x04,sf);
if (h.channels > SQUEAK_MAX_CHANNELS) return NULL;
/* 04: float/value */
/* 0c: float/value */
/* 14: value? */
/* 18: value? (new) / 1 (old) */
/* 1c: 1? (new) / none (old) */
/* sample header per channel (separate fields but assumes all are repeated except offsets) */
h.num_samples = read_s32(offset + 0x00,sf);
h.data_offset = read_u32le(offset + 0x04,sf);
h.loop_start = read_s32(offset + 0x08,sf);
h.loop_end = read_s32(offset + 0x0c,sf);
if (h.loop_start > h.loop_end || h.loop_end > h.num_samples) return NULL;
h.codec = read_s32(offset + 0x10,sf);
h.sample_rate = read_s32(offset + 0x14,sf);
if (h.sample_rate > 48000 || h.sample_rate < 0) return NULL;
/* PCM has extended fields (0x68)*/
if (h.codec != 0xFFFE0001) {
/* 18: loop start offset? (not always) */
/* 1c: loop end offset? */
/* 20: data size? */
/* 24: data size? (new) / count? (old) */
h.coef_offset = read_u32le(offset + 0x28,sf);
}
/* DSP and old versions use a external .raw file (assumed extension) */
h.stream = false;
h.external_info = false;
h.external_data = (h.data_offset & 0xF0000000);
h.data_offset = h.data_offset & 0x0FFFFFFF;
/* each channel has its own info but mostly repeats (data may have padding, but files end with no padding) */
{
int separation = 0;
switch(h.codec) {
case 0xFFFE0001:
case 0x0001FFFE:
case 0x01660001: separation = 0x68; break;
default: separation = 0x2c; break;
}
for (int i = 0; i < h.channels; i++) {
h.data_offsets[i] = read_u32le(offset + 0x04 + i * separation, sf) & 0x0FFFFFFF;
h.coef_offsets[i] = read_u32le(offset + 0x28 + i * separation, sf);
}
if (h.channels > 1) {
h.interleave = h.data_offsets[1] - h.data_offsets[0];
h.coef_spacing = h.coef_offsets[1] - h.coef_offsets[0];
}
}
switch(h.codec) {
case 0x00: h.type = DSP; break; /* (same as below for unlooped audio) */
case 0x01: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS) */
case 0x06: /* (same as below for unlooped audio) */
case 0x07: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */
case 0x08: /* (same as below for unlooped audio) */
case 0x09: h.type = IMA; break; /* Scooby-Doo! First Frights (DS), Turbo Super Stunt Squad (DS) */
case 0xFFFE0001: h.type = PCM16BE; break; /* Falling Skies The Game (X360) */
case 0x0001FFFE: h.type = PCM16LE; break; /* Scooby Doo and the Spooky Swamp (PC), Monster High: New Ghoul in School (PC) */
case 0x01660001: h.type = XMA2; break; /* Rise of the Guardians (X360) */
default:
VGM_LOG("SqueakSample: unknown codec %x\n", h.codec);
return NULL;
}
return init_vgmstream_squeak_common(sf, &h);
}
static STREAMFILE* load_assets(STREAMFILE* sf, squeak_header_t* h) {
STREAMFILE* sb = NULL;
STREAMFILE* sn = NULL;
read_s32_t read_s32 = h->big_endian ? read_s32be : read_s32le;
char asset_name[0x20]; /* "(8-byte crc).raw", "xx(6-byte crc).raw", "(regular name).raw" */
if (h->external_info) {
sn = open_streamfile_by_ext(sf, "asset"); /* unknown real extension if any, based on debug strings */
if (!sn) {
vgm_logi("Squeak: external name '.asset' not found (put together)\n");
goto fail;
}
}
if (h->stream) {
if (h->version == 0) {
h->sample_rate = read_s32(h->extb_offset + 0x04, sn ? sn : sf); /* per channel, use first */
}
read_string(asset_name, sizeof(asset_name), h->name_offset, sn ? sn : sf);
/* extb_offset defines N coef offset per channel but in practice this seem fixed, simplify */
h->coef_offset = 0x40;
h->coef_spacing = 0x30;
}
/* try to open external data .raw in various ways, since this format is a bit hard to use */
if (h->stream) {
/* "(asset name)": plain as found */
if (!sb) {
sb = open_streamfile_by_filename(sf, asset_name);
}
/* "sound/(asset name)": most common way to store files */
char path_name[256];
snprintf(path_name, sizeof(path_name), "sound/%s", asset_name);
if (!sb) {
sb = open_streamfile_by_filename(sf, path_name);
}
}
/* "(header name).raw": for squeakstreams and renamed files */
if (!sb) {
sb = open_streamfile_by_ext(sf, "raw");
}
if (!sb) {
char* info = h->stream ? asset_name : "(filename).raw";
vgm_logi("Squeak: external file '%s' not found (put together)\n", info);
goto fail;
}
close_streamfile(sn);
return sb;
fail:
close_streamfile(sn);
return NULL;
}
static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sb = NULL;
STREAMFILE* sf_body = NULL;
/* common */
int loop_flag = h->loop_end > 0;
/* open external asset */
if (h->external_data) {
sb = load_assets(sf, h);
if (!sb) goto fail;
}
sf_body = sb ? sb : sf;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(h->channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = h->stream ? meta_SQUEAKSTREAM : meta_SQUEAKSAMPLE;
vgmstream->sample_rate = h->sample_rate;
vgmstream->num_samples = h->num_samples;
vgmstream->loop_start_sample = h->loop_start;
vgmstream->loop_end_sample = h->loop_end + 1;
vgmstream->stream_size = h->data_size;
switch(h->type) {
case DSP:
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = h->interleave;
//vgmstream->interleave_last_block_size = ...; /* apparently padded */
dsp_read_coefs(vgmstream, sf, h->coef_offset + 0x00, h->coef_spacing, h->big_endian);
dsp_read_hist (vgmstream, sf, h->coef_offset + 0x24, h->coef_spacing, h->big_endian);
break;
case PCM16LE:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = h->interleave; /* not 0x02 */
break;
case PCM16BE:
vgmstream->coding_type = coding_PCM16BE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = h->interleave; /* not 0x02 */
break;
case PSX:
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = h->interleave;
break;
case PCM8:
vgmstream->coding_type = coding_PCM8;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = h->interleave;
break;
case MSIMA:
vgmstream->coding_type = coding_MS_IMA;
vgmstream->layout_type = layout_none;
//vgmstream->interleave_block_size = h->interleave; /* unused? (mono) */
vgmstream->frame_size = h->codec == 0x04 ? 0x400 : 0x20;
break;
case IMA:
vgmstream->coding_type = coding_IMA;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = h->interleave;
/* possibly considered MS-IMA in a single block (not valid though), first 2 values maybe are adpcm hist */
h->data_offset += 0x04;
break;
#ifdef VGM_USE_FFMPEG
case XMA2: {
/* uses separate mono streams */
vgmstream->coding_type = coding_FFmpeg;
for (int i = 0; i < h->channels; i++) {
uint32_t offset = h->data_offsets[i];
uint32_t next_offset = (i + 1 == h->channels) ? get_streamfile_size(sf_body) : h->data_offsets[i+1];
uint32_t data_size = next_offset - offset;
int layer_channels = 1;
vgmstream->codec_data = init_ffmpeg_xma2_raw(sf_body, offset, data_size, h->num_samples, layer_channels, h->sample_rate, 0, 0);
if (!layered_add_codec(vgmstream, 0, layer_channels))
goto fail;
}
if (!layered_add_done(vgmstream))
goto fail;
break;
}
#endif
#ifdef VGM_USE_VORBIS
case VORBIS:
vgmstream->codec_data = init_ogg_vorbis(sf_body, h->data_offset, 0, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_OGG_VORBIS;
vgmstream->layout_type = layout_none;
break;
#endif
#ifdef VGM_USE_SPEEX
case SPEEX: {
vgmstream->codec_data = init_speex_torus(h->channels);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_SPEEX;
vgmstream->layout_type = layout_none;
break;
}
#endif
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream, sb ? sb : sf, h->data_offset))
goto fail;
close_streamfile(sb);
return vgmstream;
fail:
close_streamfile(sb);
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -0,0 +1,142 @@
#include "meta.h"
#include "../coding/coding.h"
/* .STR - Sega Dreamcast's "Audio64 AM (AICA Manager) driver" streams */
VGMSTREAM* init_vgmstream_str_sega(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset, data_size;
int loop_flag, channels, track_channels, tracks, sample_rate, bps, interleave, blocks;
/* checks */
tracks = read_u32le(0x00,sf);
if (tracks < 1 || tracks > 16) /* official limits */
return NULL;
/* "Sega Stream Asset Builder Revision ..." long text with program info, after header */
if (!is_id64be(0xD4,sf, "\0Sega St"))
return NULL;
if (!check_extensions(sf, "str"))
return NULL;
sample_rate = read_s32le(0x04,sf);
bps = read_u32le(0x08,sf);
interleave = read_s32le(0x0C,sf); /* multiples of 0x800 (sector size) */
blocks = read_s32le(0x10,sf); /* interruptsTillEnd, "how may irqs until the end of that tracks data" AKA interleaved blocks */
/* per track info (channels must be the same per track, and data_size may be inaccurate for other tracks) */
data_size = read_u32le(0x14,sf);
track_channels = read_s32le(0x18,sf); /* max 2 for AICA, N for PCM */
/* 0x08: blocks / interruptsTillEnd (not including padding) */
/* header track data reserved up to max 16 * 0x0c = 0xC0 + 0x18 = 0xD4 */
/* after track headers there may be one phantom entry with empty data/channels but repeated interruptsTillEnd (bug?) */
channels = track_channels * tracks;
loop_flag = 0; /* no loop info */
start_offset = 0x800;
/* all tracks/data is padded */
if (blocks * channels * interleave != get_streamfile_size(sf) - start_offset)
goto fail;
/* streams start with a "leadIn" silence that defaults to 2 blocks, but it's configurable */
//start_offset += (interleave * channels) * 2;
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_STR_SEGA;
vgmstream->sample_rate = sample_rate;
switch (bps) {
case 4: /* common [GTA2 (DC)] */
vgmstream->coding_type = coding_AICA_int;
vgmstream->num_samples = yamaha_bytes_to_samples(data_size, track_channels);
for (int i = 0; i < channels; i++) {
vgmstream->ch[i].adpcm_step_index = 0x7f;
}
break;
case 8: /* not seen (encoder only) */
vgmstream->coding_type = coding_PCM8_U;
vgmstream->num_samples = pcm8_bytes_to_samples(data_size, track_channels);
break;
case 16: /* common [San Francisco Rush 2049 (DC)] */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = pcm16_bytes_to_samples(data_size, track_channels);
break;
default:
goto fail;
}
vgmstream->interleave_block_size = interleave;
vgmstream->layout_type = layout_interleave;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* .STR - mutant Sega Dreamcast stream [102 Dalmatians: Puppies to the Rescue (DC)] */
VGMSTREAM* init_vgmstream_str_sega_custom(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channels, sample_rate, interleave;
uint32_t data_size;
/* checks */
if (read_u32le(0x00,sf) != 0x2)
goto fail;
if (read_u64be(0xD4,sf) != 0x00)
return NULL;
if (!check_extensions(sf, "str"))
return NULL;
/* this looks vaguely like a STR and could be a fully new thing, but game does include Audio64.drv */
loop_flag = 0;
channels = 2;
sample_rate = read_s32le(0x04,sf);
if (read_u32le(0x08,sf) != 16)
return NULL;
interleave = read_s32le(0x0c,sf);
if (read_u32le(0x10,sf) != 0x10000 ||
read_u32le(0x14,sf) != 0x00 ||
read_u32le(0x18,sf) != 0x00 ||
read_u32le(0x1C,sf) != 0x1F)
return NULL;
start_offset = 0x800;
data_size = get_streamfile_size(sf) - start_offset;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_STR_SEGA_custom;
vgmstream->sample_rate =sample_rate;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = pcm16_bytes_to_samples(data_size, channels);
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -583,11 +583,17 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa
return 1;
}
/* Bad Boys II (PC)[2004] */
/* Pac-Man World 3 (PC)[2005] */
if ((read_u32be(0x04,sf_h) == 0x00000800 ||
read_u32be(0x04,sf_h) == 0x01000800) && /* rare, mu_spectral1_explore_2 */
read_u32le(0x24,sf_h) == read_u32le(0x114,sf_h) && /* sample rate repeat */
(
// check if the header ends at table1 (Bad Boys)
read_u32le(0x128,sf_h) * 0x4 + read_u32le(0x12c, sf_h) == header_size ||
// otherwise it ends at table2
read_u32le(0x130,sf_h) + read_u32le(0x134,sf_h) * 0x40 == header_size /* ~0x140 + cues */
)
) {
/* 0x08: null */
/* 0x0c: hashname */

View file

@ -142,6 +142,8 @@ typedef struct {
int chunk_start_set;
int chunk_size_set;
int chunk_count_set;
int chunk_bsize_set;
int chunk_dsize_set;
uint32_t base_offset;
uint32_t is_offset_absolute;
@ -311,6 +313,10 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
(int32_t*)&txth.loop_start_sample, (int32_t*)&txth.loop_end_sample);
}
if (txth.debug) {
vgm_logi("TXTH: offset=%x, size=%x, coefs=%x + %x\n", txth.start_offset, txth.data_size, txth.coef_offset, txth.coef_spacing);
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(txth.channels,txth.loop_flag);
@ -827,7 +833,8 @@ static void set_body_chunk(txth_header* txth) {
//todo maybe should only be done once, or have some count to retrigger to simplify?
if (!txth->chunk_start_set || !txth->chunk_size_set || !txth->chunk_count_set)
return;
if (txth->chunk_size == 0 && !(txth->chunk_bsize_offset || txth->chunk_dsize_offset))
if (txth->chunk_size == 0 && !(txth->chunk_bsize_set || txth->chunk_dsize_set))
return;
if (txth->chunk_start > txth->data_size || txth->chunk_count == 0)
return;
@ -853,6 +860,8 @@ static void set_body_chunk(txth_header* txth) {
cfg.chunk_bsize_offset = txth->chunk_bsize_offset;
cfg.chunk_dsize_offset = txth->chunk_dsize_offset;
cfg.chunk_be = txth->chunk_big_endian;
cfg.chunk_bsize_set = txth->chunk_bsize_set;
cfg.chunk_dsize_set = txth->chunk_dsize_set;
cfg.chunk_start = txth->chunk_start;
cfg.chunk_size = txth->chunk_size;
@ -1473,10 +1482,12 @@ static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, cha
else if (is_string(key,"chunk_size_offset")) {
if (!parse_num(txth->sf_head,txth,val, &txth->chunk_bsize_offset)) goto fail;
txth->chunk_size_set = 1;
txth->chunk_bsize_set = 1;
}
else if (is_string(key,"chunk_data_size_offset")) {
if (!parse_num(txth->sf_head,txth,val, &txth->chunk_dsize_offset)) goto fail;
txth->chunk_size_set = 1;
txth->chunk_dsize_set = 1;
}
else if (is_string(key,"chunk_endianness")) {
if (!parse_endianness(txth, val, &txth->chunk_big_endian, NULL)) goto fail;

View file

@ -17,6 +17,8 @@ typedef struct {
uint32_t chunk_bsize_offset;
uint32_t chunk_dsize_offset;
int chunk_be;
int chunk_bsize_set;
int chunk_dsize_set;
} txth_io_config_data;
typedef struct {
@ -72,15 +74,15 @@ static size_t txth_io_read(STREAMFILE* sf, uint8_t* dest, off_t offset, size_t l
}
/* chunk size reader (overwrites the above) */
if (data->cfg.chunk_header_size && (data->cfg.chunk_bsize_offset || data->cfg.chunk_dsize_offset)) {
if (data->cfg.chunk_header_size && (data->cfg.chunk_bsize_set || data->cfg.chunk_dsize_set)) {
read_u32_t read_u32 = data->cfg.chunk_be ? read_u32be : read_u32le;
data->block_size = 0;
data->data_size = 0;
if (data->cfg.chunk_bsize_offset)
if (data->cfg.chunk_bsize_set)
data->block_size = read_u32(data->physical_offset + data->cfg.chunk_bsize_offset, sf);
if (data->cfg.chunk_dsize_offset)
if (data->cfg.chunk_dsize_set)
data->data_size = read_u32(data->physical_offset + data->cfg.chunk_dsize_offset, sf);
if (!data->block_size && !data->data_size) { /* bad read? */

View file

@ -62,8 +62,8 @@ typedef struct {
int has_rs_files;
off_t sequence_extra_offset;
off_t sequence_sequence_loop;
off_t sequence_sequence_single;
off_t sequence_sequence_loop_start;
off_t sequence_sequence_num_loops;
off_t sequence_sequence_count;
off_t sequence_entry_number;
size_t sequence_entry_size;
@ -188,8 +188,8 @@ typedef struct {
int sequence_chain[SB_MAX_CHAIN_COUNT]; /* sequence of entry numbers */
int sequence_banks[SB_MAX_CHAIN_COUNT]; /* sequence of bnk bank numbers */
int sequence_multibank; /* info flag */
int sequence_loop; /* chain index to loop */
int sequence_single; /* if que sequence plays once (loops by default) */
int sequence_loop_start; /* chain index to loop */
int sequence_num_loops; /* if que sequence plays once (loops by default) */
float duration; /* silence duration */
@ -1467,7 +1467,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_sequence(ubi_sb_header* sb, STREAMFILE*
data->segments[i] = init_vgmstream_ubi_sb_header(&temp_sb, sf_bank, sf);
if (!data->segments[i]) goto fail;
if (i == sb->sequence_loop)
if (i == sb->sequence_loop_start)
sb->loop_start = sb->num_samples;
sb->num_samples += data->segments[i]->num_samples;
@ -1483,7 +1483,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_sequence(ubi_sb_header* sb, STREAMFILE*
goto fail;
/* build the base VGMSTREAM */
vgmstream = allocate_vgmstream(data->output_channels, !sb->sequence_single);
vgmstream = allocate_vgmstream(data->output_channels, !sb->sequence_num_loops);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_UBI_SB;
@ -1625,7 +1625,7 @@ static void build_readable_name(char * buf, size_t buf_size, ubi_sb_header* sb)
index = sb->header_index; //-1
if (sb->type == UBI_SEQUENCE) {
if (sb->sequence_single) {
if (sb->sequence_num_loops) {
if (sb->sequence_count == 1)
res_name = "single";
else
@ -1635,7 +1635,7 @@ static void build_readable_name(char * buf, size_t buf_size, ubi_sb_header* sb)
if (sb->sequence_count == 1)
res_name = "single-loop";
else
res_name = (sb->sequence_loop == 0) ? "multi-loop" : "intro-loop";
res_name = (sb->sequence_loop_start == 0) ? "multi-loop" : "intro-loop";
}
}
else {
@ -1918,8 +1918,8 @@ static int parse_type_sequence(ubi_sb_header* sb, off_t offset, STREAMFILE* sf)
}
sb->extra_offset = read_32bit(offset + sb->cfg.sequence_extra_offset, sf) + sb->sectionX_offset;
sb->sequence_loop = read_32bit(offset + sb->cfg.sequence_sequence_loop, sf);
sb->sequence_single = read_32bit(offset + sb->cfg.sequence_sequence_single, sf);
sb->sequence_loop_start = read_32bit(offset + sb->cfg.sequence_sequence_loop_start, sf);
sb->sequence_num_loops = read_32bit(offset + sb->cfg.sequence_sequence_num_loops, sf);
sb->sequence_count = read_32bit(offset + sb->cfg.sequence_sequence_count, sf);
if (sb->sequence_count > SB_MAX_CHAIN_COUNT) {
@ -2705,17 +2705,17 @@ static void config_sb_audio_ps2_old(ubi_sb_header *sb, off_t flag_bits, int stre
}
static void config_sb_sequence(ubi_sb_header* sb, off_t sequence_count, off_t entry_size) {
/* sequence header and chain table */
sb->cfg.sequence_sequence_loop = sequence_count - 0x10;
sb->cfg.sequence_sequence_single= sequence_count - 0x0c;
sb->cfg.sequence_sequence_loop_start = sequence_count - 0x10;
sb->cfg.sequence_sequence_num_loops = sequence_count - 0x0c;
sb->cfg.sequence_sequence_count = sequence_count;
sb->cfg.sequence_entry_size = entry_size;
sb->cfg.sequence_entry_number = 0x00;
if (sb->is_bnm || sb->is_dat || sb->is_ps2_bnm) {
sb->cfg.sequence_sequence_loop = sequence_count - 0x0c;
sb->cfg.sequence_sequence_single= sequence_count - 0x08;
sb->cfg.sequence_sequence_loop_start = sequence_count - 0x0c;
sb->cfg.sequence_sequence_num_loops = sequence_count - 0x08;
} else if (sb->is_blk) {
sb->cfg.sequence_sequence_loop = sequence_count - 0x14;
sb->cfg.sequence_sequence_single= sequence_count - 0x0c;
sb->cfg.sequence_sequence_loop_start = sequence_count - 0x14;
sb->cfg.sequence_sequence_num_loops = sequence_count - 0x0c;
}
}
static void config_sb_layer_hs(ubi_sb_header* sb, off_t layer_count, off_t stream_size, off_t stream_offset, off_t stream_name) {

View file

@ -81,25 +81,24 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
loop_flag = 0;
break;
case 0x70474156: /* pGAV (little endian / stereo) [Jak 3 (PS2), Jak X (PS2)] */
case 0x70474156: /* pGAV (little endian / stereo) [Jak II, Jak 3, Jak X (PS2)] */
meta_type = meta_VAG_custom;
start_offset = 0x30;
if (is_id32be(0x20,sf, "Ster")) {
channels = 2;
if (is_id32be(0x2000,sf, "pGAV"))
interleave = 0x2000; /* Jak 3 interleave, includes header */
interleave = 0x2000; /* Jak II & Jak 3 interleave, includes header */
else if (is_id32be(0x1000,sf, "pGAV"))
interleave = 0x1000; /* Jak X interleave, includes header */
else
goto fail;
interleave = 0;
if (interleave) {
channels = 2;
interleave_first = interleave - start_offset; /* interleave includes header */
interleave_first_skip = start_offset;
}
else {
channels = 1;
interleave = 0;
}
channel_size = read_u32le(0x0C,sf) / channels;
@ -289,7 +288,8 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
}
/* ignore bigfiles and bad extractions (approximate) */
if (channel_size * channels + interleave * channels + start_offset * channels + 0x8000 < get_streamfile_size(sf) ||
/* padding is set to 2 MiB to avoid breaking Jak series' VAGs */
if (channel_size * channels + interleave * channels + start_offset * channels + 0x200000 < get_streamfile_size(sf) ||
channel_size * channels > get_streamfile_size(sf)) {
vgm_logi("VAG: wrong expected (incorrect extraction? %x * %i + %x + %x + ~ vs %x)\n",
channel_size, channels, interleave * channels, start_offset * channels, (uint32_t)get_streamfile_size(sf));

View file

@ -0,0 +1,45 @@
#include "meta.h"
#include "../coding/coding.h"
/* .WB - from Shooting Love. ~TRIZEAL~ */
VGMSTREAM* init_vgmstream_wb(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset;
int channels, loop_flag;
/* check header */
if (read_u32le(0x00,sf) != 0x00000000)
return NULL;
if (read_u32le(0x0c,sf) + 0x10 != get_streamfile_size(sf))
return NULL;
/* .wb: actual extension */
if (!check_extensions(sf,"wb"))
goto fail;
channels = 2;
start_offset = 0x10;
loop_flag = read_32bitLE(0x04,sf) > 0; /* loop end may be defined */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_WB;
vgmstream->sample_rate = 48000;
vgmstream->num_samples = pcm16_bytes_to_samples(read_u32le(0x0C,sf), channels);
vgmstream->loop_start_sample = read_s32le(0x04,sf);
vgmstream->loop_end_sample = read_s32le(0x08,sf);
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 2;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,124 +0,0 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util.h"
/* .mus, as seen in Star Wars The Force Unleashed for Wii */
/* Doesn't seem to be working quite right yet, coef table looks odd */
VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
off_t interleave;
int i;
struct {
uint16_t gain;
uint16_t initial_ps;
uint16_t initial_hist1;
uint16_t initial_hist2;
uint16_t loop_ps;
/*
uint16_t loop_hist1;
uint16_t loop_hist2;
*/
} channel[2];
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("mus",filename_extension(filename))) goto fail;
start_offset = read_32bitBE(0x08,streamFile);
interleave = read_32bitBE(0x04,streamFile);
for (i=0;i<2;i++)
{
channel[i].gain = read_16bitBE(0x30+i*0x2e,streamFile);
channel[i].initial_ps = read_16bitBE(0x32+i*0x2e,streamFile);
channel[i].initial_hist1 = read_16bitBE(0x34+i*0x2e,streamFile);
channel[i].initial_hist2 = read_16bitBE(0x36+i*0x2e,streamFile);
channel[i].loop_ps = read_16bitBE(0x38+i*0x2e,streamFile);
}
/* check initial predictor/scale */
if (channel[0].initial_ps != (uint8_t)read_8bit(start_offset,streamFile))
goto fail;
if (channel[1].initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile))
goto fail;
/* check type==0 and gain==0 */
if (channel[0].gain ||
channel[1].gain)
goto fail;
#if 0
if (ch0_header.loop_flag) {
off_t loop_off;
/* check loop predictor/scale */
loop_off = ch0_header.loop_start_offset/16*8;
loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave);
if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile))
goto fail;
if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile))
goto fail;
}
#endif
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(2,0);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(0x0,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitBE(0x6c,streamFile);
/* TODO: adjust for interleave? */
#if 0
vgmstream->loop_start_sample = dsp_nibbles_to_samples(
ch0_header.loop_start_offset);
vgmstream->loop_end_sample = dsp_nibbles_to_samples(
ch0_header.loop_end_offset)+1;
#endif
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
vgmstream->meta_type = meta_DSP_WII_MUS;
/* coeffs */
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10 + i*2,streamFile);
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x3e + i*2,streamFile);
}
/* initial history */
/* always 0 that I've ever seen, but for completeness... */
vgmstream->ch[0].adpcm_history1_16 = channel[0].initial_hist1;
vgmstream->ch[0].adpcm_history2_16 = channel[0].initial_hist2;
vgmstream->ch[1].adpcm_history1_16 = channel[1].initial_hist1;
vgmstream->ch[1].adpcm_history2_16 = channel[1].initial_hist2;
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[1].streamfile) goto fail;
/* open the file for reading */
for (i=0;i<2;i++) {
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+i*interleave;
}
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) {
if (vgmstream->ch[0].streamfile) close_streamfile(vgmstream->ch[0].streamfile);
close_vgmstream(vgmstream);
}
return NULL;
}

View file

@ -39,8 +39,9 @@ VGMSTREAM* init_vgmstream_xa(STREAMFILE* sf) {
* .pxa: Mortal Kombat 4 (PS1)
* .grn: Micro Machines (CDi)
* .an2: Croc (PS1) movies
* .xai: Quake II (PS1)
* (extensionless): bigfiles [Castlevania: Symphony of the Night (PS1)] */
if (!check_extensions(sf,"xa,str,pxa,grn,an2,"))
if (!check_extensions(sf,"xa,str,pxa,grn,an2,,xai"))
goto fail;
/* Proper XA comes in raw (BIN 2352 mode2/form2) CD sectors, that contain XA subheaders.

View file

@ -5,7 +5,7 @@
VGMSTREAM * init_vgmstream_xa_xa30(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, codec;
int loop_flag, channel_count, codec, interleave_block_size;
size_t stream_size;
int total_subsongs, target_subsong = streamFile->stream_index;
@ -31,6 +31,7 @@ VGMSTREAM * init_vgmstream_xa_xa30(STREAMFILE *streamFile) {
codec = read_32bitLE(0x0c,streamFile);
start_offset = read_32bitLE(0x10 + 0x04*(target_subsong-1),streamFile);
stream_size = read_32bitLE(0x18 + 0x04*(target_subsong-1),streamFile);
interleave_block_size = read_32bitLE(0x24, streamFile);
/* build the VGMSTREAM */
@ -47,14 +48,14 @@ VGMSTREAM * init_vgmstream_xa_xa30(STREAMFILE *streamFile) {
case 0x00: /* PCM (rare, seen in Driver 3) */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile) / 2;
vgmstream->interleave_block_size = interleave_block_size / 2;
vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16);
break;
case 0x01: /* MS-IMA variation */
vgmstream->coding_type = coding_REF_IMA;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile);
vgmstream->interleave_block_size = interleave_block_size;
vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, vgmstream->interleave_block_size, channel_count);
break;

View file

@ -1,61 +0,0 @@
#include "meta.h"
#include "../util.h"
#include "../layout/layout.h"
/* matx
MATX (found in Matrix)
*/
VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag=0;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("matx",filename_extension(filename))) goto fail;
loop_flag = 0;
channel_count=read_16bitLE(0x4,streamFile);
/* 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_16bitLE(0x06,streamFile) & 0xffff;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_blocked_matx;
vgmstream->meta_type = meta_XBOX_MATX;
/* open the file for reading by each channel */
{
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;
}
}
/* Calc num_samples */
block_update_matx(0,vgmstream);
vgmstream->num_samples=0;
do {
vgmstream->num_samples += vgmstream->current_block_size/36*64;
block_update_matx(vgmstream->next_block_offset,vgmstream);
} while (vgmstream->next_block_offset<get_streamfile_size(streamFile));
block_update_matx(0,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,72 +1,61 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* XSS (found in Dino Crisis 3) */
VGMSTREAM * init_vgmstream_xss(STREAMFILE *streamFile) {
/* .XSS - found in Dino Crisis 3 (Xbox) */
VGMSTREAM* init_vgmstream_xss(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
uint32_t start_offset;
int channels, loop_flag, sample_rate;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xss",filename_extension(filename))) goto fail;
/* checks */
/* 00: name + garbage data up to ?
* (due to garbage it's hard which values are from this header, but these seem consistent) */
if (read_u32le(0x0c,sf) != 0x3a)
return NULL;
if (read_u32le(0x10,sf) != 0x00)
return NULL;
/* check header */
if ((uint16_t)read_16bitLE(0x15A,streamFile) != 0x10)
goto fail;
if (read_32bitLE(0x154,streamFile) / read_32bitLE(0x150,streamFile) !=
(uint16_t)read_16bitLE(0x158,streamFile))
goto fail;
if (!check_extensions(sf,"xss"))
return NULL;
/* some floats and stuff up to 0x100, then some sizes, then RIFF fmt-like header */
uint32_t head_offset = 0x140;
if (read_u32le(head_offset+0x00, sf) != 0x40)
return NULL;
loop_flag = (read_u32le(head_offset + 0x04,sf) != 0);
if (read_u16le(head_offset + 0x0c,sf) != 0x01)
return NULL;
channels = read_u16le(head_offset + 0x0E,sf);
sample_rate = read_u32le(head_offset + 0x10,sf);
/* 14: bitrate */
/* 18: block size */
if (read_u16le(head_offset + 0x1A,sf) != 0x10)
return NULL;
start_offset = 0x800;
loop_flag = (read_32bitLE(0x144,streamFile)!=0);
channel_count = (uint16_t)read_16bitLE(0x14E,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x150,streamFile);
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x144,streamFile)/2/channel_count;
vgmstream->loop_end_sample = read_32bitLE(0x148,streamFile)/2/channel_count;
}
vgmstream->meta_type = meta_XSS;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = pcm16_bytes_to_samples(get_streamfile_size(sf) - start_offset, channels);
vgmstream->loop_start_sample = pcm16_bytes_to_samples(read_u32le(head_offset + 0x04,sf), channels);
vgmstream->loop_end_sample = pcm16_bytes_to_samples(read_u32le(head_offset + 0x08,sf), channels);
if (vgmstream->channels == 1) {
vgmstream->layout_type = layout_none;
} else if (vgmstream->channels > 1) {
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2;
}
vgmstream->meta_type = meta_XSS;
/* 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, sf, start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View file

@ -1,10 +1,12 @@
#ifndef _UTIL_ENDIAN_H
#define _UTIL_ENDIAN_H
#ifndef _ENDIANNESS_H
#define _ENDIANNESS_H
#include "../streamfile.h"
#include "reader_get.h"
#include "reader_sf.h"
typedef uint64_t (*read_u64_t)(off_t, STREAMFILE*);
typedef int64_t (*read_s64_t)(off_t, STREAMFILE*);
typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*);
typedef int32_t (*read_s32_t)(off_t, STREAMFILE*);
typedef uint16_t (*read_u16_t)(off_t, STREAMFILE*);

View file

@ -0,0 +1,71 @@
#include "layout_utils.h"
#include "../vgmstream.h"
#include "../layout/layout.h"
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) {
if (!vs || !vs->codec_data) {
goto fail;
}
if (!layer_channels)
layer_channels = 1;
if (!layers)
layers = vs->channels / layer_channels;
int i;
layered_layout_data* data;
switch(vs->layout_type) {
case layout_segmented: //to be improved
goto fail;
case layout_layered:
data = vs->layout_data;
i = data->curr_layer;
break;
default:
data = init_layout_layered(layers);
if (!data) goto fail;
vs->layout_data = data;
vs->layout_type = layout_layered;
i = 0;
break;
}
data->layers[i] = allocate_vgmstream(layer_channels, vs->loop_flag);
if (!data->layers[i]) goto fail;
data->layers[i]->meta_type = vs->meta_type;
data->layers[i]->sample_rate = vs->sample_rate;
data->layers[i]->num_samples = vs->num_samples;
data->layers[i]->loop_start_sample = vs->loop_start_sample;
data->layers[i]->loop_end_sample = vs->loop_end_sample;
data->layers[i]->codec_data = vs->codec_data;
if (!data->layers[i]->codec_data) goto fail;
data->layers[i]->coding_type = vs->coding_type;
data->layers[i]->layout_type = layout_none;
vs->codec_data = NULL; /* moved to layer, don't hold it */
data->curr_layer++;
return true;
fail:
return false;
}
bool layered_add_done(VGMSTREAM* vs) {
//TODO: some extra checks/setup?
if (!setup_layout_layered(vs->layout_data))
goto fail;
return true;
fail:
return false;
}

View file

@ -0,0 +1,12 @@
#ifndef _LAYOUTS_UTIL_H
#define _LAYOUTS_UTIL_H
#include "../vgmstream.h"
/* add a new layer from codec data (setups layout if needed)
* codec is passed in the vs for easier free/etc control */
bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels);
/* call when done adding layers */
bool layered_add_done(VGMSTREAM* vs);
#endif

View file

@ -9,11 +9,18 @@ static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const ch
char* extension = (char*)filename_extension(pathname);
//todo safeops
if (extension[0] == '\0') {
if (swap[0] != '\0') {
strcat(pathname, ".");
strcat(pathname, swap);
}
}
else {
if (swap[0] != '\0') {
strcpy(extension, swap);
} else {
extension--;
extension[0] = '\0';
}
}
}

View file

@ -103,16 +103,12 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_lp_ap_lep,
init_vgmstream_sdt,
init_vgmstream_aix,
init_vgmstream_ngc_tydsp,
init_vgmstream_wvs_xbox,
init_vgmstream_wvs_ngc,
init_vgmstream_dc_str,
init_vgmstream_dc_str_v2,
init_vgmstream_xbox_matx,
init_vgmstream_str_sega,
init_vgmstream_str_sega_custom,
init_vgmstream_dec,
init_vgmstream_vs,
init_vgmstream_dc_str,
init_vgmstream_dc_str_v2,
init_vgmstream_xmu,
init_vgmstream_xvas,
init_vgmstream_sat_sap,
@ -130,7 +126,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_ps2_mihb,
init_vgmstream_ngc_pdt_split,
init_vgmstream_ngc_pdt,
init_vgmstream_wii_mus,
init_vgmstream_mus_krome,
init_vgmstream_dc_asd,
init_vgmstream_spsd,
init_vgmstream_rsd,
@ -145,7 +141,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_gca,
init_vgmstream_spt_spd,
init_vgmstream_ish_isd,
init_vgmstream_gsp_gsb,
init_vgmstream_gsnd,
init_vgmstream_ydsp,
init_vgmstream_ngc_ssm,
init_vgmstream_ps2_joe,
@ -171,7 +167,6 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_zsd,
init_vgmstream_vgs_ps,
init_vgmstream_redspark,
init_vgmstream_ivaud,
init_vgmstream_wii_wsd,
init_vgmstream_dsp_ndp,
init_vgmstream_ps2_sps,
@ -189,7 +184,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_apple_caff,
init_vgmstream_pc_mxst,
init_vgmstream_sab,
init_vgmstream_wii_bns,
init_vgmstream_bns,
init_vgmstream_wii_was,
init_vgmstream_pona_3do,
init_vgmstream_pona_psx,
@ -201,7 +196,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_dmsg,
init_vgmstream_ngc_dsp_aaap,
init_vgmstream_ngc_dsp_konami,
init_vgmstream_ps2_wb,
init_vgmstream_wb,
init_vgmstream_bnsf,
init_vgmstream_ps2_gcm,
init_vgmstream_smpl,
@ -214,7 +209,6 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_dsp_str_ig,
init_vgmstream_ea_swvr,
init_vgmstream_ps2_b1s,
init_vgmstream_ps2_wad,
init_vgmstream_dsp_xiii,
init_vgmstream_dsp_cabelas,
init_vgmstream_lpcm_shade,
@ -286,7 +280,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_ubi_raki,
init_vgmstream_pasx,
init_vgmstream_xma,
init_vgmstream_sxd,
init_vgmstream_sndx,
init_vgmstream_ogl,
init_vgmstream_mc3,
init_vgmstream_ghs,
@ -523,6 +517,10 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_awd,
init_vgmstream_rws_809,
init_vgmstream_pwb,
init_vgmstream_squeakstream,
init_vgmstream_squeaksample,
init_vgmstream_snds,
init_vgmstream_adm2,
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
init_vgmstream_scd_pcm,
@ -533,6 +531,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_mic_koei,
init_vgmstream_seb,
init_vgmstream_tgc,
init_vgmstream_ivaud,
/* need companion files */
init_vgmstream_pos,
init_vgmstream_sli_loops,

View file

@ -281,6 +281,7 @@ typedef struct {
int input_channels; /* internal buffer channels */
int output_channels; /* resulting channels (after mixing, if applied) */
int external_looping; /* don't loop using per-layer loops, but layout's own looping */
int curr_layer; /* helper */
} layered_layout_data;

View file

@ -26,6 +26,7 @@ typedef enum {
coding_PCMFLOAT, /* 32-bit float PCM */
coding_PCM24LE, /* little endian 24-bit PCM */
coding_PCM24BE, /* big endian 24-bit PCM */
coding_PCM32LE, /* little endian 32-bit PCM */
/* ADPCM */
coding_CRI_ADX, /* CRI ADX */
@ -202,7 +203,6 @@ typedef enum {
layout_blocked_wsi,
layout_blocked_str_snds,
layout_blocked_ws_aud,
layout_blocked_matx,
layout_blocked_dec,
layout_blocked_xvas,
layout_blocked_vs,
@ -258,7 +258,7 @@ typedef enum {
meta_DSP_SADB, /* .sad */
meta_DSP_WSI, /* .wsi */
meta_IDSP_TT, /* Traveller's Tales games */
meta_DSP_WII_MUS, /* .mus */
meta_MUS_KROME,
meta_DSP_WII_WSD, /* Phantom Brave (WII) */
meta_WII_NDP, /* Vertigo (Wii) */
meta_DSP_YGO, /* Konami: Yu-Gi-Oh! The Falsebound Kingdom (NGC), Hikaru no Go 3 (NGC) */
@ -275,8 +275,8 @@ typedef enum {
meta_THP, /* THP movie files */
meta_SWAV,
meta_NDS_RRDS, /* Ridge Racer DS */
meta_WII_BNS, /* Wii BNS Banner Sound (similar to RSTM) */
meta_WIIU_BTSND, /* Wii U Boot Sound */
meta_BNS,
meta_BTSND,
meta_ADX_03, /* CRI ADX "type 03" */
meta_ADX_04, /* CRI ADX "type 04" */
@ -345,9 +345,8 @@ typedef enum {
meta_PS2_VAS, /* Pro Baseball Spirits 5 */
meta_LP_AP_LEP,
meta_SDT, /* Baldur's Gate - Dark Alliance */
meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */
meta_DC_STR, /* SEGA Stream Asset Builder */
meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */
meta_STR_SEGA,
meta_STR_SEGA_custom,
meta_SAP,
meta_DC_IDVI, /* Eldorado Gate */
meta_KRAW, /* Geometry Wars - Galaxies */
@ -358,7 +357,7 @@ typedef enum {
meta_IDSP_IE, /* Defencer (GC) */
meta_SPT_SPD, /* Various (SPT+SPT DSP) */
meta_ISH_ISD, /* Various (ISH+ISD DSP) */
meta_GSP_GSB, /* Tecmo games (Super Swing Golf 1 & 2, Quamtum Theory) */
meta_GSND,
meta_YDSP, /* WWE Day of Reckoning */
meta_FFCC_STR, /* Final Fantasy: Crystal Chronicles */
meta_UBI_JADE, /* Beyond Good & Evil, Rayman Raving Rabbids */
@ -392,7 +391,6 @@ typedef enum {
meta_UBI_CKD, /* Ubisoft CKD RIFF header (Rayman Origins Wii) */
meta_RAW_WAVM,
meta_WVS,
meta_XBOX_MATX, /* XBOX MATX */
meta_XMU,
meta_XVAS,
meta_EA_SCHL, /* Electronic Arts SCHl with variable header */
@ -455,7 +453,7 @@ typedef enum {
meta_AST_MMV,
meta_DMSG, /* Nightcaster II - Equinox (XBOX) */
meta_NGC_DSP_AAAP, /* Turok: Evolution (NGC), Vexx (NGC) */
meta_PS2_WB, /* Shooting Love. ~TRIZEAL~ */
meta_WB,
meta_S14, /* raw Siren 14, 24kbit mono */
meta_SSS, /* raw Siren 14, 48kbit stereo */
meta_PS2_GCM, /* NamCollection */
@ -469,7 +467,6 @@ typedef enum {
meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */
meta_EA_SWVR, /* Future Cop L.A.P.D., Freekstyle */
meta_PS2_B1S, /* 7 Wonders of the ancient world */
meta_PS2_WAD, /* The golden Compass */
meta_DSP_XIII, /* XIII, possibly more (Ubisoft header???) */
meta_DSP_CABELAS, /* Cabelas games */
meta_PS2_ADM, /* Dragon Quest V (PS2) */
@ -532,7 +529,7 @@ typedef enum {
meta_ASTB,
meta_WWISE_RIFF, /* Audiokinetic Wwise RIFF/RIFX */
meta_UBI_RAKI, /* Ubisoft RAKI header (Rayman Legends, Just Dance 2017) */
meta_SXD, /* Sony SXD (Gravity Rush, Freedom Wars PSV) */
meta_SNDX,
meta_OGL, /* Shin'en Wii/WiiU (Jett Rocket (Wii), FAST Racing NEO (WiiU)) */
meta_MC3, /* Paradigm games (T3 PS2, MX Rider PS2, MI: Operation Surma PS2) */
meta_GHS,
@ -540,7 +537,7 @@ typedef enum {
meta_MTA2,
meta_XA_XA30,
meta_XA_04SW,
meta_TXTH, /* generic text header */
meta_TXTH,
meta_SK_AUD, /* Silicon Knights .AUD (Eternal Darkness GC) */
meta_AHX,
meta_STMA,
@ -581,11 +578,11 @@ typedef enum {
meta_DSP_MCADPCM, /* Skyrim (Switch) */
meta_UBI_LYN, /* Ubisoft LyN engine [The Adventures of Tintin (multi)] */
meta_MSB_MSH, /* sfx companion of MIH+MIB */
meta_TXTP, /* generic text playlist */
meta_TXTP,
meta_SMC_SMH, /* Wangan Midnight (System 246) */
meta_PPST, /* PPST [Parappa the Rapper (PSP)] */
meta_SPS_N1,
meta_UBI_BAO, /* Ubisoft BAO */
meta_UBI_BAO,
meta_DSP_SWITCH_AUDIO, /* Gal Gun 2 (Switch) */
meta_H4M, /* Hudson HVQM4 video [Resident Evil 0 (GC), Tales of Symphonia (GC)] */
meta_ASF, /* Argonaut ASF [Croc 2 (PC)] */
@ -694,13 +691,16 @@ typedef enum {
meta_SSPF,
meta_S3V,
meta_ESF,
meta_ADM3,
meta_ADM,
meta_TT_AD,
meta_SNDZ,
meta_VAB,
meta_BIGRP,
meta_DIC1,
meta_AWD,
meta_SQUEAKSTREAM,
meta_SQUEAKSAMPLE,
meta_SNDS,
} meta_t;

View file

@ -509,6 +509,7 @@
<string>fda</string>
<string>ffw</string>
<string>filp</string>
<string>fish</string>
<string>flx</string>
<string>fsb</string>
<string>fsv</string>
@ -522,10 +523,11 @@
<string>gcw</string>
<string>genh</string>
<string>gin</string>
<string>gmd</string>
<string>gms</string>
<string>grn</string>
<string>gsb</string>
<string>gsf</string>
<string>gsp</string>
<string>gtd</string>
<string>gwm</string>
<string>h4m</string>
@ -534,7 +536,6 @@
<string>hd3</string>
<string>hdr</string>
<string>hdt</string>
<string>hgc1</string>
<string>his</string>
<string>hps</string>
<string>hsf</string>
@ -638,7 +639,6 @@
<string>mab</string>
<string>mad</string>
<string>map</string>
<string>matx</string>
<string>mc3</string>
<string>mca</string>
<string>mcadpcm</string>
@ -797,8 +797,6 @@
<string>sgb</string>
<string>sgd</string>
<string>sgt</string>
<string>sgx</string>
<string>sl3</string>
<string>slb</string>
<string>sli</string>
<string>smc</string>
@ -858,10 +856,10 @@
<string>tmx</string>
<string>tra</string>
<string>trk</string>
<string>trs</string>
<string>tun</string>
<string>txth</string>
<string>txtp</string>
<string>tydsp</string>
<string>u0</string>
<string>ue4opus</string>
<string>ulw</string>
@ -943,6 +941,7 @@
<string>xa</string>
<string>xa2</string>
<string>xa30</string>
<string>xai</string>
<string>xag</string>
<string>xau</string>
<string>xav</string>