Updated VGMStream to r1050-3774-gbecac809

CQTexperiment
Christopher Snowhill 2021-06-20 19:36:12 -07:00
parent 75a4f1e722
commit 636120c9d5
37 changed files with 1171 additions and 1322 deletions

View File

@ -155,7 +155,6 @@
8349A9091FE6258200E26435 /* pc_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F01FE6257C00E26435 /* pc_ast.c */; }; 8349A9091FE6258200E26435 /* pc_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F01FE6257C00E26435 /* pc_ast.c */; };
8349A90A1FE6258200E26435 /* sab.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F11FE6257D00E26435 /* sab.c */; }; 8349A90A1FE6258200E26435 /* sab.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F11FE6257D00E26435 /* sab.c */; };
8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F21FE6257D00E26435 /* ps2_pcm.c */; }; 8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F21FE6257D00E26435 /* ps2_pcm.c */; };
8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */; };
8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F41FE6257D00E26435 /* ubi_sb.c */; }; 8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F41FE6257D00E26435 /* ubi_sb.c */; };
8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F51FE6257D00E26435 /* scd_pcm.c */; }; 8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F51FE6257D00E26435 /* scd_pcm.c */; };
8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F61FE6257E00E26435 /* aix_streamfile.h */; }; 8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F61FE6257E00E26435 /* aix_streamfile.h */; };
@ -266,7 +265,6 @@
836F6F6518BDC2190095E648 /* 2dx9.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2918BDC2180095E648 /* 2dx9.c */; }; 836F6F6518BDC2190095E648 /* 2dx9.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2918BDC2180095E648 /* 2dx9.c */; };
836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; }; 836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; };
836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; }; 836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; };
836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.c */; };
836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; }; 836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; };
836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; }; 836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; };
836F6F6D18BDC2190095E648 /* aifc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3118BDC2180095E648 /* aifc.c */; }; 836F6F6D18BDC2190095E648 /* aifc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3118BDC2180095E648 /* aifc.c */; };
@ -333,7 +331,6 @@
836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7B18BDC2180095E648 /* ngc_ssm.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 */; }; 836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */; };
836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7E18BDC2180095E648 /* ngc_ymf.c */; }; 836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7E18BDC2180095E648 /* ngc_ymf.c */; };
836F6FBB18BDC2190095E648 /* ngca.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7F18BDC2180095E648 /* ngca.c */; };
836F6FBD18BDC2190095E648 /* nwa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8118BDC2180095E648 /* nwa.c */; }; 836F6FBD18BDC2190095E648 /* nwa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8118BDC2180095E648 /* nwa.c */; };
836F6FBF18BDC2190095E648 /* otm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8318BDC2180095E648 /* otm.c */; }; 836F6FBF18BDC2190095E648 /* otm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8318BDC2180095E648 /* otm.c */; };
836F6FC018BDC2190095E648 /* p3d.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8418BDC2180095E648 /* p3d.c */; }; 836F6FC018BDC2190095E648 /* p3d.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8418BDC2180095E648 /* p3d.c */; };
@ -447,7 +444,6 @@
83709E051ECBC1A4005C03D3 /* gtd.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709DFF1ECBC1A4005C03D3 /* gtd.c */; }; 83709E051ECBC1A4005C03D3 /* gtd.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709DFF1ECBC1A4005C03D3 /* gtd.c */; };
83709E061ECBC1A4005C03D3 /* mc3.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E001ECBC1A4005C03D3 /* mc3.c */; }; 83709E061ECBC1A4005C03D3 /* mc3.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E001ECBC1A4005C03D3 /* mc3.c */; };
83709E071ECBC1A4005C03D3 /* mss.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E011ECBC1A4005C03D3 /* mss.c */; }; 83709E071ECBC1A4005C03D3 /* mss.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E011ECBC1A4005C03D3 /* mss.c */; };
83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E021ECBC1A4005C03D3 /* ps2_rxws.c */; };
83709E091ECBC1A4005C03D3 /* ta_aac.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E031ECBC1A4005C03D3 /* ta_aac.c */; }; 83709E091ECBC1A4005C03D3 /* ta_aac.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E031ECBC1A4005C03D3 /* ta_aac.c */; };
83709E0D1ECBC1C3005C03D3 /* mc3_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */; }; 83709E0D1ECBC1C3005C03D3 /* mc3_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */; };
83709E0E1ECBC1C3005C03D3 /* psv_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */; }; 83709E0E1ECBC1C3005C03D3 /* psv_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */; };
@ -497,6 +493,8 @@
837CEB0423487F2C00E62A4A /* jstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAEF23487F2C00E62A4A /* jstm.c */; }; 837CEB0423487F2C00E62A4A /* jstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAEF23487F2C00E62A4A /* jstm.c */; };
837CEB0523487F2C00E62A4A /* sqex_sead_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */; }; 837CEB0523487F2C00E62A4A /* sqex_sead_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */; };
837CEB072348809400E62A4A /* seb.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEB062348809400E62A4A /* seb.c */; }; 837CEB072348809400E62A4A /* seb.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEB062348809400E62A4A /* seb.c */; };
83852B0B2680247900378854 /* rxws.c in Sources */ = {isa = PBXBuildFile; fileRef = 83852B092680247900378854 /* rxws.c */; };
83852B0C2680247900378854 /* ads_midway.c in Sources */ = {isa = PBXBuildFile; fileRef = 83852B0A2680247900378854 /* ads_midway.c */; };
8385D4E6245174C700FF8E67 /* diva.c in Sources */ = {isa = PBXBuildFile; fileRef = 8385D4E2245174C600FF8E67 /* diva.c */; }; 8385D4E6245174C700FF8E67 /* diva.c in Sources */ = {isa = PBXBuildFile; fileRef = 8385D4E2245174C600FF8E67 /* diva.c */; };
838BDB681D3AF70D0022CA6F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB671D3AF70D0022CA6F /* libz.tbd */; }; 838BDB681D3AF70D0022CA6F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB671D3AF70D0022CA6F /* libz.tbd */; };
838BDB6A1D3AF7140022CA6F /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB691D3AF7140022CA6F /* libiconv.tbd */; }; 838BDB6A1D3AF7140022CA6F /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB691D3AF7140022CA6F /* libiconv.tbd */; };
@ -949,7 +947,6 @@
8349A8F01FE6257C00E26435 /* pc_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_ast.c; sourceTree = "<group>"; }; 8349A8F01FE6257C00E26435 /* pc_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_ast.c; sourceTree = "<group>"; };
8349A8F11FE6257D00E26435 /* sab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sab.c; sourceTree = "<group>"; }; 8349A8F11FE6257D00E26435 /* sab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sab.c; sourceTree = "<group>"; };
8349A8F21FE6257D00E26435 /* ps2_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_pcm.c; sourceTree = "<group>"; }; 8349A8F21FE6257D00E26435 /* ps2_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_pcm.c; sourceTree = "<group>"; };
8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqex_scd_streamfile.h; sourceTree = "<group>"; };
8349A8F41FE6257D00E26435 /* ubi_sb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_sb.c; sourceTree = "<group>"; }; 8349A8F41FE6257D00E26435 /* ubi_sb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_sb.c; sourceTree = "<group>"; };
8349A8F51FE6257D00E26435 /* scd_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_pcm.c; sourceTree = "<group>"; }; 8349A8F51FE6257D00E26435 /* scd_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_pcm.c; sourceTree = "<group>"; };
8349A8F61FE6257E00E26435 /* aix_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aix_streamfile.h; sourceTree = "<group>"; }; 8349A8F61FE6257E00E26435 /* aix_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aix_streamfile.h; sourceTree = "<group>"; };
@ -1060,7 +1057,6 @@
836F6E2918BDC2180095E648 /* 2dx9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 2dx9.c; sourceTree = "<group>"; }; 836F6E2918BDC2180095E648 /* 2dx9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 2dx9.c; sourceTree = "<group>"; };
836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = "<group>"; }; 836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = "<group>"; };
836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = "<group>"; }; 836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = "<group>"; };
836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = "<group>"; };
836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = "<group>"; }; 836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = "<group>"; };
836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = "<group>"; }; 836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = "<group>"; };
836F6E3118BDC2180095E648 /* aifc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aifc.c; sourceTree = "<group>"; }; 836F6E3118BDC2180095E648 /* aifc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aifc.c; sourceTree = "<group>"; };
@ -1127,7 +1123,6 @@
836F6E7B18BDC2180095E648 /* ngc_ssm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ssm.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>"; }; 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_tydsp.c; sourceTree = "<group>"; };
836F6E7E18BDC2180095E648 /* ngc_ymf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ymf.c; sourceTree = "<group>"; }; 836F6E7E18BDC2180095E648 /* ngc_ymf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ymf.c; sourceTree = "<group>"; };
836F6E7F18BDC2180095E648 /* ngca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngca.c; sourceTree = "<group>"; };
836F6E8118BDC2180095E648 /* nwa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nwa.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>"; }; 836F6E8318BDC2180095E648 /* otm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = otm.c; sourceTree = "<group>"; };
836F6E8418BDC2180095E648 /* p3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p3d.c; sourceTree = "<group>"; }; 836F6E8418BDC2180095E648 /* p3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p3d.c; sourceTree = "<group>"; };
@ -1241,7 +1236,6 @@
83709DFF1ECBC1A4005C03D3 /* gtd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gtd.c; sourceTree = "<group>"; }; 83709DFF1ECBC1A4005C03D3 /* gtd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gtd.c; sourceTree = "<group>"; };
83709E001ECBC1A4005C03D3 /* mc3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3.c; sourceTree = "<group>"; }; 83709E001ECBC1A4005C03D3 /* mc3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3.c; sourceTree = "<group>"; };
83709E011ECBC1A4005C03D3 /* mss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mss.c; sourceTree = "<group>"; }; 83709E011ECBC1A4005C03D3 /* mss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mss.c; sourceTree = "<group>"; };
83709E021ECBC1A4005C03D3 /* ps2_rxws.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rxws.c; sourceTree = "<group>"; };
83709E031ECBC1A4005C03D3 /* ta_aac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ta_aac.c; sourceTree = "<group>"; }; 83709E031ECBC1A4005C03D3 /* ta_aac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ta_aac.c; sourceTree = "<group>"; };
83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3_decoder.c; sourceTree = "<group>"; }; 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3_decoder.c; sourceTree = "<group>"; };
83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psv_decoder.c; sourceTree = "<group>"; }; 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psv_decoder.c; sourceTree = "<group>"; };
@ -1291,6 +1285,8 @@
837CEAEF23487F2C00E62A4A /* jstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jstm.c; sourceTree = "<group>"; }; 837CEAEF23487F2C00E62A4A /* jstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jstm.c; sourceTree = "<group>"; };
837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqex_sead_streamfile.h; sourceTree = "<group>"; }; 837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqex_sead_streamfile.h; sourceTree = "<group>"; };
837CEB062348809400E62A4A /* seb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = seb.c; sourceTree = "<group>"; }; 837CEB062348809400E62A4A /* seb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = seb.c; sourceTree = "<group>"; };
83852B092680247900378854 /* rxws.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rxws.c; sourceTree = "<group>"; };
83852B0A2680247900378854 /* ads_midway.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads_midway.c; sourceTree = "<group>"; };
8385D4E2245174C600FF8E67 /* diva.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = diva.c; sourceTree = "<group>"; }; 8385D4E2245174C600FF8E67 /* diva.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = diva.c; sourceTree = "<group>"; };
838BDB671D3AF70D0022CA6F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 838BDB671D3AF70D0022CA6F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
838BDB691D3AF7140022CA6F /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; 838BDB691D3AF7140022CA6F /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; };
@ -1772,7 +1768,7 @@
83F2CCE125A5B41600F46FA8 /* acx.c */, 83F2CCE125A5B41600F46FA8 /* acx.c */,
83AA7F7A2519C042004C5298 /* adp_konami.c */, 83AA7F7A2519C042004C5298 /* adp_konami.c */,
834FE0CF215C79E8000A5D3D /* adpcm_capcom.c */, 834FE0CF215C79E8000A5D3D /* adpcm_capcom.c */,
836F6E2C18BDC2180095E648 /* ads.c */, 83852B0A2680247900378854 /* ads_midway.c */,
8349A9021FE6258100E26435 /* adx_keys.h */, 8349A9021FE6258100E26435 /* adx_keys.h */,
831BA60E1EAC61A500CF89B0 /* adx.c */, 831BA60E1EAC61A500CF89B0 /* adx.c */,
8349A9001FE6258000E26435 /* afc.c */, 8349A9001FE6258000E26435 /* afc.c */,
@ -1965,7 +1961,6 @@
836F6E7C18BDC2180095E648 /* ngc_tydsp.c */, 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */,
831BD11F1EEE1CF200198540 /* ngc_ulw.c */, 831BD11F1EEE1CF200198540 /* ngc_ulw.c */,
836F6E7E18BDC2180095E648 /* ngc_ymf.c */, 836F6E7E18BDC2180095E648 /* ngc_ymf.c */,
836F6E7F18BDC2180095E648 /* ngca.c */,
83C727FC22BC893900678B4A /* nps.c */, 83C727FC22BC893900678B4A /* nps.c */,
837CEAE223487F2A00E62A4A /* nub.c */, 837CEAE223487F2A00E62A4A /* nub.c */,
832BF81B21E0514B006F50F1 /* nus3audio.c */, 832BF81B21E0514B006F50F1 /* nus3audio.c */,
@ -2028,7 +2023,6 @@
836F6EB318BDC2180095E648 /* ps2_pnb.c */, 836F6EB318BDC2180095E648 /* ps2_pnb.c */,
836F6EB618BDC2180095E648 /* ps2_rnd.c */, 836F6EB618BDC2180095E648 /* ps2_rnd.c */,
836F6EB718BDC2180095E648 /* ps2_rstm.c */, 836F6EB718BDC2180095E648 /* ps2_rstm.c */,
83709E021ECBC1A4005C03D3 /* ps2_rxws.c */,
836F6EBA18BDC2180095E648 /* ps2_sfs.c */, 836F6EBA18BDC2180095E648 /* ps2_sfs.c */,
836F6EBB18BDC2180095E648 /* ps2_sl3.c */, 836F6EBB18BDC2180095E648 /* ps2_sl3.c */,
836F6EBC18BDC2180095E648 /* ps2_smpl.c */, 836F6EBC18BDC2180095E648 /* ps2_smpl.c */,
@ -2072,6 +2066,7 @@
836F6EB818BDC2180095E648 /* rws.c */, 836F6EB818BDC2180095E648 /* rws.c */,
836F6EE818BDC2190095E648 /* rwsd.c */, 836F6EE818BDC2190095E648 /* rwsd.c */,
836F6EE918BDC2190095E648 /* rwx.c */, 836F6EE918BDC2190095E648 /* rwx.c */,
83852B092680247900378854 /* rxws.c */,
836F6EEA18BDC2190095E648 /* s14_sss.c */, 836F6EEA18BDC2190095E648 /* s14_sss.c */,
83AA7F772519C042004C5298 /* sab_streamfile.h */, 83AA7F772519C042004C5298 /* sab_streamfile.h */,
8349A8F11FE6257D00E26435 /* sab.c */, 8349A8F11FE6257D00E26435 /* sab.c */,
@ -2101,7 +2096,6 @@
83A21F82201D8981000F04B9 /* sps_n1.c */, 83A21F82201D8981000F04B9 /* sps_n1.c */,
836F6EF318BDC2190095E648 /* spt_spd.c */, 836F6EF318BDC2190095E648 /* spt_spd.c */,
834FE0D6215C79E9000A5D3D /* sqex_scd_sscf.c */, 834FE0D6215C79E9000A5D3D /* sqex_scd_sscf.c */,
8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */,
836F6EF418BDC2190095E648 /* sqex_scd.c */, 836F6EF418BDC2190095E648 /* sqex_scd.c */,
837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */, 837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */,
83A21F84201D8981000F04B9 /* sqex_sead.c */, 83A21F84201D8981000F04B9 /* sqex_sead.c */,
@ -2333,7 +2327,6 @@
83031EDA243C510500C3F3E0 /* mul_streamfile.h in Headers */, 83031EDA243C510500C3F3E0 /* mul_streamfile.h in Headers */,
83C7281822BC893D00678B4A /* sfh_streamfile.h in Headers */, 83C7281822BC893D00678B4A /* sfh_streamfile.h in Headers */,
834FE0EF215C79ED000A5D3D /* xvag_streamfile.h in Headers */, 834FE0EF215C79ED000A5D3D /* xvag_streamfile.h in Headers */,
8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */,
83031EC4243C50A800C3F3E0 /* circus_decoder_miniz.h in Headers */, 83031EC4243C50A800C3F3E0 /* circus_decoder_miniz.h in Headers */,
8349A91B1FE6258200E26435 /* adx_keys.h in Headers */, 8349A91B1FE6258200E26435 /* adx_keys.h in Headers */,
836F6F4D18BDC2190095E648 /* layout.h in Headers */, 836F6F4D18BDC2190095E648 /* layout.h in Headers */,
@ -2601,7 +2594,6 @@
83E7FD6525EF2B2400683FD2 /* tac.c in Sources */, 83E7FD6525EF2B2400683FD2 /* tac.c in Sources */,
83C7281322BC893D00678B4A /* mta2.c in Sources */, 83C7281322BC893D00678B4A /* mta2.c in Sources */,
8306B0EF20984590000302D4 /* ubi_bao.c in Sources */, 8306B0EF20984590000302D4 /* ubi_bao.c in Sources */,
836F6FBB18BDC2190095E648 /* ngca.c in Sources */,
83AF2CCA26226BA500538240 /* exst.c in Sources */, 83AF2CCA26226BA500538240 /* exst.c in Sources */,
8306B0E220984590000302D4 /* smv.c in Sources */, 8306B0E220984590000302D4 /* smv.c in Sources */,
8349A91E1FE6258200E26435 /* bar.c in Sources */, 8349A91E1FE6258200E26435 /* bar.c in Sources */,
@ -2622,7 +2614,6 @@
835C883622CC17BE001B4B3F /* bwav.c in Sources */, 835C883622CC17BE001B4B3F /* bwav.c in Sources */,
8349A90A1FE6258200E26435 /* sab.c in Sources */, 8349A90A1FE6258200E26435 /* sab.c in Sources */,
83AF2CC926226BA500538240 /* gcub.c in Sources */, 83AF2CC926226BA500538240 /* gcub.c in Sources */,
836F6F6818BDC2190095E648 /* ads.c in Sources */,
8306B08620984518000302D4 /* fadpcm_decoder.c in Sources */, 8306B08620984518000302D4 /* fadpcm_decoder.c in Sources */,
83AB8C761E8072A100086084 /* x360_ast.c in Sources */, 83AB8C761E8072A100086084 /* x360_ast.c in Sources */,
834FE105215C79ED000A5D3D /* xmd.c in Sources */, 834FE105215C79ED000A5D3D /* xmd.c in Sources */,
@ -2738,6 +2729,7 @@
837CEB0423487F2C00E62A4A /* jstm.c in Sources */, 837CEB0423487F2C00E62A4A /* jstm.c in Sources */,
83C7282022BC893D00678B4A /* dcs_wav.c in Sources */, 83C7282022BC893D00678B4A /* dcs_wav.c in Sources */,
8306B0F220984590000302D4 /* ubi_jade.c in Sources */, 8306B0F220984590000302D4 /* ubi_jade.c in Sources */,
83852B0C2680247900378854 /* ads_midway.c in Sources */,
836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */, 836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */,
836F6F2918BDC2190095E648 /* l5_555_decoder.c in Sources */, 836F6F2918BDC2190095E648 /* l5_555_decoder.c in Sources */,
836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */, 836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */,
@ -2794,7 +2786,6 @@
836F704418BDC2190095E648 /* ws_aud.c in Sources */, 836F704418BDC2190095E648 /* ws_aud.c in Sources */,
83031ED2243C50DF00C3F3E0 /* bkhd.c in Sources */, 83031ED2243C50DF00C3F3E0 /* bkhd.c in Sources */,
8373342F23F60D4100DE14DC /* tgc.c in Sources */, 8373342F23F60D4100DE14DC /* tgc.c in Sources */,
83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */,
8373342823F60CDC00DE14DC /* fda.c in Sources */, 8373342823F60CDC00DE14DC /* fda.c in Sources */,
836F6F6D18BDC2190095E648 /* aifc.c in Sources */, 836F6F6D18BDC2190095E648 /* aifc.c in Sources */,
836F702218BDC2190095E648 /* rsd.c in Sources */, 836F702218BDC2190095E648 /* rsd.c in Sources */,
@ -2954,6 +2945,7 @@
832BF82621E0514B006F50F1 /* nwav.c in Sources */, 832BF82621E0514B006F50F1 /* nwav.c in Sources */,
836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */, 836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */,
8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */, 8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */,
83852B0B2680247900378854 /* rxws.c in Sources */,
831BA6181EAC61A500CF89B0 /* adx.c in Sources */, 831BA6181EAC61A500CF89B0 /* adx.c in Sources */,
832BF82321E0514B006F50F1 /* imc.c in Sources */, 832BF82321E0514B006F50F1 /* imc.c in Sources */,
836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */, 836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */,

View File

@ -90,7 +90,9 @@ void decode_ulaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
void decode_ulaw_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_ulaw_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian); void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample); int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
int32_t pcm16_bytes_to_samples(size_t bytes, int channels);
int32_t pcm8_bytes_to_samples(size_t bytes, int channels);
/* psx_decoder */ /* psx_decoder */
@ -159,7 +161,7 @@ STREAMFILE* nwa_get_streamfile(nwa_codec_data* data);
#define MSADPCM_MAX_BLOCK_SIZE 0x800 /* known max and RIFF spec seems to concur, while MS's encoders may be lower (typical stereo: 0x8c, 0x2C, 0x48, 0x400) */ #define MSADPCM_MAX_BLOCK_SIZE 0x800 /* known max and RIFF spec seems to concur, while MS's encoders may be lower (typical stereo: 0x8c, 0x2C, 0x48, 0x400) */
void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do); void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do);
void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int config);
void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels); long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
int msadpcm_check_coefs(STREAMFILE* sf, off_t offset); int msadpcm_check_coefs(STREAMFILE* sf, off_t offset);

View File

@ -22,14 +22,64 @@ static const int16_t msadpcm_coefs[7][2] = {
{ 392, -232 } { 392, -232 }
}; };
/* Decodes MSADPCM as explained in the spec (RIFFNEW doc + msadpcm.c).
/* Decodes MSADPCM as explained in the spec (RIFFNEW / msadpcm.c). * Though RIFFNEW writes "predictor / 256" (DIV), msadpcm.c uses "predictor >> 8" (SHR). They may seem the
* Though RIFFNEW spec uses "predictor / 256", msadpcm.c uses "predictor >> 8" = diffs on negs (silly MS). * same but on negative values SHR gets different results (-128 / 256 = 0; -128 >> 8 = -1) = some output diffs.
* SHR is also true in Windows msadp32.acm decoders (up to Win10), that seem to use same code. * SHR is true in Windows msadp32.acm decoders (up to Win10), while some non-Windows implementations or
* Some non-Windows implementations or engines (like UE4) use DIV though (more accurate). * engines (like UE4) may use DIV.
*
* On invalid coef index, msadpcm.c returns 0 decoded samples but here we clamp and keep on trucking. * On invalid coef index, msadpcm.c returns 0 decoded samples but here we clamp and keep on trucking.
* In theory blocks may be 0-padded and should use samples_per_frame from header, in practice seems to * In theory blocks may be 0-padded and should use samples_per_frame from header, in practice seems to
* decode up to block length or available data. */ * decode up to block length or available data. */
static int16_t msadpcm_adpcm_expand_nibble_shr(VGMSTREAMCHANNEL* stream, uint8_t byte, int shift) {
int32_t hist1, hist2, predicted;
int code = (shift) ?
get_high_nibble_signed(byte) :
get_low_nibble_signed (byte);
hist1 = stream->adpcm_history1_16;
hist2 = stream->adpcm_history2_16;
predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1];
predicted = predicted >> 8; /* 256 = FIXED_POINT_COEF_BASE (uses SHR instead) */
predicted = predicted + (code * stream->adpcm_scale);
predicted = clamp16(predicted); /* lNewSample */
stream->adpcm_history2_16 = stream->adpcm_history1_16;
stream->adpcm_history1_16 = predicted;
stream->adpcm_scale = (msadpcm_steps[code & 0xf] * stream->adpcm_scale) >> 8; /* not diffs vs DIV here (always >=0) */
if (stream->adpcm_scale < 16) /* min delta */
stream->adpcm_scale = 16;
return predicted;
}
static int16_t msadpcm_adpcm_expand_nibble_div(VGMSTREAMCHANNEL* stream, uint8_t byte, int shift) {
int32_t hist1, hist2, predicted;
int code = (shift) ?
get_high_nibble_signed(byte) :
get_low_nibble_signed (byte);
hist1 = stream->adpcm_history1_16;
hist2 = stream->adpcm_history2_16;
predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1];
predicted = predicted / 256; /* 256 = FIXED_POINT_COEF_BASE */
predicted = predicted + (code * stream->adpcm_scale);
predicted = clamp16(predicted); /* lNewSample */
stream->adpcm_history2_16 = stream->adpcm_history1_16;
stream->adpcm_history1_16 = predicted;
stream->adpcm_scale = (msadpcm_steps[code & 0xf] * stream->adpcm_scale) / 256; /* 256 = FIXED_POINT_ADAPTION_BASE */
if (stream->adpcm_scale < 16) /* min delta */
stream->adpcm_scale = 16;
return predicted;
}
void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do) { void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do) {
VGMSTREAMCHANNEL *stream1, *stream2; VGMSTREAMCHANNEL *stream1, *stream2;
uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0}; uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0};
@ -81,40 +131,20 @@ void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first
/* decode nibbles */ /* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) { for (i = first_sample; i < first_sample + samples_to_do; i++) {
int ch; uint8_t byte = get_u8(frame+0x07*2+(i-2));
for (ch = 0; ch < 2; ch++) { *outbuf++ = msadpcm_adpcm_expand_nibble_shr(&vgmstream->ch[0], byte, 1); /* L */
VGMSTREAMCHANNEL* stream = &vgmstream->ch[ch]; *outbuf++ = msadpcm_adpcm_expand_nibble_shr(&vgmstream->ch[1], byte, 0); /* R */
int32_t hist1, hist2, predicted;
uint8_t byte = get_u8(frame+0x07*2+(i-2));
int sample_nibble = (ch == 0) ? /* L = high nibble first (iErrorDelta) */
get_high_nibble_signed(byte) :
get_low_nibble_signed (byte);
hist1 = stream->adpcm_history1_16;
hist2 = stream->adpcm_history2_16;
predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1];
predicted = predicted / 256; /* 256 = FIXED_POINT_COEF_BASE (though MS code uses SHR) */
predicted = predicted + (sample_nibble * stream->adpcm_scale);
outbuf[0] = clamp16(predicted); /* lNewSample */
stream->adpcm_history2_16 = stream->adpcm_history1_16;
stream->adpcm_history1_16 = outbuf[0];
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) / 256; /* 256 = FIXED_POINT_ADAPTION_BASE */
if (stream->adpcm_scale < 16) /* min delta */
stream->adpcm_scale = 16;
outbuf++;
}
} }
} }
void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int config) {
VGMSTREAMCHANNEL* stream = &vgmstream->ch[channel]; VGMSTREAMCHANNEL* stream = &vgmstream->ch[channel];
uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0}; uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0};
int i, frames_in; int i, frames_in;
size_t bytes_per_frame, samples_per_frame; size_t bytes_per_frame, samples_per_frame;
off_t frame_offset; off_t frame_offset;
int is_shr = (config == 0);
/* external interleave (variable size), mono */ /* external interleave (variable size), mono */
bytes_per_frame = vgmstream->frame_size; bytes_per_frame = vgmstream->frame_size;
@ -150,25 +180,12 @@ void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspac
/* decode nibbles */ /* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) { for (i = first_sample; i < first_sample + samples_to_do; i++) {
int32_t hist1, hist2, predicted;
uint8_t byte = get_u8(frame+0x07+(i-2)/2); uint8_t byte = get_u8(frame+0x07+(i-2)/2);
int sample_nibble = (i & 1) ? /* high nibble first */ int shift = !(i & 1); /* high nibble first */
get_low_nibble_signed (byte) :
get_high_nibble_signed(byte);
hist1 = stream->adpcm_history1_16;
hist2 = stream->adpcm_history2_16;
predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1];
predicted = predicted / 256;
predicted = predicted + (sample_nibble * stream->adpcm_scale);
outbuf[0] = clamp16(predicted);
stream->adpcm_history2_16 = stream->adpcm_history1_16;
stream->adpcm_history1_16 = outbuf[0];
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) / 256;
if (stream->adpcm_scale < 16) /* min delta */
stream->adpcm_scale = 16;
outbuf[0] = is_shr ?
msadpcm_adpcm_expand_nibble_shr(stream, byte, shift) :
msadpcm_adpcm_expand_nibble_div(stream, byte, shift);
outbuf += channelspacing; outbuf += channelspacing;
} }
} }
@ -215,26 +232,11 @@ void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacin
} }
/* decode nibbles */ /* decode nibbles */
for (i = first_sample; i < first_sample+samples_to_do; i++) { for (i = first_sample; i < first_sample + samples_to_do; i++) {
int32_t hist1,hist2, predicted;
uint8_t byte = get_u8(frame+0x07+(i-2)/2); uint8_t byte = get_u8(frame+0x07+(i-2)/2);
int sample_nibble = (i & 1) ? /* low nibble first, unlike normal MSADPCM */ int shift = (i & 1); /* low nibble first, unlike normal MSADPCM */
get_high_nibble_signed(byte) :
get_low_nibble_signed (byte);
hist1 = stream->adpcm_history1_16;
hist2 = stream->adpcm_history2_16;
predicted = hist1 * stream->adpcm_coef[0] + hist2 *stream->adpcm_coef[1];
predicted = predicted >> 8; /* not DIV unlike spec */
predicted = predicted + (sample_nibble * stream->adpcm_scale);
outbuf[0] = clamp16(predicted);
stream->adpcm_history2_16 = stream->adpcm_history1_16;
stream->adpcm_history1_16 = outbuf[0];
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) >> 8; /* not DIV but same here (always >=0) */
if (stream->adpcm_scale < 16)
stream->adpcm_scale = 16;
outbuf[0] = msadpcm_adpcm_expand_nibble_shr(stream, byte, shift);
outbuf += channelspacing; outbuf += channelspacing;
} }
} }

View File

@ -216,7 +216,15 @@ void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelsp
} }
} }
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) { int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) {
if (channels <= 0 || bits_per_sample <= 0) return 0; if (channels <= 0 || bits_per_sample <= 0) return 0;
return ((int64_t)bytes * 8) / channels / bits_per_sample; return ((int64_t)bytes * 8) / channels / bits_per_sample;
} }
int32_t pcm16_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 16);
}
int32_t pcm8_bytes_to_samples(size_t bytes, int channels) {
return pcm_bytes_to_samples(bytes, channels, 8);
}

View File

@ -358,7 +358,7 @@ size_t ps_find_padding(STREAMFILE *streamFile, off_t start_offset, size_t data_s
size_t interleave_consumed = 0; size_t interleave_consumed = 0;
if (data_size == 0 || channels == 0 || (channels > 0 && interleave == 0)) if (data_size == 0 || channels == 0 || (channels > 1 && interleave == 0))
return 0; return 0;
offset = start_offset + data_size; offset = start_offset + data_size;
@ -405,7 +405,7 @@ size_t ps_find_padding(STREAMFILE *streamFile, off_t start_offset, size_t data_s
interleave_consumed += 0x10; interleave_consumed += 0x10;
if (interleave_consumed == interleave) { if (interleave_consumed == interleave) {
interleave_consumed = 0; interleave_consumed = 0;
offset -= interleave*(channels - 1); offset -= interleave * (channels - 1);
} }
} }

View File

@ -1290,7 +1290,8 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
if (vgmstream->channels == 1 || vgmstream->coding_type == coding_MSADPCM_int) { if (vgmstream->channels == 1 || vgmstream->coding_type == coding_MSADPCM_int) {
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_msadpcm_mono(vgmstream,buffer+ch, decode_msadpcm_mono(vgmstream,buffer+ch,
vgmstream->channels,vgmstream->samples_into_block, samples_to_do, ch); vgmstream->channels,vgmstream->samples_into_block, samples_to_do, ch,
vgmstream->codec_config);
} }
} }
else if (vgmstream->channels == 2) { else if (vgmstream->channels == 2) {

View File

@ -311,7 +311,7 @@ static const char* extension_list[] = {
"mdsp", "mdsp",
"med", "med",
"mjb", "mjb",
"mi4", "mi4", //fake extension for .mib (renamed, to be removed)
"mib", "mib",
"mic", "mic",
"mihb", "mihb",
@ -353,7 +353,6 @@ static const char* extension_list[] = {
"naac", "naac",
"nds", "nds",
"ndp", //fake extension/header id for .nds "ndp", //fake extension/header id for .nds
"ngca",
"nlsd", "nlsd",
"nop", "nop",
"nps", "nps",
@ -581,7 +580,6 @@ static const char* extension_list[] = {
"wii", "wii",
"wip", //txth/reserved [Colin McRae DiRT (PC)] "wip", //txth/reserved [Colin McRae DiRT (PC)]
"wlv", //txth/reserved [ToeJam & Earl III: Mission to Earth (DC)] "wlv", //txth/reserved [ToeJam & Earl III: Mission to Earth (DC)]
"wma", //common
"wmus", "wmus",
"wp2", "wp2",
"wpd", "wpd",
@ -658,6 +656,7 @@ static const char* common_extension_list[] = {
"ogg", //common "ogg", //common
"opus", //common "opus", //common
"wav", //common "wav", //common
"wma", //common
}; };
@ -921,7 +920,7 @@ static const meta_info meta_info_list[] = {
{meta_DSP_STD, "Nintendo DSP header"}, {meta_DSP_STD, "Nintendo DSP header"},
{meta_DSP_CSTR, "Namco Cstr header"}, {meta_DSP_CSTR, "Namco Cstr header"},
{meta_GCSW, "MileStone GCSW header"}, {meta_GCSW, "MileStone GCSW header"},
{meta_PS2_SShd, "Sony ADS header"}, {meta_ADS, "Sony ADS header"},
{meta_NPS, "Namco NPSF header"}, {meta_NPS, "Namco NPSF header"},
{meta_RWSD, "Nintendo RWSD header (single stream)"}, {meta_RWSD, "Nintendo RWSD header (single stream)"},
{meta_RWAR, "Nintendo RWAR header (single RWAV stream)"}, {meta_RWAR, "Nintendo RWAR header (single RWAV stream)"},
@ -929,7 +928,7 @@ static const meta_info meta_info_list[] = {
{meta_CWAV, "Nintendo CWAV header"}, {meta_CWAV, "Nintendo CWAV header"},
{meta_FWAV, "Nintendo FWAV header"}, {meta_FWAV, "Nintendo FWAV header"},
{meta_XA, "Sony XA header"}, {meta_XA, "Sony XA header"},
{meta_PS2_RXWS, "Sony RXWS header"}, {meta_RXWS, "Sony RXWS header"},
{meta_RAW_INT, "PS2 .int raw header"}, {meta_RAW_INT, "PS2 .int raw header"},
{meta_PS2_OMU, "Alter Echo OMU Header"}, {meta_PS2_OMU, "Alter Echo OMU Header"},
{meta_DSP_STM, "Intelligent Systems STM header"}, {meta_DSP_STM, "Intelligent Systems STM header"},
@ -1080,7 +1079,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_TK5, "Tekken 5 Stream Header"}, {meta_PS2_TK5, "Tekken 5 Stream Header"},
{meta_PS2_SND, "Might and Magic SSND Header"}, {meta_PS2_SND, "Might and Magic SSND Header"},
{meta_PS2_VSF_TTA, "VSF with SMSS Header"}, {meta_PS2_VSF_TTA, "VSF with SMSS Header"},
{meta_ADS, "dhSS Header"}, {meta_ADS_MIDWAY, "Midway ADS header"},
{meta_PS2_MCG, "Gunvari MCG Header"}, {meta_PS2_MCG, "Gunvari MCG Header"},
{meta_ZSD, "ZSD Header"}, {meta_ZSD, "ZSD Header"},
{meta_REDSPARK, "RedSpark Header"}, {meta_REDSPARK, "RedSpark Header"},
@ -1151,7 +1150,6 @@ static const meta_info meta_info_list[] = {
{meta_MSF, "Sony MSF header"}, {meta_MSF, "Sony MSF header"},
{meta_PS3_PAST, "SNDP header"}, {meta_PS3_PAST, "SNDP header"},
{meta_SGXD, "Sony SGXD header"}, {meta_SGXD, "Sony SGXD header"},
{meta_NGCA, "NGCA header"},
{meta_WII_RAS, "RAS header"}, {meta_WII_RAS, "RAS header"},
{meta_PS2_SPM, "SPM header"}, {meta_PS2_SPM, "SPM header"},
{meta_X360_TRA, "Terminal Reality .TRA raw header"}, {meta_X360_TRA, "Terminal Reality .TRA raw header"},

View File

@ -2,15 +2,15 @@
#include "../vgmstream.h" #include "../vgmstream.h"
/* set up for the block at the given offset */ /* set up for the block at the given offset */
void block_update_thp(off_t block_offset, VGMSTREAM *vgmstream) { void block_update_thp(off_t block_offset, VGMSTREAM* vgmstream) {
int i, j; int i, j;
STREAMFILE *streamFile = vgmstream->ch[0].streamfile; STREAMFILE* sf = vgmstream->ch[0].streamfile;
off_t audio_offset; off_t audio_offset;
size_t next_block_size, video_size; size_t next_block_size, video_size;
next_block_size = read_32bitBE(block_offset + 0x00, streamFile); next_block_size = read_u32be(block_offset + 0x00, sf);
/* 0x04: frame size previous */ /* 0x04: frame size previous */
video_size = read_32bitBE(block_offset + 0x08,streamFile); video_size = read_u32be(block_offset + 0x08,sf);
/* 0x0c: audio size */ /* 0x0c: audio size */
audio_offset = block_offset + 0x10 + video_size; audio_offset = block_offset + 0x10 + video_size;
@ -21,21 +21,21 @@ void block_update_thp(off_t block_offset, VGMSTREAM *vgmstream) {
/* block samples can be smaller than block size, normally in the last block, /* block samples can be smaller than block size, normally in the last block,
* but num_samples already takes that into account, so there is no real difference */ * but num_samples already takes that into account, so there is no real difference */
vgmstream->current_block_size = read_32bitBE(audio_offset + 0x00, streamFile); vgmstream->current_block_size = read_u32be(audio_offset + 0x00, sf);
vgmstream->current_block_samples = read_32bitBE(audio_offset + 0x04, streamFile); vgmstream->current_block_samples = read_u32be(audio_offset + 0x04, sf);
audio_offset += 0x08; audio_offset += 0x08;
for (i = 0; i < vgmstream->channels; i++) { for (i = 0; i < vgmstream->channels; i++) {
off_t coef_offset = audio_offset + i*0x20; off_t coef_offset = audio_offset + i*0x20;
off_t hist_offset = audio_offset + vgmstream->channels*0x20 + i*0x04; off_t hist_offset = audio_offset + vgmstream->channels*0x20 + i*0x04;
off_t data_offset = audio_offset + vgmstream->channels*0x24 + i*vgmstream->current_block_size; off_t data_offset = audio_offset + 2*0x24 + i*vgmstream->current_block_size; /* reserved for 2 even in mono [WarioWare Inc. (GC)] */
for (j = 0; j < 16; j++) { for (j = 0; j < 16; j++) {
vgmstream->ch[i].adpcm_coef[j] = read_16bitBE(coef_offset + (j*0x02),streamFile); vgmstream->ch[i].adpcm_coef[j] = read_s16be(coef_offset + (j*0x02),sf);
} }
vgmstream->ch[i].adpcm_history1_16 = read_16bitBE(hist_offset + 0x00,streamFile); vgmstream->ch[i].adpcm_history1_16 = read_s16be(hist_offset + 0x00,sf);
vgmstream->ch[i].adpcm_history2_16 = read_16bitBE(hist_offset + 0x02,streamFile); vgmstream->ch[i].adpcm_history2_16 = read_s16be(hist_offset + 0x02,sf);
vgmstream->ch[i].offset = data_offset; vgmstream->ch[i].offset = data_offset;
} }
} }

View File

@ -44,7 +44,6 @@ VGMSTREAM * init_vgmstream_cstr(STREAMFILE* sf) {
loop_flag = (loop_start >= 0); loop_flag = (loop_start >= 0);
start_offset = 0x20 + 0x60 * channels + first_skip; start_offset = 0x20 + 0x60 * channels + first_skip;
#if 1
/* nonlooped tracks may not set first skip for no reason, but can be tested with initial p/s */ /* nonlooped tracks may not set first skip for no reason, but can be tested with initial p/s */
if (!loop_flag && channels == 2 && first_skip == 0) { if (!loop_flag && channels == 2 && first_skip == 0) {
while (first_skip < 0x800) { while (first_skip < 0x800) {
@ -61,7 +60,7 @@ VGMSTREAM * init_vgmstream_cstr(STREAMFILE* sf) {
} }
if (first_skip > 0 && loop_start >= (interleave - first_skip)) if (first_skip > 0 && loop_start >= (interleave - first_skip))
loop_start = loop_start - (interleave - first_skip); loop_start = loop_start - (interleave - first_skip);
#endif
loop_start = loop_start * 2; loop_start = loop_start * 2;
/* Mr. Driller oddity, unreliable loop flag */ /* Mr. Driller oddity, unreliable loop flag */
@ -97,7 +96,7 @@ VGMSTREAM * init_vgmstream_cstr(STREAMFILE* sf) {
vgmstream->interleave_first_block_size = interleave - first_skip; vgmstream->interleave_first_block_size = interleave - first_skip;
vgmstream->interleave_first_skip = first_skip; vgmstream->interleave_first_skip = first_skip;
vgmstream->meta_type = meta_DSP_CSTR; vgmstream->meta_type = meta_DSP_CSTR;
VGM_LOG("1=%x, =%x\n",vgmstream->interleave_first_block_size, vgmstream->interleave_first_skip);
dsp_read_coefs_be(vgmstream, sf, 0x3c, 0x60); dsp_read_coefs_be(vgmstream, sf, 0x3c, 0x60);
if (!vgmstream_open_stream(vgmstream, sf, start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))

View File

@ -132,6 +132,7 @@ typedef struct {
/* config */ /* config */
int is_memory; int is_memory;
int target_waveid; int target_waveid;
int target_port;
int has_TrackEventTable; int has_TrackEventTable;
int has_CommandTable; int has_CommandTable;
@ -221,7 +222,7 @@ static void add_acb_name(acb_header* acb, int8_t Streaming) {
/* OBJECT HANDLERS */ /* OBJECT HANDLERS */
static int load_acb_waveform(acb_header* acb, int16_t Index) { static int load_acb_waveform(acb_header* acb, int16_t Index) {
uint16_t Id; uint16_t Id, PortNo;
uint8_t Streaming; uint8_t Streaming;
/* read Waveform[Index] */ /* read Waveform[Index] */
@ -231,18 +232,30 @@ static int load_acb_waveform(acb_header* acb, int16_t Index) {
if (acb->is_memory) { if (acb->is_memory) {
if (!utf_query_u16(acb->WaveformTable, Index, "MemoryAwbId", &Id)) if (!utf_query_u16(acb->WaveformTable, Index, "MemoryAwbId", &Id))
goto fail; goto fail;
PortNo = 0xFFFF;
} else { } else {
if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbId", &Id)) if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbId", &Id))
goto fail; goto fail;
if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbPortNo", &PortNo))
PortNo = 0; /* assumed */
} }
} }
else {
PortNo = 0xFFFF;
}
if (!utf_query_u8(acb->WaveformTable, Index, "Streaming", &Streaming)) if (!utf_query_u8(acb->WaveformTable, Index, "Streaming", &Streaming))
goto fail; goto fail;
//;VGM_LOG("ACB: Waveform[%i]: Id=%i, Streaming=%i\n", Index, Id, Streaming); //;VGM_LOG("ACB: Waveform[%i]: Id=%i, PortNo=%i, Streaming=%i\n", Index, Id, PortNo, Streaming);
/* not found but valid */ /* not found but valid */
if (Id != acb->target_waveid) if (Id != acb->target_waveid)
return 1; return 1;
/* correct AWB port (check ignored if set to -1) */
if (acb->target_port >= 0 && PortNo != 0xFFFF && PortNo != acb->target_port)
return 1;
/* must match our target's (0=memory, 1=streaming, 2=memory (prefetch)+stream) */ /* must match our target's (0=memory, 1=streaming, 2=memory (prefetch)+stream) */
if ((acb->is_memory && Streaming == 1) || (!acb->is_memory && Streaming == 0)) if ((acb->is_memory && Streaming == 1) || (!acb->is_memory && Streaming == 0))
return 1; return 1;
@ -694,7 +707,7 @@ fail:
} }
void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is_memory) { void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int port, int is_memory) {
acb_header acb = {0}; acb_header acb = {0};
int i, CueName_rows; int i, CueName_rows;
@ -722,9 +735,12 @@ void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is
* Atom Craft may only target certain .acb versions so some links are later removed * Atom Craft may only target certain .acb versions so some links are later removed
* Not all cues to point to Waveforms, some are just config events/commands. * Not all cues to point to Waveforms, some are just config events/commands.
* .acb link to .awb by name (loaded manually), though they have a checksum/hash/header to validate. * .acb link to .awb by name (loaded manually), though they have a checksum/hash/header to validate.
*
* .acb can contain info for multiple .awb, that are loaded sequentially and assigned "port numbers" (0 to N).
* Both Wave ID and port number must be passed externally to find appropriate song name.
*/ */
//;VGM_LOG("ACB: find waveid=%i\n", waveid); //;VGM_LOG("ACB: find waveid=%i, port=%i\n", waveid, port);
acb.acbFile = sf; acb.acbFile = sf;
@ -732,6 +748,7 @@ void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is
if (!acb.Header) goto fail; if (!acb.Header) goto fail;
acb.target_waveid = waveid; acb.target_waveid = waveid;
acb.target_port = port;
acb.is_memory = is_memory; acb.is_memory = is_memory;
acb.has_TrackEventTable = utf_query_data(acb.Header, 0, "TrackEventTable", NULL,NULL); acb.has_TrackEventTable = utf_query_data(acb.Header, 0, "TrackEventTable", NULL,NULL);
acb.has_CommandTable = utf_query_data(acb.Header, 0, "CommandTable", NULL,NULL); acb.has_CommandTable = utf_query_data(acb.Header, 0, "CommandTable", NULL,NULL);

View File

@ -1,78 +1,80 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../util.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* ADS - from Gauntlet Dark Legacy (GC/Xbox) */ /* .ADS - from Gauntlet Dark Legacy (GC/Xbox) */
VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ads_midway(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count, codec; int loop_flag, channels, codec;
/* check extension, case insensitive */ /* checks */
if (!check_extensions(streamFile,"ads")) goto fail; if (!check_extensions(sf,"ads"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x64685353) /* "dhSS" */
goto fail; /* fake PS2 .ads but BE */
if (read_32bitBE(0x20,streamFile) != 0x64625353) /* "dbSS" */ if (!is_id32be(0x00,sf, "dhSS"))
goto fail; goto fail;
if (!is_id32be(0x20,sf, "dbSS"))
loop_flag = 1; goto fail;
channel_count = read_32bitBE(0x10,streamFile);
loop_flag = 1;
if (channel_count > 2) channels = read_32bitBE(0x10,sf);
goto fail; if (channels > 2)
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); if (!vgmstream) goto fail;
codec = read_32bitBE(0x08,streamFile); vgmstream->sample_rate = read_32bitBE(0x0c,sf);
switch (codec) {
case 0x00000020: /* GC */ codec = read_32bitBE(0x08,sf);
start_offset = 0x28 + 0x60 * channel_count; switch (codec) {
vgmstream->coding_type = coding_NGC_DSP; case 0x00000020: /* GC */
vgmstream->num_samples = read_32bitBE(0x28,streamFile); start_offset = 0x28 + 0x60 * channels;
if (loop_flag) { vgmstream->coding_type = coding_NGC_DSP;
vgmstream->loop_start_sample = 0; vgmstream->num_samples = read_32bitBE(0x28,sf);
vgmstream->loop_end_sample = vgmstream->num_samples; if (loop_flag) {
} vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
if (channel_count == 1) { }
vgmstream->layout_type = layout_none;
} else if (channel_count == 2) { if (channels == 1) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile); } else if (channels == 2) {
} vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x14,sf);
dsp_read_coefs_be(vgmstream, streamFile, 0x44,0x60); }
break;
dsp_read_coefs_be(vgmstream, sf, 0x44,0x60);
case 0x00000021: /* Xbox */ break;
start_offset = 0x28;
vgmstream->coding_type = coding_XBOX_IMA_int; case 0x00000021: /* Xbox */
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitBE(0x24,streamFile), vgmstream->channels); start_offset = 0x28;
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave; vgmstream->coding_type = coding_XBOX_IMA_int;
vgmstream->interleave_block_size = 0x24; vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitBE(0x24,sf), vgmstream->channels);
if (loop_flag) { vgmstream->layout_type = channels == 1 ? layout_none : layout_interleave;
vgmstream->loop_start_sample = 0; vgmstream->interleave_block_size = 0x24;
vgmstream->loop_end_sample = vgmstream->num_samples; if (loop_flag) {
} vgmstream->loop_start_sample = 0;
break; vgmstream->loop_end_sample = vgmstream->num_samples;
}
default: break;
goto fail;
} default:
goto fail;
vgmstream->meta_type = meta_ADS; }
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) vgmstream->meta_type = meta_ADS_MIDWAY;
goto fail;
return vgmstream; if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
fail: return vgmstream;
close_vgmstream(vgmstream);
return NULL; fail:
} close_vgmstream(vgmstream);
return NULL;
}

View File

@ -190,6 +190,7 @@ fail:
static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) { static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) {
int is_memory = (sf_acb != NULL); int is_memory = (sf_acb != NULL);
int port = 0;
/* .acb is passed when loading memory .awb inside .acb */ /* .acb is passed when loading memory .awb inside .acb */
if (!is_memory) { if (!is_memory) {
@ -198,7 +199,7 @@ static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre
int len_name, len_cmp; int len_name, len_cmp;
/* try parsing TXTM if present */ /* try parsing TXTM if present */
sf_acb = read_filemap_file(sf, 0); sf_acb = read_filemap_file_pos(sf, 0, &port);
/* try (name).awb + (name).awb */ /* try (name).awb + (name).awb */
if (!sf_acb) { if (!sf_acb) {
@ -233,27 +234,12 @@ static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre
} }
} }
/* try (name)_(name)_R001.awb + (name).acb [Sengoku Basara Battle Party (Mobile)] */
if (!sf_acb) {
char *cmp = "_R001";
get_streamfile_basename(sf, filename, sizeof(filename));
len_name = strlen(filename);
len_cmp = strlen(cmp);
if (len_name > len_cmp && strcmp(filename + len_name - len_cmp, cmp) == 0) {
filename[(len_name - len_cmp) / 2] = '\0';
strcat(filename, ".acb");
VGM_LOG("%s\n", filename);
sf_acb = open_streamfile_by_filename(sf, filename);
}
}
/* probably loaded */ /* probably loaded */
load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory);
close_streamfile(sf_acb); close_streamfile(sf_acb);
} }
else { else {
load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory);
} }
} }

View File

@ -222,6 +222,7 @@ fail:
static void load_cpk_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) { static void load_cpk_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) {
int is_memory = (sf_acb != NULL); int is_memory = (sf_acb != NULL);
int port = -1; /* cpk has no port numbers */
/* .acb is passed when loading memory .awb inside .acb */ /* .acb is passed when loading memory .awb inside .acb */
if (!is_memory) { if (!is_memory) {
@ -238,11 +239,11 @@ static void load_cpk_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre
return; return;
/* companion .acb probably loaded */ /* companion .acb probably loaded */
load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory);
close_streamfile(sf_acb); close_streamfile(sf_acb);
} }
else { else {
load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory);
} }
} }

View File

@ -1,55 +1,55 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii), Donkey Kong Country Returns (Wii)] */ /* CSMP - Retro Studios sample [Metroid Prime 3 (Wii), Donkey Kong Country Returns (Wii)] */
VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, first_offset = 0x08, chunk_offset; off_t start_offset, first_offset = 0x08, chunk_offset;
int loop_flag, channel_count; int loop_flag, channels;
/* checks */ /* checks */
if (!check_extensions(streamFile, "csmp")) if (!check_extensions(sf, "csmp"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) != 0x43534D50) /* "CSMP" */ if (!is_id32be(0x00, sf, "CSMP"))
goto fail; goto fail;
if (read_32bitBE(0x04, streamFile) != 1) /* version? */ if (read_u32be(0x04, sf) != 1)
goto fail; goto fail;
if (!find_chunk(streamFile, 0x44415441,first_offset,0, &chunk_offset,NULL, 1, 0)) /*"DATA"*/ if (!find_chunk(sf, 0x44415441,first_offset,0, &chunk_offset,NULL, 1, 0)) /*"DATA"*/
goto fail; goto fail;
/* contains standard DSP header, but somehow some validations (start/loop ps) /* contains standard DSP header, but somehow some validations (start/loop ps)
* don't seem to work, so no point to handle as standard DSP */ * don't seem to work, so no point to handle as standard DSP */
channel_count = 1; channels = 1;
loop_flag = read_16bitBE(chunk_offset+0x0c,streamFile); loop_flag = read_s16be(chunk_offset+0x0c,sf);
start_offset = chunk_offset + 0x60; start_offset = chunk_offset + 0x60;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_CSMP; vgmstream->meta_type = meta_CSMP;
vgmstream->sample_rate = read_32bitBE(chunk_offset+0x08,streamFile); vgmstream->sample_rate = read_s32be(chunk_offset+0x08,sf);
vgmstream->num_samples = read_32bitBE(chunk_offset+0x00,streamFile); vgmstream->num_samples = read_s32be(chunk_offset+0x00,sf);
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bitBE(chunk_offset+0x10,streamFile)); vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x10,sf));
vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bitBE(chunk_offset+0x14,streamFile))+1; vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x14,sf)) + 1;
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */ if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
dsp_read_coefs_be(vgmstream, streamFile, chunk_offset+0x1c, 0x00); dsp_read_coefs_be(vgmstream, sf, chunk_offset+0x1c, 0x00);
dsp_read_hist_be(vgmstream, streamFile, chunk_offset+0x40, 0x00); dsp_read_hist_be(vgmstream, sf, chunk_offset+0x40, 0x00);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
fail: fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -35,6 +35,10 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
if (get_streamfile_size(sf) <= 0x1000) if (get_streamfile_size(sf) <= 0x1000)
goto fail; goto fail;
/* reject some formats handled elsewhere (better fail and check there than let buggy FFmpeg take over) */
if (check_extensions(sf, "at3"))
goto fail;
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
/* init ffmpeg */ /* init ffmpeg */

View File

@ -53,7 +53,7 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
* This accepts ktsl2asbin with internal data, or opening external streams as subsongs. * This accepts ktsl2asbin with internal data, or opening external streams as subsongs.
* Some info from KTSR.bt */ * Some info from KTSR.bt */
if (read_u32be(0x00, sf) != 0x4B545352) /* "KTSR" */ if (!is_id32be(0x00, sf, "KTSR"))
goto fail; goto fail;
if (read_u32be(0x04, sf) != 0x777B481A) /* hash(?) id: 0x777B481A=as, 0x0294DDFC=st, 0xC638E69E=gc */ if (read_u32be(0x04, sf) != 0x777B481A) /* hash(?) id: 0x777B481A=as, 0x0294DDFC=st, 0xC638E69E=gc */
goto fail; goto fail;
@ -482,6 +482,7 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) {
case 0xBD888C36: /* config (floats, stream id, etc, may have extended name) */ case 0xBD888C36: /* config (floats, stream id, etc, may have extended name) */
case 0xC9C48EC1: /* unknown (has some string inside like "boss") */ case 0xC9C48EC1: /* unknown (has some string inside like "boss") */
case 0xA9D23BF1: /* "state container", some kind of config/floats, witgh names like 'State_bgm01'..N */ case 0xA9D23BF1: /* "state container", some kind of config/floats, witgh names like 'State_bgm01'..N */
case 0x836FBECA: /* unknown (~0x300, encrypted? table + data) */
break; break;
case 0xC5CCCB70: /* sound (internal data or external stream) */ case 0xC5CCCB70: /* sound (internal data or external stream) */

View File

@ -1,7 +1,7 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF } kwb_codec; typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF, XMA2 } kwb_codec;
typedef struct { typedef struct {
int big_endian; int big_endian;
@ -187,6 +187,27 @@ static VGMSTREAM* init_vgmstream_koei_wavebank(kwb_header* kwb, STREAMFILE* sf_h
break; break;
#ifdef VGM_USE_FFMPEG
case XMA2: {
uint8_t buf[0x100];
size_t bytes, block_size, block_count;
if (kwb->channels > 1) goto fail;
block_size = 0x800; /* ? */
block_count = kwb->stream_size / block_size;
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), vgmstream->num_samples, kwb->stream_size, kwb->channels, kwb->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf_b, buf,bytes, kwb->stream_offset, kwb->stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, sf_b, kwb->stream_offset, kwb->stream_size, 0, 0,0); /* assumed */
break;
}
#endif
#ifdef VGM_USE_ATRAC9 #ifdef VGM_USE_ATRAC9
case AT9: { case AT9: {
atrac9_config cfg = {0}; atrac9_config cfg = {0};
@ -357,7 +378,7 @@ static int parse_type_k4hd(kwb_header* kwb, off_t offset, off_t body_offset, STR
ppva_offset += offset; ppva_offset += offset;
/* PPVA table: */ /* PPVA table: */
if (read_u32be(ppva_offset + 0x00, sf_h) != 0x50505641) /* "PPVA" */ if (!is_id32be(ppva_offset + 0x00, sf_h, "PPVA"))
goto fail; goto fail;
entry_size = read_u32le(ppva_offset + 0x08, sf_h); entry_size = read_u32le(ppva_offset + 0x08, sf_h);
@ -403,8 +424,57 @@ fail:
} }
static int parse_type_sdsd(kwb_header* kwb, off_t offset, off_t body_offset, STREAMFILE* sf_h) { static int parse_type_sdsd(kwb_header* kwb, off_t offset, off_t body_offset, STREAMFILE* sf_h) {
/* has Vers, Head, Prog, Smpl sections (like Sony VABs) off_t smpl_offset, header_offset;
unknown codec, blocked with some common start, variable sized */ int entries, current_subsongs, relative_subsong;
size_t entry_size;
/* format somewhat similar to Sony VABs */
/* 00: SDsdVers */
/* 08: chunk size */
/* 0c: null */
/* 10: SDsdHead */
/* 18: chunk size */
/* 1c: ? size */
/* 20: null */
/* 24: SDsdProg offset ('program'? cues?) */
/* 28: SDsdSmpl offset ('samples'? waves?) */
/* rest: ? */
smpl_offset = read_u32le(offset + 0x28, sf_h);
smpl_offset += offset;
/* Smpl table: */
if (!is_id64be(smpl_offset + 0x00, sf_h, "SDsdSmpl"))
goto fail;
/* 0x08: ? */
entries = read_u32le(smpl_offset + 0x0c, sf_h);
entry_size = 0x9c;
current_subsongs = kwb->total_subsongs;
kwb->total_subsongs += entries;
if (kwb->target_subsong - 1 < current_subsongs || kwb->target_subsong > kwb->total_subsongs)
return 1;
kwb->found = 1;
relative_subsong = kwb->target_subsong - current_subsongs;
header_offset = smpl_offset + 0x10 + (relative_subsong-1) * entry_size;
kwb->stream_offset = read_u32le(header_offset + 0x00, sf_h);
/* 08: ? + channels? */
/* 0c: bps? */
kwb->sample_rate = read_u32le(header_offset + 0x0c, sf_h);
kwb->num_samples = read_u32le(header_offset + 0x10, sf_h) / sizeof(int16_t); /* PCM */
/* rest: ? (flags, etc) */
kwb->stream_size = read_u32le(header_offset + 0x44, sf_h);
kwb->codec = XMA2;
kwb->channels = 1;
kwb->stream_offset += body_offset;
return 1;
fail:
return 0; return 0;
} }
@ -429,8 +499,7 @@ static int parse_type_sdwi(kwb_header* kwb, off_t offset, off_t body_offset, STR
smpl_offset += offset; smpl_offset += offset;
/* Smpl table: */ /* Smpl table: */
if (read_u32be(smpl_offset + 0x00, sf_h) != 0x53447364 && /* "SDsd" */ if (!is_id64be(smpl_offset + 0x00, sf_h, "SDsdSmpl"))
read_u32be(smpl_offset + 0x04, sf_h) != 0x536D706C) /* "Smpl" */
goto fail; goto fail;
/* 0x08: ? */ /* 0x08: ? */
@ -534,7 +603,7 @@ static int parse_kwb(kwb_header* kwb, STREAMFILE* sf_h, STREAMFILE* sf_b) {
goto fail; goto fail;
break; break;
case 0x53447364: /* "SDsd" (PS3? leftover files) */ case 0x53447364: /* "SDsd" [Bladestorm Nightmare (PC)-X360 leftover files] */
if (!parse_type_sdsd(kwb, head_offset, body_offset, sf_h)) if (!parse_type_sdsd(kwb, head_offset, body_offset, sf_h))
goto fail; goto fail;
break; break;

View File

@ -66,8 +66,8 @@ VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_rfrm(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_rfrm(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ads(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ads_container(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_nps(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_nps(STREAMFILE *streamFile);
@ -79,8 +79,8 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_xa(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_xa(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_rxws(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_rxws_badrip(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_raw_int(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_raw_int(STREAMFILE *streamFile);
@ -384,7 +384,7 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ads_midway(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile);
@ -508,8 +508,6 @@ VGMSTREAM * init_vgmstream_ps3_past(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_sgxd(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_sgxd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngca(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_spm(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_spm(STREAMFILE* streamFile);
@ -848,7 +846,7 @@ VGMSTREAM * init_vgmstream_awb(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_awb_memory(STREAMFILE * streamFile, STREAMFILE *acbFile); VGMSTREAM * init_vgmstream_awb_memory(STREAMFILE * streamFile, STREAMFILE *acbFile);
VGMSTREAM * init_vgmstream_acb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_acb(STREAMFILE * streamFile);
void load_acb_wave_name(STREAMFILE *acbFile, VGMSTREAM* vgmstream, int waveid, int is_memory); void load_acb_wave_name(STREAMFILE *acbFile, VGMSTREAM* vgmstream, int waveid, int port, int is_memory);
VGMSTREAM * init_vgmstream_rad(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_rad(STREAMFILE * streamFile);

View File

@ -8,7 +8,9 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) {
off_t start_offset, header_offset = 0; off_t start_offset, header_offset = 0;
size_t stream_size; size_t stream_size;
int loop_flag, channels, sample_rate; int loop_flag, channels, sample_rate;
int32_t loop_start, loop_end;
int total_subsongs, target_subsong = sf->stream_index; int total_subsongs, target_subsong = sf->stream_index;
uint32_t config;
/* checks */ /* checks */
@ -20,12 +22,12 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) {
if (read_u32le(0x00,sh) != get_streamfile_size(sh)) if (read_u32le(0x00,sh) != get_streamfile_size(sh))
goto fail; goto fail;
/* 0x04: unknown */ /* 0x04: flags? (0x04/34*/
/* parse entries */ /* parse entries */
{ {
int i; int i;
int entries = read_s32le(0x08,sh); int entries = read_s32le(0x08,sh); /* may be less than file size, or include dummies (all dummies is possible too) */
total_subsongs = 0; total_subsongs = 0;
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
@ -45,15 +47,20 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) {
} }
loop_flag = 0;
channels = 1;
stream_size = read_u32le(header_offset+0x00, sh); stream_size = read_u32le(header_offset+0x00, sh);
if (read_u32le(header_offset+0x04, sh) != 0) /* stereo flag? */ config = read_u32le(header_offset+0x04, sh); /* volume (0~100), null, null, loop (0/1) */
goto fail;
start_offset = read_u32le(header_offset+0x08, sh); start_offset = read_u32le(header_offset+0x08, sh);
sample_rate = read_u32le(header_offset+0x0c, sh); /* Ace Combat 2 seems to set wrong values but probably their bug */ sample_rate = read_u32le(header_offset+0x0c, sh); /* Ace Combat 2 seems to set wrong values but probably their bug */
loop_flag = (config & 1);
channels = 1;
/* rare [Dr. Seuss Cat in the Hat (PS2)] */
if (loop_flag) {
/* when loop is set ADPCM has loop flags, but rarely appear too without loop set */
loop_flag = ps_find_loop_offsets(sf, start_offset, stream_size, channels, 0, &loop_start, &loop_end);
}
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
@ -62,6 +69,8 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) {
vgmstream->meta_type = meta_MSB_MSH; vgmstream->meta_type = meta_MSB_MSH;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->num_streams = total_subsongs; vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size; vgmstream->stream_size = stream_size;

View File

@ -1,62 +1,62 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* WMSF - Banpresto MSFx wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS3)] */ /* WMSF - Banpresto MSFx wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS3)] */
VGMSTREAM * init_vgmstream_msf_banpresto_wmsf(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_msf_banpresto_wmsf(STREAMFILE* sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL; STREAMFILE* temp_sf = NULL;
off_t subfile_offset = 0x10; off_t subfile_offset = 0x10;
size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; size_t subfile_size = get_streamfile_size(sf) - subfile_offset;
/* checks */ /* checks */
if ( !check_extensions(streamFile,"msf")) if (!check_extensions(sf,"msf"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x574D5346) /* "WMSF" */ if (!is_id32be(0x00,sf,"WMSF"))
goto fail; goto fail;
/* 0x04: size, 0x08: flags? 0x0c: null? */ /* 0x04: size, 0x08: flags? 0x0c: null? */
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL);
if (!temp_streamFile) goto fail; if (!temp_sf) goto fail;
vgmstream = init_vgmstream_msf(temp_streamFile); vgmstream = init_vgmstream_msf(temp_sf);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
return vgmstream; return vgmstream;
fail: fail:
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }
/* 2MSF - Banpresto RIFF wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS4)] */ /* 2MSF - Banpresto RIFF wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS4)] */
VGMSTREAM * init_vgmstream_msf_banpresto_2msf(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_msf_banpresto_2msf(STREAMFILE *sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL; STREAMFILE*temp_sf = NULL;
off_t subfile_offset = 0x14; off_t subfile_offset = 0x14;
size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; size_t subfile_size = get_streamfile_size(sf) - subfile_offset;
/* checks */ /* checks */
if ( !check_extensions(streamFile,"at9")) if ( !check_extensions(sf,"at9"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x324D5346) /* "2MSF" */ if (!is_id32be(0x00,sf,"2MSF"))
goto fail; goto fail;
/* 0x04: size, 0x08: flags? 0x0c: null?, 0x10: 0x01? (BE values even though RIFF is LE) */ /* 0x04: size, 0x08: flags? 0x0c: null?, 0x10: 0x01? (BE values even though RIFF is LE) */
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL);
if (!temp_streamFile) goto fail; if (!temp_sf) goto fail;
vgmstream = init_vgmstream_riff(temp_streamFile); vgmstream = init_vgmstream_riff(temp_sf);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
return vgmstream; return vgmstream;
fail: fail:
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -1,58 +1,58 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (PS3), Metal Gear Solid 3 HD (PS3)] */ /* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (PS3), Metal Gear Solid 3 HD (PS3)] */
VGMSTREAM * init_vgmstream_msf_konami(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_msf_konami(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
uint32_t codec; uint32_t codec;
int loop_flag, channel_count, sample_rate; int loop_flag, channels, sample_rate;
size_t data_size; size_t data_size;
/* checks */ /* checks */
if (!check_extensions(streamFile,"msf")) if (!check_extensions(sf,"msf"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4D534643) /* "MSFC" */ if (!is_id32be(0x00,sf,"MSFC"))
goto fail; goto fail;
start_offset = 0x20; start_offset = 0x20;
codec = read_32bitBE(0x04,streamFile); codec = read_u32be(0x04,sf);
channel_count = read_32bitBE(0x08,streamFile); channels = read_s32be(0x08,sf);
sample_rate = read_32bitBE(0x0c,streamFile); sample_rate = read_s32be(0x0c,sf);
data_size = read_32bitBE(0x10,streamFile); /* without header */ data_size = read_u32be(0x10,sf); /* without header */
if (data_size + start_offset != get_streamfile_size(streamFile)) if (data_size + start_offset != get_streamfile_size(sf))
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_MSF_KONAMI; vgmstream->meta_type = meta_MSF_KONAMI;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
switch (codec) { switch (codec) {
case 0x01: case 0x01:
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); vgmstream->num_samples = ps_bytes_to_samples(data_size, channels);
break; break;
default: default:
goto fail; goto fail;
} }
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
fail: fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -1,68 +0,0 @@
#include "meta.h"
#include "../util.h"
/* NGCA (from GoldenEye 007) */
VGMSTREAM * init_vgmstream_ngca(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("ngca",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x4E474341) /* "NGCA" */
goto fail;
loop_flag = 0;
channel_count = 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x40;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 32000;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (((read_32bitBE(0x4,streamFile))/2) - 1) / 8 * 14;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_NGCA;
vgmstream->allow_dual_stereo = 1;
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0xC+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

@ -1,368 +1,368 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* .ADS - Sony's "Audio Stream" format [Edit Racing (PS2), Evergrace II (PS2), Pri-Saga! Portable (PSP)] */ /* .ADS - Sony's "Audio Stream" format [Edit Racing (PS2), Evergrace II (PS2), Pri-Saga! Portable (PSP)] */
VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ads(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count, sample_rate, interleave, is_loop_samples = 0; int loop_flag, channels, sample_rate, interleave, is_loop_samples = 0;
size_t body_size, stream_size, file_size; size_t body_size, stream_size, file_size;
uint32_t codec, loop_start_sample = 0, loop_end_sample = 0, loop_start_offset = 0, loop_end_offset = 0; uint32_t codec, loop_start_sample = 0, loop_end_sample = 0, loop_start_offset = 0, loop_end_offset = 0;
coding_t coding_type; coding_t coding_type;
int ignore_silent_frame_cavia = 0, ignore_silent_frame_capcom = 0; int ignore_silent_frame_cavia = 0, ignore_silent_frame_capcom = 0;
/* checks */ /* checks */
/* .ads: actual extension /* .ads: actual extension
* .ss2: demuxed videos (fake?) * .ss2: demuxed videos (fake?)
* .pcm: Taisho Mononoke Ibunroku (PS2) * .pcm: Taisho Mononoke Ibunroku (PS2)
* .adx: Armored Core 3 (PS2) * .adx: Armored Core 3 (PS2)
* [no actual extension]: MotoGP (PS2) * (extensionless): MotoGP (PS2)
* .800: Mobile Suit Gundam: The One Year War (PS2) */ * .800: Mobile Suit Gundam: The One Year War (PS2) */
if (!check_extensions(streamFile, "ads,ss2,pcm,adx,,800")) if (!check_extensions(sf, "ads,ss2,pcm,adx,,800"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53536864 && /* "SShd" */ if (!is_id32be(0x00,sf,"SShd") &&
read_32bitBE(0x20,streamFile) != 0x53536264) /* "SSbd" */ !is_id32be(0x20,sf,"SSbd"))
goto fail; goto fail;
if (read_32bitLE(0x04,streamFile) != 0x18 && /* standard header size */ if (read_32bitLE(0x04,sf) != 0x18 && /* standard header size */
read_32bitLE(0x04,streamFile) != 0x20) /* True Fortune (PS2) */ read_32bitLE(0x04,sf) != 0x20) /* True Fortune (PS2) */
goto fail; goto fail;
/* base values (a bit unorderly since devs hack ADS too much and detection is messy) */ /* base values (a bit unorderly since devs hack ADS too much and detection is messy) */
{ {
codec = read_32bitLE(0x08,streamFile); codec = read_32bitLE(0x08,sf);
sample_rate = read_32bitLE(0x0C,streamFile); sample_rate = read_32bitLE(0x0C,sf);
channel_count = read_32bitLE(0x10,streamFile); /* up to 4 [Eve of Extinction (PS2)] */ channels = read_32bitLE(0x10,sf); /* up to 4 [Eve of Extinction (PS2)] */
interleave = read_32bitLE(0x14,streamFile); /* set even when mono */ interleave = read_32bitLE(0x14,sf); /* set even when mono */
switch(codec) { switch(codec) {
case 0x01: /* official definition */ case 0x01: /* official definition */
case 0x80000001: /* [Evergrace II (PS2), but not other From Soft games] */ case 0x80000001: /* [Evergrace II (PS2), but not other From Soft games] */
coding_type = coding_PCM16LE; coding_type = coding_PCM16LE;
/* Angel Studios/Rockstar San Diego videos codec hijack [Red Dead Revolver (PS2), Spy Hunter 2 (PS2)] */ /* Angel Studios/Rockstar San Diego videos codec hijack [Red Dead Revolver (PS2), Spy Hunter 2 (PS2)] */
if (sample_rate == 12000 && interleave == 0x200) { if (sample_rate == 12000 && interleave == 0x200) {
sample_rate = 48000; sample_rate = 48000;
interleave = 0x40; interleave = 0x40;
coding_type = coding_DVI_IMA_int; coding_type = coding_DVI_IMA_int;
/* should try to detect IMA data but it's not so easy, this works ok since /* should try to detect IMA data but it's not so easy, this works ok since
* no known games use these settings, videos normally are 48000/24000hz */ * no known games use these settings, videos normally are 48000/24000hz */
} }
break; break;
case 0x10: /* official definition */ case 0x10: /* official definition */
case 0x02: /* Capcom games extension, stereo only [Megaman X7 (PS2), Breath of Fire V (PS2), Clock Tower 3 (PS2)] */ case 0x02: /* Capcom games extension, stereo only [Megaman X7 (PS2), Breath of Fire V (PS2), Clock Tower 3 (PS2)] */
coding_type = coding_PSX; coding_type = coding_PSX;
break; break;
case 0x00: /* PCM16BE from official docs, probably never used */ case 0x00: /* PCM16BE from official docs, probably never used */
default: default:
VGM_LOG("ADS: unknown codec\n"); VGM_LOG("ADS: unknown codec\n");
goto fail; goto fail;
} }
} }
/* sizes */ /* sizes */
{ {
file_size = get_streamfile_size(streamFile); file_size = get_streamfile_size(sf);
body_size = read_32bitLE(0x24,streamFile); body_size = read_32bitLE(0x24,sf);
/* bigger than file_size in rare cases, even if containing all data (ex. Megaman X7's SY04.ADS) */ /* bigger than file_size in rare cases, even if containing all data (ex. Megaman X7's SY04.ADS) */
if (body_size + 0x28 > file_size) { if (body_size + 0x28 > file_size) {
body_size = file_size - 0x28; body_size = file_size - 0x28;
} }
/* True Fortune: weird stream size */ /* True Fortune: weird stream size */
if (body_size * 2 == file_size - 0x18) { if (body_size * 2 == file_size - 0x18) {
body_size = (body_size * 2) - 0x10; body_size = (body_size * 2) - 0x10;
} }
stream_size = body_size; stream_size = body_size;
} }
/* offset */ /* offset */
{ {
start_offset = 0x28; start_offset = 0x28;
/* start padding (body size is ok, may have end padding) [Evergrace II (PS2), Armored Core 3 (PS2)] */ /* start padding (body size is ok, may have end padding) [Evergrace II (PS2), Armored Core 3 (PS2)] */
/* detection depends on files being properly ripped, so broken/cut files won't play ok */ /* detection depends on files being properly ripped, so broken/cut files won't play ok */
if (file_size - body_size >= 0x800) { if (file_size - body_size >= 0x800) {
start_offset = 0x800; /* aligned to sector */ start_offset = 0x800; /* aligned to sector */
/* too much end padding, happens in Super Galdelic Hour's SEL.ADS, maybe in bad rips too */ /* too much end padding, happens in Super Galdelic Hour's SEL.ADS, maybe in bad rips too */
VGM_ASSERT(file_size - body_size > 0x8000, "ADS: big end padding %x\n", file_size - body_size); VGM_ASSERT(file_size - body_size > 0x8000, "ADS: big end padding %x\n", file_size - body_size);
} }
/* "ADSC" container */ /* "ADSC" container */
if (coding_type == coding_PSX if (coding_type == coding_PSX
&& read_32bitLE(0x28,streamFile) == 0x1000 /* real start */ && read_32bitLE(0x28,sf) == 0x1000 /* real start */
&& read_32bitLE(0x2c,streamFile) == 0 && read_32bitLE(0x2c,sf) == 0
&& read_32bitLE(0x1008,streamFile) != 0) { && read_32bitLE(0x1008,sf) != 0) {
int i; int i;
int is_adsc = 1; int is_adsc = 1;
/* should be empty up to data start */ /* should be empty up to data start */
for (i = 0; i < 0xFDC/4; i++) { for (i = 0; i < 0xFDC/4; i++) {
if (read_32bitLE(0x2c+(i*4),streamFile) != 0) { if (read_32bitLE(0x2c+(i*4),sf) != 0) {
is_adsc = 0; is_adsc = 0;
break; break;
} }
} }
if (is_adsc) { if (is_adsc) {
start_offset = 0x1000 - 0x08; /* remove "ADSC" alignment */ start_offset = 0x1000 - 0x08; /* remove "ADSC" alignment */
/* stream_size doesn't count start offset padding */ /* stream_size doesn't count start offset padding */
} }
} }
} }
/* loops */ /* loops */
{ {
uint32_t loop_start, loop_end; uint32_t loop_start, loop_end;
loop_start = read_32bitLE(0x18,streamFile); loop_start = read_32bitLE(0x18,sf);
loop_end = read_32bitLE(0x1C,streamFile); loop_end = read_32bitLE(0x1C,sf);
loop_flag = 0; loop_flag = 0;
/* detect loops the best we can; docs say those are loop block addresses, /* detect loops the best we can; docs say those are loop block addresses,
* but each maker does whatever (no games seem to use PS-ADPCM loop flags though) */ * but each maker does whatever (no games seem to use PS-ADPCM loop flags though) */
if (loop_start != 0xFFFFFFFF && loop_end == 0xFFFFFFFF) { if (loop_start != 0xFFFFFFFF && loop_end == 0xFFFFFFFF) {
if (codec == 0x02) { /* Capcom codec */ if (codec == 0x02) { /* Capcom codec */
/* Capcom games: loop_start is address * 0x10 [Mega Man X7, Breath of Fire V, Clock Tower 3] */ /* Capcom games: loop_start is address * 0x10 [Mega Man X7, Breath of Fire V, Clock Tower 3] */
loop_flag = ((loop_start * 0x10) + 0x200 < body_size); /* near the end (+0x20~80) means no loop */ loop_flag = ((loop_start * 0x10) + 0x200 < body_size); /* near the end (+0x20~80) means no loop */
loop_start_offset = loop_start * 0x10; loop_start_offset = loop_start * 0x10;
ignore_silent_frame_capcom = 1; ignore_silent_frame_capcom = 1;
} }
else if (read_32bitBE(0x28,streamFile) == 0x50414421) { /* "PAD!" padding until 0x800 */ else if (read_32bitBE(0x28,sf) == 0x50414421) { /* "PAD!" padding until 0x800 */
/* Super Galdelic Hour: loop_start is PCM bytes */ /* Super Galdelic Hour: loop_start is PCM bytes */
loop_flag = 1; loop_flag = 1;
loop_start_sample = loop_start / 2 / channel_count; loop_start_sample = loop_start / 2 / channels;
is_loop_samples = 1; is_loop_samples = 1;
} }
else if ((loop_start % 0x800 == 0) && loop_start > 0) { /* sector-aligned, min/0 is 0x800 */ else if ((loop_start % 0x800 == 0) && loop_start > 0) { /* sector-aligned, min/0 is 0x800 */
/* cavia games: loop_start is offset [Drakengard 1/2, GITS: Stand Alone Complex] */ /* cavia games: loop_start is offset [Drakengard 1/2, GITS: Stand Alone Complex] */
/* offset is absolute from the "cavia stream format" container that adjusts ADS start */ /* offset is absolute from the "cavia stream format" container that adjusts ADS start */
loop_flag = 1; loop_flag = 1;
loop_start_offset = loop_start - 0x800; loop_start_offset = loop_start - 0x800;
ignore_silent_frame_cavia = 1; ignore_silent_frame_cavia = 1;
} }
else if (loop_start % 0x800 != 0 || loop_start == 0) { /* not sector aligned */ else if (loop_start % 0x800 != 0 || loop_start == 0) { /* not sector aligned */
/* Katakamuna: loop_start is address * 0x10 */ /* Katakamuna: loop_start is address * 0x10 */
loop_flag = 1; loop_flag = 1;
loop_start_offset = loop_start * 0x10; loop_start_offset = loop_start * 0x10;
} }
} }
else if (loop_start != 0xFFFFFFFF && loop_end != 0xFFFFFFFF else if (loop_start != 0xFFFFFFFF && loop_end != 0xFFFFFFFF
&& loop_end > 0) { /* ignore Kamen Rider Blade and others */ && loop_end > 0) { /* ignore Kamen Rider Blade and others */
#if 0 #if 0
//todo improve detection to avoid clashing with address*0x20 //todo improve detection to avoid clashing with address*0x20
if (loop_end == body_size / 0x10) { /* always body_size? but not all files should loop */ if (loop_end == body_size / 0x10) { /* always body_size? but not all files should loop */
/* Akane Iro ni Somaru Saka - Parallel: loops is address * 0x10 */ /* Akane Iro ni Somaru Saka - Parallel: loops is address * 0x10 */
loop_flag = 1; loop_flag = 1;
loop_start_offset = loop_start * 0x10; loop_start_offset = loop_start * 0x10;
loop_end_offset = loop_end * 0x10; loop_end_offset = loop_end * 0x10;
} }
#endif #endif
if (loop_end <= body_size / 0x200 && coding_type == coding_PCM16LE) { /* close to body_size */ if (loop_end <= body_size / 0x200 && coding_type == coding_PCM16LE) { /* close to body_size */
/* Gofun-go no Sekai: loops is address * 0x200 */ /* Gofun-go no Sekai: loops is address * 0x200 */
loop_flag = 1; loop_flag = 1;
loop_start_offset = loop_start * 0x200; loop_start_offset = loop_start * 0x200;
loop_end_offset = loop_end * 0x200; loop_end_offset = loop_end * 0x200;
} }
else if (loop_end <= body_size / 0x70 && coding_type == coding_PCM16LE) { /* close to body_size */ else if (loop_end <= body_size / 0x70 && coding_type == coding_PCM16LE) { /* close to body_size */
/* Armored Core - Nexus: loops is address * 0x70 */ /* Armored Core - Nexus: loops is address * 0x70 */
loop_flag = 1; loop_flag = 1;
loop_start_offset = loop_start * 0x70; loop_start_offset = loop_start * 0x70;
loop_end_offset = loop_end * 0x70; loop_end_offset = loop_end * 0x70;
} }
else if (loop_end <= body_size / 0x20 && coding_type == coding_PCM16LE) { /* close to body_size */ else if (loop_end <= body_size / 0x20 && coding_type == coding_PCM16LE) { /* close to body_size */
/* Armored Core - Nine Breaker: loops is address * 0x20 */ /* Armored Core - Nine Breaker: loops is address * 0x20 */
loop_flag = 1; loop_flag = 1;
loop_start_offset = loop_start * 0x20; loop_start_offset = loop_start * 0x20;
loop_end_offset = loop_end * 0x20; loop_end_offset = loop_end * 0x20;
} }
else if (loop_end <= body_size / 0x20 && coding_type == coding_PSX) { else if (loop_end <= body_size / 0x20 && coding_type == coding_PSX) {
/* various games: loops is address * 0x20 [Fire Pro Wrestling Returns, A.C.E. - Another Century's Episode] */ /* various games: loops is address * 0x20 [Fire Pro Wrestling Returns, A.C.E. - Another Century's Episode] */
loop_flag = 1; loop_flag = 1;
loop_start_offset = loop_start * 0x20; loop_start_offset = loop_start * 0x20;
loop_end_offset = loop_end * 0x20; loop_end_offset = loop_end * 0x20;
} }
else if (loop_end <= body_size / 0x10 && coding_type == coding_PSX else if (loop_end <= body_size / 0x10 && coding_type == coding_PSX
&& (read_32bitBE(0x28 + loop_end*0x10 + 0x10 + 0x00, streamFile) == 0x00077777 || && (read_32bitBE(0x28 + loop_end*0x10 + 0x10 + 0x00, sf) == 0x00077777 ||
read_32bitBE(0x28 + loop_end*0x10 + 0x20 + 0x00, streamFile) == 0x00077777)) { read_32bitBE(0x28 + loop_end*0x10 + 0x20 + 0x00, sf) == 0x00077777)) {
/* not-quite-looping sfx, ending with a "non-looping PS-ADPCM end frame" [Kono Aozora ni Yakusoku, Chanter] */ /* not-quite-looping sfx, ending with a "non-looping PS-ADPCM end frame" [Kono Aozora ni Yakusoku, Chanter] */
loop_flag = 0; loop_flag = 0;
} }
else if ((loop_end > body_size / 0x20 && coding_type == coding_PSX) || else if ((loop_end > body_size / 0x20 && coding_type == coding_PSX) ||
(loop_end > body_size / 0x70 && coding_type == coding_PCM16LE)) { (loop_end > body_size / 0x70 && coding_type == coding_PCM16LE)) {
/* various games: loops in samples [Eve of Extinction, Culdcept, WWE Smackdown! 3] */ /* various games: loops in samples [Eve of Extinction, Culdcept, WWE Smackdown! 3] */
loop_flag = 1; loop_flag = 1;
loop_start_sample = loop_start; loop_start_sample = loop_start;
loop_end_sample = loop_end; loop_end_sample = loop_end;
is_loop_samples = 1; is_loop_samples = 1;
} }
} }
//todo Jet Ion Grand Prix seems to have some loop-like values at 0x28 //todo Jet Ion Grand Prix seems to have some loop-like values at 0x28
//todo Yoake mae yori Ruriiro na has loops in unknown format //todo Yoake mae yori Ruriiro na has loops in unknown format
} }
/* most games have empty PS-ADPCM frames in the last interleave block that should be skipped for smooth looping */ /* most games have empty PS-ADPCM frames in the last interleave block that should be skipped for smooth looping */
if (coding_type == coding_PSX) { if (coding_type == coding_PSX) {
off_t offset, min_offset; off_t offset, min_offset;
offset = start_offset + stream_size; offset = start_offset + stream_size;
min_offset = offset - interleave; min_offset = offset - interleave;
do { do {
offset -= 0x10; offset -= 0x10;
if (read_8bit(offset+0x01,streamFile) == 0x07) { if (read_8bit(offset+0x01,sf) == 0x07) {
stream_size -= 0x10*channel_count;/* ignore don't decode flag/padding frame (most common) [ex. Capcom games] */ stream_size -= 0x10*channels;/* ignore don't decode flag/padding frame (most common) [ex. Capcom games] */
} }
else if (read_32bitBE(offset+0x00,streamFile) == 0x00000000 && read_32bitBE(offset+0x04,streamFile) == 0x00000000 && else if (read_32bitBE(offset+0x00,sf) == 0x00000000 && read_32bitBE(offset+0x04,sf) == 0x00000000 &&
read_32bitBE(offset+0x08,streamFile) == 0x00000000 && read_32bitBE(offset+0x0c,streamFile) == 0x00000000) { read_32bitBE(offset+0x08,sf) == 0x00000000 && read_32bitBE(offset+0x0c,sf) == 0x00000000) {
stream_size -= 0x10*channel_count; /* ignore null frame [ex. A.C.E. Another Century Episode 1/2/3] */ stream_size -= 0x10*channels; /* ignore null frame [ex. A.C.E. Another Century Episode 1/2/3] */
} }
else if (read_32bitBE(offset+0x00,streamFile) == 0x00007777 && read_32bitBE(offset+0x04,streamFile) == 0x77777777 && else if (read_32bitBE(offset+0x00,sf) == 0x00007777 && read_32bitBE(offset+0x04,sf) == 0x77777777 &&
read_32bitBE(offset+0x08,streamFile) == 0x77777777 && read_32bitBE(offset+0x0c,streamFile) == 0x77777777) { read_32bitBE(offset+0x08,sf) == 0x77777777 && read_32bitBE(offset+0x0c,sf) == 0x77777777) {
stream_size -= 0x10*channel_count; /* ignore padding frame [ex. Akane Iro ni Somaru Saka - Parallel] */ stream_size -= 0x10*channels; /* ignore padding frame [ex. Akane Iro ni Somaru Saka - Parallel] */
} }
else if (read_32bitBE(offset+0x00,streamFile) == 0x0C020000 && read_32bitBE(offset+0x04,streamFile) == 0x00000000 && else if (read_32bitBE(offset+0x00,sf) == 0x0C020000 && read_32bitBE(offset+0x04,sf) == 0x00000000 &&
read_32bitBE(offset+0x08,streamFile) == 0x00000000 && read_32bitBE(offset+0x0c,streamFile) == 0x00000000 && read_32bitBE(offset+0x08,sf) == 0x00000000 && read_32bitBE(offset+0x0c,sf) == 0x00000000 &&
ignore_silent_frame_cavia) { ignore_silent_frame_cavia) {
stream_size -= 0x10*channel_count; /* ignore silent frame [ex. cavia games] */ stream_size -= 0x10*channels; /* ignore silent frame [ex. cavia games] */
} }
else if (read_32bitBE(offset+0x00,streamFile) == 0x0C010000 && read_32bitBE(offset+0x04,streamFile) == 0x00000000 && else if (read_32bitBE(offset+0x00,sf) == 0x0C010000 && read_32bitBE(offset+0x04,sf) == 0x00000000 &&
read_32bitBE(offset+0x08,streamFile) == 0x00000000 && read_32bitBE(offset+0x0c,streamFile) == 0x00000000 && read_32bitBE(offset+0x08,sf) == 0x00000000 && read_32bitBE(offset+0x0c,sf) == 0x00000000 &&
ignore_silent_frame_capcom) { ignore_silent_frame_capcom) {
stream_size -= 0x10*channel_count; /* ignore silent frame [ex. Capcom games] */ stream_size -= 0x10*channels; /* ignore silent frame [ex. Capcom games] */
} }
else { else {
break; /* standard frame */ break; /* standard frame */
} }
} }
while(offset > min_offset); while(offset > min_offset);
/* don't bother fixing loop_end_offset since will be adjusted to num_samples later, if needed */ /* don't bother fixing loop_end_offset since will be adjusted to num_samples later, if needed */
} }
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
vgmstream->coding_type = coding_type; vgmstream->coding_type = coding_type;
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = interleave;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_SShd; vgmstream->meta_type = meta_ADS;
switch(coding_type) { switch(coding_type) {
case coding_PCM16LE: case coding_PCM16LE:
vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16); vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels);
break; break;
case coding_PSX: case coding_PSX:
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels);
break; break;
case coding_DVI_IMA_int: case coding_DVI_IMA_int:
vgmstream->num_samples = ima_bytes_to_samples(stream_size, channel_count); vgmstream->num_samples = ima_bytes_to_samples(stream_size, channels);
break; break;
default: default:
goto fail; goto fail;
} }
if (vgmstream->loop_flag) { if (vgmstream->loop_flag) {
if (is_loop_samples) { if (is_loop_samples) {
vgmstream->loop_start_sample = loop_start_sample; vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample; vgmstream->loop_end_sample = loop_end_sample;
} }
else { else {
switch(vgmstream->coding_type) { switch(vgmstream->coding_type) {
case coding_PCM16LE: case coding_PCM16LE:
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start_offset,channel_count,16); vgmstream->loop_start_sample = pcm16_bytes_to_samples(loop_start_offset, channels);
vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end_offset,channel_count,16); vgmstream->loop_end_sample = pcm16_bytes_to_samples(loop_end_offset, channels);
break; break;
case coding_PSX: case coding_PSX:
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start_offset,channel_count); vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start_offset, channels);
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end_offset,channel_count); vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end_offset, channels);
break; break;
default: default:
goto fail; goto fail;
} }
} }
/* when loop_end = 0xFFFFFFFF */ /* when loop_end = 0xFFFFFFFF */
if (vgmstream->loop_end_sample == 0) if (vgmstream->loop_end_sample == 0)
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
/* happens even when loops are directly samples, loops sound fine (ex. Culdcept) */ /* happens even when loops are directly samples, loops sound fine (ex. Culdcept) */
if (vgmstream->loop_end_sample > vgmstream->num_samples) if (vgmstream->loop_end_sample > vgmstream->num_samples)
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
} }
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
fail: fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }
/* ****************************************************************************** */ /* ****************************************************************************** */
/* ADS in containers */ /* ADS in containers */
VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ads_container(STREAMFILE* sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL; STREAMFILE* temp_sf = NULL;
off_t subfile_offset; off_t subfile_offset;
size_t subfile_size; size_t subfile_size;
/* checks */ /* checks */
if (!check_extensions(streamFile, "ads")) if (!check_extensions(sf, "ads"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) == 0x41445343 && /* "ADSC" */ if (read_32bitBE(0x00,sf) == 0x41445343 && /* "ADSC" */
read_32bitBE(0x04,streamFile) == 0x01000000) { read_32bitBE(0x04,sf) == 0x01000000) {
/* Kenka Bancho 2, Kamen Rider Hibiki/Kabuto, Shinjuku no Okami */ /* Kenka Bancho 2, Kamen Rider Hibiki/Kabuto, Shinjuku no Okami */
subfile_offset = 0x08; subfile_offset = 0x08;
} }
else if (read_32bitBE(0x00,streamFile) == 0x63617669 && /* "cavi" */ else if (read_32bitBE(0x00,sf) == 0x63617669 && /* "cavi" */
read_32bitBE(0x04,streamFile) == 0x61207374 && /* "a st" */ read_32bitBE(0x04,sf) == 0x61207374 && /* "a st" */
read_32bitBE(0x08,streamFile) == 0x7265616D) { /* "ream" */ read_32bitBE(0x08,sf) == 0x7265616D) { /* "ream" */
/* cavia games: Drakengard 1/2, Dragon Quest Yangus, GITS: Stand Alone Complex */ /* cavia games: Drakengard 1/2, Dragon Quest Yangus, GITS: Stand Alone Complex */
subfile_offset = 0x7d8; subfile_offset = 0x7d8;
} }
else { else {
goto fail; goto fail;
} }
subfile_size = get_streamfile_size(streamFile) - subfile_offset; subfile_size = get_streamfile_size(sf) - subfile_offset;
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, NULL);
if (!temp_streamFile) goto fail; if (!temp_sf) goto fail;
vgmstream = init_vgmstream_ps2_ads(temp_streamFile); vgmstream = init_vgmstream_ads(temp_sf);
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
return vgmstream; return vgmstream;
fail: fail:
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -794,6 +794,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
/* UE4 uses interleaved mono MSADPCM, try to autodetect without breaking normal MSADPCM */ /* UE4 uses interleaved mono MSADPCM, try to autodetect without breaking normal MSADPCM */
if (fmt.coding_type == coding_MSADPCM && is_ue4_msadpcm(vgmstream, sf, &fmt, fact_sample_count, start_offset)) { if (fmt.coding_type == coding_MSADPCM && is_ue4_msadpcm(vgmstream, sf, &fmt, fact_sample_count, start_offset)) {
vgmstream->coding_type = coding_MSADPCM_int; vgmstream->coding_type = coding_MSADPCM_int;
vgmstream->codec_config = 1; /* mark as UE4 MSADPCM */
vgmstream->frame_size = fmt.block_size; vgmstream->frame_size = fmt.block_size;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = get_ue4_msadpcm_interleave(sf, &fmt, start_offset, data_size); vgmstream->interleave_block_size = get_ue4_msadpcm_interleave(sf, &fmt, start_offset, data_size);

View File

@ -3,52 +3,53 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* RXWS - from Sony SCEI PS2 games (Okage: Shadow King, Genji, Bokura no Kazoku) */ /* RXWS - from Sony SCEI PS2 games (Okage: Shadow King, Genji, Bokura no Kazoku) */
VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_rxws(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
STREAMFILE * streamHeader = NULL; STREAMFILE* sh = NULL;
off_t start_offset, chunk_offset, name_offset = 0; off_t start_offset, chunk_offset, name_offset = 0;
size_t stream_size, chunk_size; size_t stream_size, chunk_size;
int loop_flag = 0, channel_count, is_separate = 0, type, sample_rate; int loop_flag = 0, channels, is_separate = 0, type, sample_rate;
int32_t num_samples, loop_start; int32_t num_samples, loop_start;
int total_subsongs, target_subsong = streamFile->stream_index; int total_subsongs, target_subsong = sf->stream_index;
/* checks */ /* checks */
/* .xws: header and data /* .xws: header and data
* .xwh+xwb: header + data (.bin+dat are also found in Wild Arms 4/5) */ * .xwh+xwb: header + data (.bin+dat are also found in Wild Arms 4/5) */
if (!check_extensions(streamFile,"xws,xwb")) if (!check_extensions(sf,"xws,xwb"))
goto fail; goto fail;
is_separate = check_extensions(streamFile,"xwb"); is_separate = check_extensions(sf,"xwb");
/* xwh+xwb: use xwh as header; otherwise use the current file */ /* xwh+xwb: use xwh as header; otherwise use the current file */
if (is_separate) { if (is_separate) {
/* extra check to reject Microsoft's XWB faster */ /* extra check to reject Microsoft's XWB faster */
if ((read_32bitBE(0x00,streamFile) == 0x57424E44) || /* "WBND" (LE) */ if (is_id32be(0x00,sf,"WBND") || /* (LE) */
(read_32bitBE(0x00,streamFile) == 0x444E4257)) /* "DNBW" (BE) */ is_id32be(0x00,sf,"DNBW")) /* (BE) */
goto fail; goto fail;
streamHeader = open_streamfile_by_ext(streamFile, "xwh"); sh = open_streamfile_by_ext(sf, "xwh");
if (!streamHeader) goto fail; if (!sh) goto fail;
} else { } else {
streamHeader = streamFile; sh = sf;
} }
if (read_32bitBE(0x00,streamHeader) != 0x52585753) /* "RXWS" */ if (!is_id32be(0x00,sh,"RXWS"))
goto fail; goto fail;
/* file size (just the .xwh/xws) */ /* file size (just the .xwh/xws) */
if (read_32bitLE(0x04,streamHeader)+0x10 != get_streamfile_size(streamHeader)) if (read_u32le(0x04,sh) + 0x10 != get_streamfile_size(sh))
goto fail; goto fail;
/* 0x08(4): version (0x100/0x200), 0x0C: null */ /* 0x08: version (0x100/0x200)
* 0x0C: null */
/* typical chunks: FORM, FTXT, MARK, BODY (for .xws) */ /* typical chunks: FORM, FTXT, MARK, BODY (for .xws) */
if (read_32bitBE(0x10,streamHeader) != 0x464F524D) /* "FORM", main header (always first) */ if (!is_id32be(0x10,sh,"FORM")) /* main header (always first) */
goto fail; goto fail;
chunk_size = read_32bitLE(0x10+0x04,streamHeader); /* size - 0x10 */ chunk_size = read_u32le(0x10+0x04,sh); /* size - 0x10 */
/* 0x08 version (0x100), 0x0c: null */ /* 0x08 version (0x100), 0x0c: null */
chunk_offset = 0x20; chunk_offset = 0x20;
/* check multi-streams */ /* check multi-streams */
total_subsongs = read_32bitLE(chunk_offset+0x00,streamHeader); total_subsongs = read_s32le(chunk_offset+0x00,sh);
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
@ -58,15 +59,18 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
off_t header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong-1); /* position in FORM */ off_t header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong-1); /* position in FORM */
off_t stream_offset, next_stream_offset, data_offset = 0; off_t stream_offset, next_stream_offset, data_offset = 0;
type = read_8bit(header_offset+0x00, streamHeader); type = read_u8(header_offset+0x00, sh);
/* 0x01(1): unknown (always 0x1c), 0x02(2): flags? (usually 8002/0002, & 0x01 if looped) */ /* 0x01: unknown (always 0x1c) */
/* 0x04(4): vol/pan stuff? (0x00007F7F), 0x08(1): null?, 0x0c(4): null? */ /* 0x02: flags? (usually 8002/0002, & 0x01 if looped) */
channel_count = read_8bit(header_offset+0x09, streamHeader); /* 0x04: vol/pan stuff? (0x00007F7F) */
sample_rate = (uint16_t)read_16bitLE(header_offset+0x0a,streamHeader); /* 0x08: null? */
stream_offset = read_32bitLE(header_offset+0x10,streamHeader); channels = read_u8(header_offset+0x09, sh);
num_samples = read_32bitLE(header_offset+0x14,streamHeader); /* 0x0c: null? */
loop_start = read_32bitLE(header_offset+0x18,streamHeader); sample_rate = read_u16le(header_offset+0x0a,sh);
loop_flag = (loop_start != 0xFFFFFFFF); stream_offset = read_u32le(header_offset+0x10,sh);
num_samples = read_s32le(header_offset+0x14,sh);
loop_start = read_s32le(header_offset+0x18,sh);
loop_flag = (loop_start >= 0);
/* find data start and size */ /* find data start and size */
if (is_separate) { if (is_separate) {
@ -75,21 +79,21 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
else { else {
off_t current_chunk = 0x10; off_t current_chunk = 0x10;
/* note the extra 0x10 in chunk_size/offsets */ /* note the extra 0x10 in chunk_size/offsets */
while (current_chunk < get_streamfile_size(streamFile)) { while (current_chunk < get_streamfile_size(sf)) {
if (read_32bitBE(current_chunk,streamFile) == 0x424F4459) { /* "BODY" chunk_type */ if (is_id32be(current_chunk,sf, "BODY")) {
data_offset = 0x10 + current_chunk; data_offset = 0x10 + current_chunk;
break; break;
} }
current_chunk += 0x10 + read_32bitLE(current_chunk+4,streamFile); current_chunk += 0x10 + read_u32le(current_chunk+4,sf);
} }
if (!data_offset) goto fail; if (!data_offset) goto fail;
} }
if (target_subsong == total_subsongs) { if (target_subsong == total_subsongs) {
next_stream_offset = get_streamfile_size(is_separate ? streamFile : streamHeader) - data_offset; next_stream_offset = get_streamfile_size(is_separate ? sf : sh) - data_offset;
} else { } else {
off_t next_header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong); off_t next_header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong);
next_stream_offset = read_32bitLE(next_header_offset+0x10,streamHeader); next_stream_offset = read_u32le(next_header_offset+0x10,sh);
} }
stream_size = next_stream_offset - stream_offset; stream_size = next_stream_offset - stream_offset;
@ -97,24 +101,24 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
} }
/* get stream name (always follows FORM) */ /* get stream name (always follows FORM) */
if (read_32bitBE(0x10+0x10 + chunk_size,streamHeader) == 0x46545854) { /* "FTXT" */ if (is_id32be(0x10+0x10 + chunk_size,sh, "FTXT")) {
chunk_offset = 0x10+0x10 + chunk_size + 0x10; chunk_offset = 0x10+0x10 + chunk_size + 0x10;
if (read_32bitLE(chunk_offset+0x00,streamHeader) == total_subsongs) { if (read_s32le(chunk_offset+0x00,sh) == total_subsongs) {
name_offset = chunk_offset + read_32bitLE(chunk_offset+0x04 + (target_subsong-1)*0x04,streamHeader); name_offset = chunk_offset + read_u32le(chunk_offset+0x04 + (target_subsong-1)*0x04,sh);
} }
} }
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_RXWS;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
vgmstream->num_streams = total_subsongs; vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size; vgmstream->stream_size = stream_size;
vgmstream->meta_type = meta_PS2_RXWS;
if (name_offset) if (name_offset)
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader); read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sh);
switch (type) { switch (type) {
case 0x00: /* PS-ADPCM */ case 0x00: /* PS-ADPCM */
@ -122,8 +126,8 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->num_samples = ps_bytes_to_samples(num_samples, channel_count); vgmstream->num_samples = ps_bytes_to_samples(num_samples, channels);
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count); vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channels);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
break; break;
@ -132,8 +136,8 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2; vgmstream->interleave_block_size = 0x2;
vgmstream->num_samples = pcm_bytes_to_samples(num_samples, channel_count, 16); vgmstream->num_samples = pcm_bytes_to_samples(num_samples, channels, 16);
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16); vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channels, 16);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
break; break;
@ -141,11 +145,11 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
case 0x02: { /* ATRAC3 */ case 0x02: { /* ATRAC3 */
int block_align, encoder_delay; int block_align, encoder_delay;
block_align = 0xc0 * channel_count; block_align = 0xc0 * channels;
encoder_delay = 1024 + 69*2; /* observed default */ encoder_delay = 1024 + 69*2; /* observed default */
vgmstream->num_samples = num_samples - encoder_delay; vgmstream->num_samples = num_samples - encoder_delay;
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
@ -160,57 +164,58 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
} }
/* open the file for reading */ /* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
if (is_separate && streamHeader) close_streamfile(streamHeader); if (is_separate && sh) close_streamfile(sh);
return vgmstream; return vgmstream;
fail: fail:
if (is_separate && streamHeader) close_streamfile(streamHeader); if (is_separate && sh) close_streamfile(sh);
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }
/* .RXW - legacy fake ext/header for poorly split XWH+XWB files generated by old tools (incorrect header/chunk sizes) */ /* .RXW - legacy fake ext/header for poorly split XWH+XWB files generated by old tools (incorrect header/chunk sizes) */
VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_rxws_badrip(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
int loop_flag=0, channel_count; int loop_flag=0, channels;
off_t start_offset; off_t start_offset;
/* check extension, case insensitive */ /* check extension, case insensitive */
if (!check_extensions(streamFile,"rxw")) goto fail; if (!check_extensions(sf,"rxw"))
/* check RXWS/FORM Header */
if (!((read_32bitBE(0x00,streamFile) == 0x52585753) &&
(read_32bitBE(0x10,streamFile) == 0x464F524D)))
goto fail; goto fail;
loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF); /* check RXWS/FORM Header */
channel_count=2; /* Always stereo files */ if (!((read_32bitBE(0x00,sf) == 0x52585753) &&
(read_32bitBE(0x10,sf) == 0x464F524D)))
goto fail;
loop_flag = (read_32bitLE(0x3C,sf)!=0xFFFFFFFF);
channels=2; /* Always stereo files */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x2E,streamFile); vgmstream->sample_rate = read_32bitLE(0x2E,sf);
vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2; vgmstream->num_samples = (read_32bitLE(0x38,sf)*28/16)/2;
/* Get loop point values */ /* Get loop point values */
if(vgmstream->loop_flag) { if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14; vgmstream->loop_start_sample = read_32bitLE(0x3C,sf)/16*14;
vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14; vgmstream->loop_end_sample = read_32bitLE(0x38,sf)/16*14;
} }
vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10; vgmstream->interleave_block_size = read_32bitLE(0x1c,sf)+0x10;
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_RXWS; vgmstream->meta_type = meta_RXWS;
start_offset = 0x40; start_offset = 0x40;
/* open the file for reading */ /* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -1,38 +1,39 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
#include "../layout/layout.h" #include "../layout/layout.h"
#include "sqex_scd_streamfile.h"
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource); static void scd_ogg_v2_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource);
static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource); static void scd_ogg_v3_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource);
#endif #endif
/* SCD - Square-Enix games (FF XIII, XIV) */ /* SCD - Square-Enix games (FF XIII, XIV) */
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0; off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0;
int32_t stream_size, extradata_size, loop_start, loop_end; int32_t stream_size, extradata_size, loop_start, loop_end;
int loop_flag = 0, channel_count, codec, sample_rate; int loop_flag = 0, channels, codec, sample_rate;
int version, target_entry, aux_chunk_count; int version, target_entry, aux_chunk_count;
int total_subsongs, target_subsong = streamFile->stream_index; int total_subsongs, target_subsong = sf->stream_index;
int big_endian;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* check extension, case insensitive */ /* checks */
if ( !check_extensions(streamFile, "scd") ) if (!check_extensions(sf, "scd"))
goto fail; goto fail;
/** main header **/ /** main header **/
if (read_32bitBE(0x00,streamFile) != 0x53454442 && /* "SEDB" */ if (!is_id32be(0x00,sf, "SEDB") &&
read_32bitBE(0x04,streamFile) != 0x53534346) /* "SSCF" */ !is_id32be(0x04,sf, "SSCF"))
goto fail; goto fail;
if (read_8bit(0x0c,streamFile) == 0x01) { /* big endian flag */ big_endian = read_u8(0x0c,sf) == 0x01;
if (big_endian) { /* big endian flag */
//size_offset = 0x14; //size_offset = 0x14;
read_32bit = read_32bitBE; read_32bit = read_32bitBE;
read_16bit = read_16bitBE; read_16bit = read_16bitBE;
@ -42,21 +43,20 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
read_16bit = read_16bitLE; read_16bit = read_16bitLE;
} }
/* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */
if (read_8bit(0x0d,streamFile) != 0x04)
goto fail;
/* v2: FFXIII demo (PS3), FFT0 test files (PC); v3: common; v4: Kingdom Hearts 2.8 (PS4) */ /* v2: FFXIII demo (PS3), FFT0 test files (PC); v3: common; v4: Kingdom Hearts 2.8 (PS4) */
version = read_32bit(0x08,streamFile); version = read_32bit(0x08,sf);
if (version != 2 && version != 3 && version != 4) if (version != 2 && version != 3 && version != 4)
goto fail; goto fail;
tables_offset = read_16bit(0x0e,streamFile); /* usually 0x30 or 0x20 */ /* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */
if (read_u8(0x0d,sf) != 0x04)
goto fail;
tables_offset = read_16bit(0x0e,sf); /* usually 0x30 or 0x20 */
#if 0 #if 0
/* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */ /* FFXIII music_68tak.ps3.scd is 0x80 shorter? */
/* check file size with header value */ if (read_32bit(size_offset,sf) != get_streamfile_size(sf))
if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile))
goto fail; goto fail;
#endif #endif
@ -80,8 +80,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* find meta_offset in table3 (headers) and total subsongs */ /* find meta_offset in table3 (headers) and total subsongs */
{ {
int i; int i;
int headers_entries = read_16bit(tables_offset+0x04,streamFile); int headers_entries = read_16bit(tables_offset+0x04,sf);
off_t headers_offset = read_32bit(tables_offset+0x0c,streamFile); off_t headers_offset = read_32bit(tables_offset+0x0c,sf);
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
total_subsongs = 0; total_subsongs = 0;
@ -89,9 +89,9 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* manually find subsongs as entries can be dummy (ex. sfx banks in FF XIV or FF Type-0) */ /* manually find subsongs as entries can be dummy (ex. sfx banks in FF XIV or FF Type-0) */
for (i = 0; i < headers_entries; i++) { for (i = 0; i < headers_entries; i++) {
off_t entry_offset = read_32bit(headers_offset + i*0x04,streamFile); off_t entry_offset = read_32bit(headers_offset + i*0x04,sf);
if (read_32bit(entry_offset+0x0c,streamFile) == -1) if (read_32bit(entry_offset+0x0c,sf) == -1)
continue; /* codec -1 when dummy */ continue; /* codec -1 when dummy */
total_subsongs++; total_subsongs++;
@ -105,15 +105,15 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
} }
/** stream header **/ /** stream header **/
stream_size = read_32bit(meta_offset+0x00,streamFile); stream_size = read_32bit(meta_offset+0x00,sf);
channel_count = read_32bit(meta_offset+0x04,streamFile); channels = read_32bit(meta_offset+0x04,sf);
sample_rate = read_32bit(meta_offset+0x08,streamFile); sample_rate = read_32bit(meta_offset+0x08,sf);
codec = read_32bit(meta_offset+0x0c,streamFile); codec = read_32bit(meta_offset+0x0c,sf);
loop_start = read_32bit(meta_offset+0x10,streamFile); loop_start = read_32bit(meta_offset+0x10,sf);
loop_end = read_32bit(meta_offset+0x14,streamFile); loop_end = read_32bit(meta_offset+0x14,sf);
extradata_size = read_32bit(meta_offset+0x18,streamFile); extradata_size = read_32bit(meta_offset+0x18,sf);
aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile); aux_chunk_count = read_32bit(meta_offset+0x1c,sf);
/* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */ /* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */
loop_flag = (loop_end > 0); loop_flag = (loop_end > 0);
@ -127,19 +127,19 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
} }
/* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */ /* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */
if (aux_chunk_count && read_32bitBE(extradata_offset, streamFile) == 0x4D41524B) { /* "MARK" */ if (aux_chunk_count && is_id32be(extradata_offset, sf, "MARK")) {
extradata_offset += read_32bit(extradata_offset+0x04, streamFile); extradata_offset += read_32bit(extradata_offset+0x04, sf);
} }
/* find name if possible */ /* find name if possible */
if (version == 4) { if (version == 4) {
int info_entries = read_16bit(tables_offset+0x00,streamFile); int info_entries = read_16bit(tables_offset+0x00,sf);
int headers_entries = read_16bit(tables_offset+0x04,streamFile); int headers_entries = read_16bit(tables_offset+0x04,sf);
off_t info_offset = tables_offset+0x20; off_t info_offset = tables_offset+0x20;
/* not very exact as table1 and table3 entries may differ in V3, not sure about V4 */ /* not very exact as table1 and table3 entries may differ in V3, not sure about V4 */
if (info_entries == headers_entries) { if (info_entries == headers_entries) {
off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,streamFile); off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,sf);
name_offset = entry_offset+0x30; name_offset = entry_offset+0x30;
} }
} }
@ -157,17 +157,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
ovmi.disable_reordering = 1; /* already ordered */ ovmi.disable_reordering = 1; /* already ordered */
/* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */ /* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */
ogg_version = read_8bit(extradata_offset + 0x00, streamFile); ogg_version = read_u8(extradata_offset + 0x00, sf);
/* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */ /* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */
ogg_byte = read_8bit(extradata_offset + 0x02, streamFile); ogg_byte = read_u8(extradata_offset + 0x02, sf);
/* 0x03(1): ? in v3 */ /* 0x03(1): ? in v3 */
if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */ if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */
ovmi.stream_size = stream_size; ovmi.stream_size = stream_size;
} }
else { /* 0x20 header, then seek table */ else { /* 0x20 header, then seek table */
size_t seek_table_size = read_32bit(extradata_offset+0x10, streamFile); size_t seek_table_size = read_32bit(extradata_offset+0x10, sf);
size_t vorb_header_size = read_32bit(extradata_offset+0x14, streamFile); size_t vorb_header_size = read_32bit(extradata_offset+0x14, sf);
/* 0x18(4): ? (can be 0) */ /* 0x18(4): ? (can be 0) */
if ((extradata_offset-meta_offset) + seek_table_size + vorb_header_size != extradata_size) if ((extradata_offset-meta_offset) + seek_table_size + vorb_header_size != extradata_size)
@ -192,16 +192,16 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
} }
/* actual Ogg init */ /* actual Ogg init */
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, start_offset, &ovmi);
if (ogg_vgmstream && name_offset) if (ogg_vgmstream && name_offset)
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile); read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, sf);
return ogg_vgmstream; return ogg_vgmstream;
} }
#endif #endif
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
@ -209,7 +209,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->stream_size = stream_size; vgmstream->stream_size = stream_size;
vgmstream->meta_type = meta_SQEX_SCD; vgmstream->meta_type = meta_SQEX_SCD;
if (name_offset) if (name_offset)
read_string(vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile); read_string(vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf);
switch (codec) { switch (codec) {
case 0x01: /* PCM */ case 0x01: /* PCM */
@ -217,10 +217,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02; vgmstream->interleave_block_size = 0x02;
vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16); vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channels, 16);
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16); vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channels, 16);
vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channel_count, 16); vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channels, 16);
} }
break; break;
@ -229,10 +229,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels);
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count); vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channels);
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channel_count); vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channels);
} }
break; break;
@ -246,7 +246,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */ cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */
cfg.data_size = stream_size; cfg.data_size = stream_size;
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg); vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
@ -268,9 +268,9 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */ case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->frame_size = read_16bit(extradata_offset + 0x0c, streamFile); vgmstream->frame_size = read_16bit(extradata_offset + 0x0c, sf);
/* WAVEFORMATEX in extradata_offset */ /* WAVEFORMATEX in extradata_offset */
if (!msadpcm_check_coefs(streamFile, extradata_offset + 0x14)) if (!msadpcm_check_coefs(sf, extradata_offset + 0x14))
goto fail; goto fail;
vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->frame_size, vgmstream->channels); vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->frame_size, vgmstream->channels);
@ -282,83 +282,53 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
case 0x0A: /* DSP ADPCM [Dragon Quest X (Wii)] */ case 0x0A: /* DSP ADPCM [Dragon Quest X (Wii)] */
case 0x15: { /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */ case 0x15: { /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */
const off_t interleave_size = 0x800;
const off_t stride_size = interleave_size * channel_count;
int i;
size_t total_size;
layered_layout_data * data = NULL;
/* interleaved DSPs including the header (so the first 0x800 is 0x60 header + 0x740 data)
* so interleave layout can't used; we'll setup de-interleaving streamfiles as layers/channels instead */
//todo this could be simplified using a block layout or adding interleave_first_block
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_layered; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x800;
vgmstream->interleave_first_skip = 0x60;
vgmstream->interleave_first_block_size = vgmstream->interleave_block_size - vgmstream->interleave_first_skip;
/* read from the first DSP header and verify other channel headers */ /* standard dsp header at start_offset */
{ dsp_read_coefs_be(vgmstream, sf, start_offset+0x1c, vgmstream->interleave_block_size);
total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2; /* rounded nibbles / 2 */ dsp_read_hist_be(vgmstream, sf, start_offset+0x40, vgmstream->interleave_block_size);
vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end + 1;
}
for (i = 1; i < channel_count; i++) { vgmstream->num_samples = read_32bit(start_offset+0x00,sf);
if ((read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size || if (loop_flag) {
read_32bitBE(start_offset+interleave_size*i+0x00,streamFile) != vgmstream->num_samples) { vgmstream->loop_start_sample = loop_start;
goto fail; vgmstream->loop_end_sample = loop_end + 1;
}
}
} }
/* init layout */ start_offset += vgmstream->interleave_first_skip;
data = init_layout_layered(channel_count);
if (!data) goto fail;
vgmstream->layout_data = data;
/* open each layer subfile */
for (i = 0; i < channel_count; i++) {
STREAMFILE* temp_streamFile = setup_scd_dsp_streamfile(streamFile, start_offset+interleave_size*i, interleave_size, stride_size, total_size);
if (!temp_streamFile) goto fail;
data->layers[i] = init_vgmstream_ngc_dsp_std(temp_streamFile);
close_streamfile(temp_streamFile);
if (!data->layers[i]) goto fail;
}
/* setup layered VGMSTREAMs */
if (!setup_layout_layered(data))
goto fail;
break; break;
} }
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */ case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */
ffmpeg_codec_data *ffmpeg_data = NULL; uint8_t buf[0x100];
uint8_t buf[200];
int32_t bytes; int32_t bytes;
/* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */ /* extradata:
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1); * 0x00: fmt0x166 header (BE X360, LE XBone)
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size); * 0x34: seek table */
if (!ffmpeg_data) goto fail; bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, extradata_offset,0x34, stream_size, sf, big_endian);
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = ffmpeg_data->totalSamples; xma2_parse_fmt_chunk_extra(sf, extradata_offset, NULL, &vgmstream->num_samples, NULL, NULL, big_endian);
vgmstream->loop_start_sample = loop_start; vgmstream->loop_start_sample = loop_start; /* same loops in chunk */
vgmstream->loop_end_sample = loop_end; //todo +1? vgmstream->loop_end_sample = loop_end;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,stream_size, 0, 0,0); /* samples are ok, loops? */ xma_fix_raw_samples(vgmstream, sf, start_offset, stream_size, extradata_offset, 1,1);
break; break;
} }
case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */ case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */
int fact_samples = 0; int fact_samples = 0;
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, &fact_samples); vgmstream->codec_data = init_ffmpeg_atrac3_riff(sf, start_offset, &fact_samples);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
@ -377,17 +347,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* post header has various typical ATRAC9 values */ /* post header has various typical ATRAC9 values */
cfg.channels = vgmstream->channels; cfg.channels = vgmstream->channels;
cfg.config_data = read_32bit(extradata_offset+0x0c,streamFile); cfg.config_data = read_32bit(extradata_offset+0x0c,sf);
cfg.encoder_delay = read_32bit(extradata_offset+0x18,streamFile); cfg.encoder_delay = read_32bit(extradata_offset+0x18,sf);
vgmstream->codec_data = init_atrac9(&cfg); vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9; vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */ vgmstream->num_samples = read_32bit(extradata_offset+0x10,sf); /* loop values above are also weird and ignored */
vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile); vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, sf);
vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) + 1; vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, sf) + 1;
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample -= cfg.encoder_delay; vgmstream->loop_start_sample -= cfg.encoder_delay;
vgmstream->loop_end_sample -= cfg.encoder_delay; vgmstream->loop_end_sample -= cfg.encoder_delay;
@ -403,7 +373,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
} }
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -415,7 +385,7 @@ fail:
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) { static void scd_ogg_v2_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource) {
uint8_t *ptr8 = ptr; uint8_t *ptr8 = ptr;
size_t bytes_read = size * nmemb; size_t bytes_read = size * nmemb;
ogg_vorbis_io *io = datasource; ogg_vorbis_io *io = datasource;
@ -438,7 +408,7 @@ static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb,
} }
} }
static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) { static void scd_ogg_v3_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource) {
/* V3 decryption table found in the .exe of FF XIV Heavensward */ /* V3 decryption table found in the .exe of FF XIV Heavensward */
static const uint8_t scd_ogg_v3_lookuptable[256] = { static const uint8_t scd_ogg_v3_lookuptable[256] = {
0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F 0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F

View File

@ -1,92 +0,0 @@
#ifndef _SQEX_SCD_STREAMFILE_H_
#define _SQEX_SCD_STREAMFILE_H_
#include "../streamfile.h"
typedef struct {
off_t start_physical_offset; /* interleaved data start, for this substream */
size_t interleave_block_size; /* max size that can be read before encountering other substreams */
size_t stride_size; /* step size between interleave blocks (interleave*channels) */
size_t total_size; /* final size of the deinterleaved substream */
} scd_dsp_io_data;
/* Handles deinterleaving of complete files, skipping portions or other substreams. */
static size_t scd_dsp_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, scd_dsp_io_data* data) {
size_t total_read = 0;
while (length > 0) {
size_t to_read;
size_t length_available;
off_t block_num;
off_t intrablock_offset;
off_t physical_offset;
block_num = offset / data->interleave_block_size;
intrablock_offset = offset % data->interleave_block_size;
physical_offset = data->start_physical_offset + block_num*data->stride_size + intrablock_offset;
length_available = data->interleave_block_size - intrablock_offset;
if (length < length_available) {
to_read = length;
}
else {
to_read = length_available;
}
if (to_read > 0) {
size_t bytes_read;
bytes_read = read_streamfile(dest, physical_offset, to_read, streamfile);
total_read += bytes_read;
if (bytes_read != to_read) {
return total_read;
}
dest += bytes_read;
offset += bytes_read;
length -= bytes_read;
}
}
return total_read;
}
static size_t scd_dsp_io_size(STREAMFILE *streamfile, scd_dsp_io_data* data) {
return data->total_size;
}
static STREAMFILE* setup_scd_dsp_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t interleave_block_size, size_t stride_size, size_t total_size) {
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
scd_dsp_io_data io_data = {0};
size_t io_data_size = sizeof(scd_dsp_io_data);
io_data.start_physical_offset = start_offset;
io_data.interleave_block_size = interleave_block_size;
io_data.stride_size = stride_size;
io_data.total_size = total_size;
/* setup subfile */
new_streamFile = open_wrap_streamfile(streamFile);
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, scd_dsp_io_read,scd_dsp_io_size);
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,"dsp");
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
return temp_streamFile;
fail:
close_streamfile(temp_streamFile);
return NULL;
}
#endif /* _SCD_STREAMFILE_H_ */

View File

@ -2,12 +2,12 @@
#include "../layout/layout.h" #include "../layout/layout.h"
/* THP - Nintendo movie format found in GC/Wii games */ /* THP - Nintendo movie format found in GC/Wii games */
VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_thp(STREAMFILE* sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, component_type_offset, component_data_offset; off_t start_offset, component_type_offset, component_data_offset;
uint32_t version, max_audio_size; uint32_t version, max_audio_size;
int num_components; int num_components;
int loop_flag, channel_count; int loop_flag, channels;
int i; int i;
@ -15,14 +15,14 @@ VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) {
/* .thp: actual extension /* .thp: actual extension
* .dsp: fake extension? * .dsp: fake extension?
* (extensionless): Fragile (Wii) */ * (extensionless): Fragile (Wii) */
if (!check_extensions(streamFile, "thp,dsp,")) if (!check_extensions(sf, "thp,dsp,"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x54485000) /* "THP\0" */ if (!is_id32be(0x00,sf, "THP\0"))
goto fail; goto fail;
version = read_32bitBE(0x04,streamFile); /* 16b+16b major/minor */ version = read_u32be(0x04,sf); /* 16b+16b major/minor */
/* 0x08: max buffer size */ /* 0x08: max buffer size */
max_audio_size = read_32bitBE(0x0C,streamFile); max_audio_size = read_u32be(0x0C,sf);
/* 0x10: fps in float */ /* 0x10: fps in float */
/* 0x14: block count */ /* 0x14: block count */
/* 0x18: first block size */ /* 0x18: first block size */
@ -33,19 +33,19 @@ VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) {
if (max_audio_size == 0) /* no sound */ if (max_audio_size == 0) /* no sound */
goto fail; goto fail;
component_type_offset = read_32bitBE(0x20,streamFile); component_type_offset = read_u32be(0x20,sf);
/* 0x24: block offsets table offset (optional, for seeking) */ /* 0x24: block offsets table offset (optional, for seeking) */
start_offset = read_32bitBE(0x28,streamFile); start_offset = read_u32be(0x28,sf);
/* 0x2c: last block offset */ /* 0x2c: last block offset */
/* first component "type" x16 then component headers */ /* first component "type" x16 then component headers */
num_components = read_32bitBE(component_type_offset,streamFile); num_components = read_u32be(component_type_offset,sf);
component_type_offset += 0x04; component_type_offset += 0x04;
component_data_offset = component_type_offset + 0x10; component_data_offset = component_type_offset + 0x10;
/* parse "component" (data that goes into blocks) */ /* parse "component" (data that goes into blocks) */
for (i = 0; i < num_components; i++) { for (i = 0; i < num_components; i++) {
int type = read_8bit(component_type_offset + i,streamFile); int type = read_u8(component_type_offset + i,sf);
if (type == 0x00) { /* video */ if (type == 0x00) { /* video */
if (version == 0x00010000) if (version == 0x00010000)
@ -73,24 +73,24 @@ VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) {
* adjusted, but we can't detect Wii (non adjusted) .thp tho */ * adjusted, but we can't detect Wii (non adjusted) .thp tho */
loop_flag = 0; loop_flag = 0;
channel_count = read_32bitBE(component_data_offset + 0x00,streamFile); channels = read_u32be(component_data_offset + 0x00,sf);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitBE(component_data_offset + 0x04,streamFile); vgmstream->sample_rate = read_u32be(component_data_offset + 0x04,sf);
vgmstream->num_samples = read_32bitBE(component_data_offset + 0x08,streamFile); vgmstream->num_samples = read_u32be(component_data_offset + 0x08,sf);
vgmstream->meta_type = meta_THP; vgmstream->meta_type = meta_THP;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_thp; vgmstream->layout_type = layout_blocked_thp;
/* coefs are in every block */ /* coefs are in every block */
vgmstream->full_block_size = read_32bitBE(0x18,streamFile); /* next block size */ vgmstream->full_block_size = read_u32be(0x18,sf); /* next block size */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -599,75 +599,32 @@ fail:
} }
static size_t silence_io_read(STREAMFILE* streamfile, uint8_t *dest, off_t offset, size_t length, void* data) {
int i;
for (i = 0; i < length; i++) {
dest[i] = 0;
}
return length; /* pretend we read zeroes */
}
static size_t silence_io_size(STREAMFILE* streamfile, void* data) {
return 0x7FFFFFF; /* whatevs */
}
static STREAMFILE* setup_silence_streamfile(STREAMFILE* sf) {
STREAMFILE* temp_sf = NULL, *new_sf = NULL;
/* setup custom streamfile */
new_sf = open_wrap_streamfile(sf);
if (!new_sf) goto fail;
temp_sf = new_sf;
new_sf = open_io_streamfile(temp_sf, NULL,0, silence_io_read,silence_io_size);
if (!new_sf) goto fail;
temp_sf = new_sf;
return temp_sf;
fail:
close_streamfile(temp_sf);
return NULL;
}
static VGMSTREAM* init_vgmstream_ubi_bao_silence(ubi_bao_header* bao, STREAMFILE* sf) { static VGMSTREAM* init_vgmstream_ubi_bao_silence(ubi_bao_header* bao, STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
STREAMFILE* temp_sf = NULL; int channels, sample_rate;
int channel_count, sample_rate; int32_t num_samples;
channel_count = bao->channels; /* by default silences don't have settings */
channels = bao->channels;
if (channels == 0)
channels = 2;
sample_rate = bao->sample_rate; sample_rate = bao->sample_rate;
/* by default silences don't have settings so let's pretend */
if (channel_count == 0)
channel_count = 2;
if (sample_rate == 0) if (sample_rate == 0)
sample_rate = 48000; sample_rate = 48000;
num_samples = bao->duration * sample_rate;
/* build the VGMSTREAM */ /* init the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, 0); vgmstream = init_vgmstream_silence(channels, sample_rate, num_samples);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_UBI_BAO; vgmstream->meta_type = meta_UBI_BAO;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = bao->duration * sample_rate;
vgmstream->num_streams = bao->total_subsongs; vgmstream->num_streams = bao->total_subsongs;
vgmstream->stream_size = vgmstream->num_samples * channel_count * 0x02; /* PCM size */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
temp_sf = setup_silence_streamfile(sf);
if ( !vgmstream_open_stream(vgmstream, temp_sf, 0x00) )
goto fail;
close_streamfile(temp_sf);
return vgmstream; return vgmstream;
fail: fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
close_streamfile(temp_sf);
return vgmstream; return vgmstream;
} }

View File

@ -1526,74 +1526,33 @@ fail:
return NULL; return NULL;
} }
static size_t silence_io_read(STREAMFILE* sf, uint8_t *dest, off_t offset, size_t length, void* data) {
int i;
for (i = 0; i < length; i++) {
dest[i] = 0;
}
return length; /* pretend we read zeroes */
}
static size_t silence_io_size(STREAMFILE* sf, void* data) {
return 0x7FFFFFF; /* whatevs */
}
static STREAMFILE* setup_silence_streamfile(STREAMFILE* sf) {
STREAMFILE *temp_sf = NULL, *new_sf = NULL;
/* setup custom streamfile */
new_sf = open_wrap_streamfile(sf);
if (!new_sf) goto fail;
temp_sf = new_sf;
new_sf = open_io_streamfile(temp_sf, NULL,0, silence_io_read,silence_io_size);
if (!new_sf) goto fail;
temp_sf = new_sf;
return temp_sf;
fail:
close_streamfile(temp_sf);
return NULL;
}
static VGMSTREAM* init_vgmstream_ubi_sb_silence(ubi_sb_header* sb, STREAMFILE* sf_index, STREAMFILE* sf) { static VGMSTREAM* init_vgmstream_ubi_sb_silence(ubi_sb_header* sb, STREAMFILE* sf_index, STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
STREAMFILE* temp_sf = NULL; int channels, sample_rate;
int channel_count, sample_rate; int32_t num_samples;
channel_count = sb->channels; /* by default silences don't have settings */
channels = sb->channels;
if (channels == 0)
channels = 2;
sample_rate = sb->sample_rate; sample_rate = sb->sample_rate;
/* by default silences don't have settings so let's pretend */
if (channel_count == 0)
channel_count = 2;
if (sample_rate == 0) if (sample_rate == 0)
sample_rate = 48000; sample_rate = 48000;
num_samples = sb->duration * sample_rate;
/* build the VGMSTREAM */ /* init the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, 0); vgmstream = init_vgmstream_silence(channels, sample_rate, num_samples);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_UBI_SB; vgmstream->meta_type = meta_UBI_SB;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = (int32_t)(sb->duration * (float)sample_rate);
vgmstream->num_streams = sb->total_subsongs; vgmstream->num_streams = sb->total_subsongs;
vgmstream->stream_size = vgmstream->num_samples * channel_count * 0x02; /* PCM size */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
temp_sf = setup_silence_streamfile(sf);
if ( !vgmstream_open_stream(vgmstream, temp_sf, 0x00) )
goto fail;
close_streamfile(temp_sf);
return vgmstream; return vgmstream;
fail: fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
close_streamfile(temp_sf);
return vgmstream; return vgmstream;
} }

View File

@ -1,62 +1,61 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* UE4OPUS - from Unreal Engine 4 games [ARK: Survival Evolved (PC), Fortnite (PC)] */ /* UE4OPUS - from Unreal Engine 4 games [ARK: Survival Evolved (PC), Fortnite (PC)] */
VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag = 0, channel_count, sample_rate, num_samples, skip; int loop_flag = 0, channels, sample_rate, num_samples, skip;
size_t data_size; size_t data_size;
/* checks*/ /* checks*/
/* .opus/lopus: possible real extension /* .opus/lopus: possible real extension
* .ue4opus: header id */ * .ue4opus: header id */
if (!check_extensions(streamFile, "opus,lopus,ue4opus")) if (!check_extensions(sf, "opus,lopus,ue4opus"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) != 0x5545344F && /* "UE4O" */ if (!is_id64be(0x00, sf, "UE4OPUS\0"))
read_32bitBE(0x00, streamFile) != 0x50555300) /* "PUS\0" */ goto fail;
goto fail;
sample_rate = read_u16le(0x08, sf);
sample_rate = (uint16_t)read_16bitLE(0x08, streamFile); num_samples = read_s32le(0x0a, sf); /* may be less or equal to file num_samples */
num_samples = read_32bitLE(0x0a, streamFile); /* may be less or equal to file num_samples */ channels = read_u8(0x0e, sf);
channel_count = read_8bit(0x0e, streamFile); /* 0x0f(2): frame count */
/* 0x0f(2): frame count */ loop_flag = 0;
loop_flag = 0;
start_offset = 0x11;
start_offset = 0x11; data_size = get_streamfile_size(sf) - start_offset;
data_size = get_streamfile_size(streamFile) - start_offset;
/* build the VGMSTREAM */
/* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels, loop_flag);
vgmstream = allocate_vgmstream(channel_count, loop_flag); if (!vgmstream) goto fail;
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_UE4OPUS;
vgmstream->meta_type = meta_UE4OPUS; vgmstream->sample_rate = sample_rate;
vgmstream->sample_rate = sample_rate;
#ifdef VGM_USE_FFMPEG
#ifdef VGM_USE_FFMPEG {
{ /* usually uses 60ms for music (delay of 360 samples) */
/* usually uses 60ms for music (delay of 360 samples) */ skip = ue4_opus_get_encoder_delay(start_offset, sf);
skip = ue4_opus_get_encoder_delay(start_offset, streamFile); vgmstream->num_samples = num_samples - skip;
vgmstream->num_samples = num_samples - skip;
vgmstream->codec_data = init_ffmpeg_ue4_opus(sf, start_offset,data_size, vgmstream->channels, skip, vgmstream->sample_rate);
vgmstream->codec_data = init_ffmpeg_ue4_opus(streamFile, start_offset,data_size, vgmstream->channels, skip, vgmstream->sample_rate); if (!vgmstream->codec_data) goto fail;
if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg;
vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none;
vgmstream->layout_type = layout_none; }
} #else
#else goto fail;
goto fail; #endif
#endif
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) goto fail;
goto fail; return vgmstream;
return vgmstream;
fail:
fail: close_vgmstream(vgmstream);
close_vgmstream(vgmstream); return NULL;
return NULL; }
}

View File

@ -532,3 +532,17 @@ void vgmstream_mixing_autodownmix(VGMSTREAM *vgmstream, int max_channels) {
return; return;
} }
void vgmstream_mixing_stereo_only(VGMSTREAM *vgmstream, int start) {
if (start < 0)
return;
/* could check to avoid making mono files in edge cases but meh */
/* remove channels before start */
while (start) {
mixing_push_downmix(vgmstream, 0);
start--;
}
/* remove channels after stereo */
mixing_push_killmix(vgmstream, start + 2);
}

View File

@ -215,7 +215,10 @@ void vgmstream_tags_close(VGMSTREAM_TAGS* tags);
void vgmstream_mixing_enable(VGMSTREAM* vgmstream, int32_t max_sample_count, int *input_channels, int *output_channels); void vgmstream_mixing_enable(VGMSTREAM* vgmstream, int32_t max_sample_count, int *input_channels, int *output_channels);
/* sets automatic downmixing if vgmstream's channels are higher than max_channels */ /* sets automatic downmixing if vgmstream's channels are higher than max_channels */
void vgmstream_mixing_autodownmix(VGMSTREAM *vgmstream, int max_channels); void vgmstream_mixing_autodownmix(VGMSTREAM* vgmstream, int max_channels);
/* downmixes to get stereo from start channel */
void vgmstream_mixing_stereo_only(VGMSTREAM* vgmstream, int start);
/* sets a fadeout */ /* sets a fadeout */
//void vgmstream_mixing_fadeout(VGMSTREAM *vgmstream, float start_second, float duration_seconds); //void vgmstream_mixing_fadeout(VGMSTREAM *vgmstream, float start_second, float duration_seconds);

View File

@ -1123,9 +1123,14 @@ fail:
} }
STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
return read_filemap_file_pos(sf, file_num, NULL);
}
STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) {
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
off_t txt_offset, file_size; off_t txt_offset, file_size;
STREAMFILE* sf_map = NULL; STREAMFILE* sf_map = NULL;
int file_pos = 0;
sf_map = open_streamfile_by_filename(sf, ".txtm"); sf_map = open_streamfile_by_filename(sf, ".txtm");
if (!sf_map) goto fail; if (!sf_map) goto fail;
@ -1136,10 +1141,10 @@ STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
file_size = get_streamfile_size(sf_map); file_size = get_streamfile_size(sf_map);
/* skip BOM if needed */ /* skip BOM if needed */
if ((uint16_t)read_16bitLE(0x00, sf_map) == 0xFFFE || if (read_u16le(0x00, sf_map) == 0xFFFE ||
(uint16_t)read_16bitLE(0x00, sf_map) == 0xFEFF) { read_u16le(0x00, sf_map) == 0xFEFF) {
txt_offset = 0x02; txt_offset = 0x02;
} else if (((uint32_t)read_32bitBE(0x00, sf_map) & 0xFFFFFF00) == 0xEFBBBF00) { } else if ((read_u32be(0x00, sf_map) & 0xFFFFFF00) == 0xEFBBBF00) {
txt_offset = 0x03; txt_offset = 0x03;
} }
@ -1174,8 +1179,9 @@ STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
if (ok != 1) if (ok != 1)
goto fail; goto fail;
if (i == file_num) if (i == file_num) {
{ if (p_pos) *p_pos = file_pos;
close_streamfile(sf_map); close_streamfile(sf_map);
return open_streamfile_by_filename(sf, subval); return open_streamfile_by_filename(sf, subval);
} }
@ -1185,6 +1191,7 @@ STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
current++; current++;
} }
} }
file_pos++;
} }
fail: fail:

View File

@ -361,7 +361,9 @@ size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf);
/* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match /* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match
* then loads the associated companion file if one is found */ * then loads the associated companion file if one is found */
STREAMFILE *read_filemap_file(STREAMFILE *sf, int file_num); STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num);
STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos);
/* hack to allow relative paths in various OSs */ /* hack to allow relative paths in various OSs */
void fix_dir_separators(char* filename); void fix_dir_separators(char* filename);

View File

@ -40,12 +40,11 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_rfrm, init_vgmstream_rfrm,
init_vgmstream_cstr, init_vgmstream_cstr,
init_vgmstream_gcsw, init_vgmstream_gcsw,
init_vgmstream_ps2_ads, init_vgmstream_ads,
init_vgmstream_nps, init_vgmstream_nps,
init_vgmstream_rwsd, init_vgmstream_rwsd,
init_vgmstream_xa, init_vgmstream_xa,
init_vgmstream_ps2_rxws, init_vgmstream_rxws,
init_vgmstream_ps2_rxw,
init_vgmstream_ngc_dsp_stm, init_vgmstream_ngc_dsp_stm,
init_vgmstream_exst, init_vgmstream_exst,
init_vgmstream_svag_kcet, init_vgmstream_svag_kcet,
@ -194,7 +193,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_nds_rrds, init_vgmstream_nds_rrds,
init_vgmstream_ps2_tk5, init_vgmstream_ps2_tk5,
init_vgmstream_ps2_vsf_tta, init_vgmstream_ps2_vsf_tta,
init_vgmstream_ads, init_vgmstream_ads_midway,
init_vgmstream_ps2_mcg, init_vgmstream_ps2_mcg,
init_vgmstream_zsd, init_vgmstream_zsd,
init_vgmstream_ps2_vgs, init_vgmstream_ps2_vgs,
@ -262,11 +261,9 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_sqex_scd, init_vgmstream_sqex_scd,
init_vgmstream_ngc_nst_dsp, init_vgmstream_ngc_nst_dsp,
init_vgmstream_baf, init_vgmstream_baf,
init_vgmstream_baf_badrip,
init_vgmstream_msf, init_vgmstream_msf,
init_vgmstream_ps3_past, init_vgmstream_ps3_past,
init_vgmstream_sgxd, init_vgmstream_sgxd,
init_vgmstream_ngca,
init_vgmstream_wii_ras, init_vgmstream_wii_ras,
init_vgmstream_ps2_spm, init_vgmstream_ps2_spm,
init_vgmstream_x360_tra, init_vgmstream_x360_tra,
@ -395,7 +392,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_dsp_switch_audio, init_vgmstream_dsp_switch_audio,
init_vgmstream_sadf, init_vgmstream_sadf,
init_vgmstream_h4m, init_vgmstream_h4m,
init_vgmstream_ps2_ads_container, init_vgmstream_ads_container,
init_vgmstream_asf, init_vgmstream_asf,
init_vgmstream_xmd, init_vgmstream_xmd,
init_vgmstream_cks, init_vgmstream_cks,
@ -539,6 +536,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_s14_sss, /* .s14/sss raw siren14 */ init_vgmstream_s14_sss, /* .s14/sss raw siren14 */
init_vgmstream_raw_al, /* .al/al2 raw A-LAW */ init_vgmstream_raw_al, /* .al/al2 raw A-LAW */
init_vgmstream_zwdsp, /* fake format */ init_vgmstream_zwdsp, /* fake format */
init_vgmstream_baf_badrip, /* crap, to be removed */
init_vgmstream_rxws_badrip, /* crap, to be removed */
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
init_vgmstream_ffmpeg, /* may play anything incorrectly, since FFmpeg doesn't check extensions */ init_vgmstream_ffmpeg, /* may play anything incorrectly, since FFmpeg doesn't check extensions */
#endif #endif
@ -1409,7 +1408,7 @@ static int get_vgmstream_file_bitrate_from_streamfile(STREAMFILE* sf, int sample
return get_vgmstream_file_bitrate_from_size(get_streamfile_size(sf), sample_rate, length_samples); return get_vgmstream_file_bitrate_from_size(get_streamfile_size(sf), sample_rate, length_samples);
} }
static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* br) { static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* br, int* p_uniques) {
int i, ch; int i, ch;
int bitrate = 0; int bitrate = 0;
@ -1423,15 +1422,18 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t*
* become a bit high since its hard to detect only part of the file is needed. */ * become a bit high since its hard to detect only part of the file is needed. */
if (vgmstream->layout_type == layout_segmented) { if (vgmstream->layout_type == layout_segmented) {
int uniques = 0;
segmented_layout_data *data = (segmented_layout_data *) vgmstream->layout_data; segmented_layout_data *data = (segmented_layout_data *) vgmstream->layout_data;
for (i = 0; i < data->segment_count; i++) { for (i = 0; i < data->segment_count; i++) {
bitrate += get_vgmstream_file_bitrate_main(data->segments[i], br); bitrate += get_vgmstream_file_bitrate_main(data->segments[i], br, &uniques);
} }
if (uniques)
bitrate /= uniques; /* average */
} }
else if (vgmstream->layout_type == layout_layered) { else if (vgmstream->layout_type == layout_layered) {
layered_layout_data *data = vgmstream->layout_data; layered_layout_data *data = vgmstream->layout_data;
for (i = 0; i < data->layer_count; i++) { for (i = 0; i < data->layer_count; i++) {
bitrate += get_vgmstream_file_bitrate_main(data->layers[i], br); bitrate += get_vgmstream_file_bitrate_main(data->layers[i], br, NULL);
} }
} }
else { else {
@ -1467,6 +1469,8 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t*
br->subsong[br->count] = subsong_cur; br->subsong[br->count] = subsong_cur;
br->count++; br->count++;
if (p_uniques)
(*p_uniques)++;
if (vgmstream->stream_size) { if (vgmstream->stream_size) {
/* stream_size applies to both channels but should add once and detect repeats (for current subsong) */ /* stream_size applies to both channels but should add once and detect repeats (for current subsong) */
@ -1494,7 +1498,7 @@ int get_vgmstream_average_bitrate(VGMSTREAM* vgmstream) {
bitrate_info_t br = {0}; bitrate_info_t br = {0};
br.count_max = BITRATE_FILES_MAX; br.count_max = BITRATE_FILES_MAX;
return get_vgmstream_file_bitrate_main(vgmstream, &br); return get_vgmstream_file_bitrate_main(vgmstream, &br, NULL);
} }

View File

@ -362,9 +362,9 @@ typedef enum {
meta_BNSF, /* Bandai Namco Sound Format */ meta_BNSF, /* Bandai Namco Sound Format */
meta_XA, /* CD-ROM XA */ meta_XA, /* CD-ROM XA */
meta_PS2_SShd, /* .ADS with SShd header */ meta_ADS,
meta_NPS, meta_NPS,
meta_PS2_RXWS, /* Sony games (Genji, Okage Shadow King, Arc The Lad Twilight of Spirits) */ meta_RXWS,
meta_RAW_INT, meta_RAW_INT,
meta_EXST, meta_EXST,
meta_SVAG_KCET, meta_SVAG_KCET,
@ -460,7 +460,7 @@ typedef enum {
meta_SAT_BAKA, /* Crypt Killer */ meta_SAT_BAKA, /* Crypt Killer */
meta_VSF, meta_VSF,
meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */ meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */
meta_ADS, /* Gauntlet Dark Legends (GC) */ meta_ADS_MIDWAY,
meta_PS2_SPS, /* Ape Escape 2 */ meta_PS2_SPS, /* Ape Escape 2 */
meta_PS2_XA2_RRP, /* RC Revenge Pro */ meta_PS2_XA2_RRP, /* RC Revenge Pro */
meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */ meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */
@ -568,7 +568,6 @@ typedef enum {
meta_MSF, meta_MSF,
meta_PS3_PAST, /* Bakugan Battle Brawlers (PS3) */ meta_PS3_PAST, /* Bakugan Battle Brawlers (PS3) */
meta_SGXD, /* Sony: Folklore, Genji, Tokyo Jungle (PS3), Brave Story, Kurohyo (PSP) */ meta_SGXD, /* Sony: Folklore, Genji, Tokyo Jungle (PS3), Brave Story, Kurohyo (PSP) */
meta_NGCA, /* GoldenEye 007 (Wii) */
meta_WII_RAS, /* Donkey Kong Country Returns (Wii) */ meta_WII_RAS, /* Donkey Kong Country Returns (Wii) */
meta_PS2_SPM, /* Lethal Skies Elite Pilot: Team SW */ meta_PS2_SPM, /* Lethal Skies Elite Pilot: Team SW */
meta_X360_TRA, /* Def Jam Rapstar */ meta_X360_TRA, /* Def Jam Rapstar */