Updated VGMStream to r1050-449-gd2fac791.
parent
c291a4885b
commit
22fa3a3df0
|
@ -10,12 +10,27 @@
|
||||||
48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 48C2650E1A5D420800A0A3D6 /* vorbisfile.h */; };
|
48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 48C2650E1A5D420800A0A3D6 /* vorbisfile.h */; };
|
||||||
8313E3E61902020400B4B6F1 /* mpg123.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; };
|
8313E3E61902020400B4B6F1 /* mpg123.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; };
|
||||||
8313E3E71902021800B4B6F1 /* mpg123.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; };
|
8313E3E71902021800B4B6F1 /* mpg123.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8313E3431901FBDD00B4B6F1 /* mpg123.framework */; };
|
||||||
|
831BA6181EAC61A500CF89B0 /* adx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA60E1EAC61A500CF89B0 /* adx.c */; };
|
||||||
|
831BA6191EAC61A500CF89B0 /* ogl.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA60F1EAC61A500CF89B0 /* ogl.c */; };
|
||||||
|
831BA61A1EAC61A500CF89B0 /* ps2_vds_vdm.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */; };
|
||||||
|
831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6111EAC61A500CF89B0 /* sgxd.c */; };
|
||||||
|
831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6121EAC61A500CF89B0 /* sxd.c */; };
|
||||||
|
831BA61D1EAC61A500CF89B0 /* ubi_raki.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6131EAC61A500CF89B0 /* ubi_raki.c */; };
|
||||||
|
831BA61E1EAC61A500CF89B0 /* vawx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6141EAC61A500CF89B0 /* vawx.c */; };
|
||||||
|
831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6151EAC61A500CF89B0 /* x360_cxs.c */; };
|
||||||
|
831BA6201EAC61A500CF89B0 /* x360_nub.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6161EAC61A500CF89B0 /* x360_nub.c */; };
|
||||||
|
831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6171EAC61A500CF89B0 /* x360_pasx.c */; };
|
||||||
|
831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6221EAC61CB00CF89B0 /* coding_utils.c */; };
|
||||||
|
831BA6291EAC61CB00CF89B0 /* ogl_vorbis_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6231EAC61CB00CF89B0 /* ogl_vorbis_decoder.c */; };
|
||||||
|
831BA62A1EAC61CB00CF89B0 /* wwise_vorbis_data.h in Headers */ = {isa = PBXBuildFile; fileRef = 831BA6241EAC61CB00CF89B0 /* wwise_vorbis_data.h */; };
|
||||||
|
831BA62B1EAC61CB00CF89B0 /* wwise_vorbis_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6251EAC61CB00CF89B0 /* wwise_vorbis_decoder.c */; };
|
||||||
|
831BA62C1EAC61CB00CF89B0 /* wwise_vorbis_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BA6261EAC61CB00CF89B0 /* wwise_vorbis_utils.c */; };
|
||||||
|
831BA62D1EAC61CB00CF89B0 /* wwise_vorbis_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 831BA6271EAC61CB00CF89B0 /* wwise_vorbis_utils.h */; };
|
||||||
8321405A1E8758D7001A8A5E /* fsb_vorbis_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 832140591E8758D7001A8A5E /* fsb_vorbis_decoder.c */; };
|
8321405A1E8758D7001A8A5E /* fsb_vorbis_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 832140591E8758D7001A8A5E /* fsb_vorbis_decoder.c */; };
|
||||||
8323894A1D22419B00482226 /* clHCA.c in Sources */ = {isa = PBXBuildFile; fileRef = 832389481D22419B00482226 /* clHCA.c */; };
|
8323894A1D22419B00482226 /* clHCA.c in Sources */ = {isa = PBXBuildFile; fileRef = 832389481D22419B00482226 /* clHCA.c */; };
|
||||||
8323894B1D22419B00482226 /* clHCA.h in Headers */ = {isa = PBXBuildFile; fileRef = 832389491D22419B00482226 /* clHCA.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
8323894B1D22419B00482226 /* clHCA.h in Headers */ = {isa = PBXBuildFile; fileRef = 832389491D22419B00482226 /* clHCA.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
832389501D2246C300482226 /* hca.c in Sources */ = {isa = PBXBuildFile; fileRef = 8323894F1D2246C300482226 /* hca.c */; };
|
832389501D2246C300482226 /* hca.c in Sources */ = {isa = PBXBuildFile; fileRef = 8323894F1D2246C300482226 /* hca.c */; };
|
||||||
832389521D224C0800482226 /* hca_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 832389511D224C0800482226 /* hca_decoder.c */; };
|
832389521D224C0800482226 /* hca_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 832389511D224C0800482226 /* hca_decoder.c */; };
|
||||||
83299FC61E76606B003A3242 /* ffmpeg_decoder_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FC51E76606B003A3242 /* ffmpeg_decoder_utils.c */; };
|
|
||||||
83299FCC1E76607A003A3242 /* header.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCA1E76607A003A3242 /* header.c */; };
|
83299FCC1E76607A003A3242 /* header.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCA1E76607A003A3242 /* header.c */; };
|
||||||
83299FCD1E76607A003A3242 /* header.h in Headers */ = {isa = PBXBuildFile; fileRef = 83299FCB1E76607A003A3242 /* header.h */; };
|
83299FCD1E76607A003A3242 /* header.h in Headers */ = {isa = PBXBuildFile; fileRef = 83299FCB1E76607A003A3242 /* header.h */; };
|
||||||
83299FD01E7660C7003A3242 /* bik.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCE1E7660C7003A3242 /* bik.c */; };
|
83299FD01E7660C7003A3242 /* bik.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCE1E7660C7003A3242 /* bik.c */; };
|
||||||
|
@ -95,7 +110,6 @@
|
||||||
836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; };
|
836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; };
|
||||||
836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; };
|
836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; };
|
||||||
836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.c */; };
|
836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.c */; };
|
||||||
836F6F6918BDC2190095E648 /* adx_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2D18BDC2180095E648 /* adx_header.c */; };
|
|
||||||
836F6F6A18BDC2190095E648 /* afc_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2E18BDC2180095E648 /* afc_header.c */; };
|
836F6F6A18BDC2190095E648 /* afc_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2E18BDC2180095E648 /* afc_header.c */; };
|
||||||
836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; };
|
836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; };
|
||||||
836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; };
|
836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; };
|
||||||
|
@ -267,8 +281,6 @@
|
||||||
836F701318BDC2190095E648 /* ps3_klbs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED718BDC2190095E648 /* ps3_klbs.c */; };
|
836F701318BDC2190095E648 /* ps3_klbs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED718BDC2190095E648 /* ps3_klbs.c */; };
|
||||||
836F701418BDC2190095E648 /* ps3_msf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED818BDC2190095E648 /* ps3_msf.c */; };
|
836F701418BDC2190095E648 /* ps3_msf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED818BDC2190095E648 /* ps3_msf.c */; };
|
||||||
836F701518BDC2190095E648 /* ps3_past.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED918BDC2190095E648 /* ps3_past.c */; };
|
836F701518BDC2190095E648 /* ps3_past.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED918BDC2190095E648 /* ps3_past.c */; };
|
||||||
836F701618BDC2190095E648 /* ps3_sgh_sgb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDA18BDC2190095E648 /* ps3_sgh_sgb.c */; };
|
|
||||||
836F701718BDC2190095E648 /* ps3_vawx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDB18BDC2190095E648 /* ps3_vawx.c */; };
|
|
||||||
836F701818BDC2190095E648 /* ps3_xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDC18BDC2190095E648 /* ps3_xvag.c */; };
|
836F701818BDC2190095E648 /* ps3_xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDC18BDC2190095E648 /* ps3_xvag.c */; };
|
||||||
836F701918BDC2190095E648 /* psx_cdxa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDD18BDC2190095E648 /* psx_cdxa.c */; };
|
836F701918BDC2190095E648 /* psx_cdxa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDD18BDC2190095E648 /* psx_cdxa.c */; };
|
||||||
836F701A18BDC2190095E648 /* psx_fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDE18BDC2190095E648 /* psx_fag.c */; };
|
836F701A18BDC2190095E648 /* psx_fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDE18BDC2190095E648 /* psx_fag.c */; };
|
||||||
|
@ -353,8 +365,6 @@
|
||||||
83A3F0741E3AD8B900D6A794 /* formats.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F0711E3AD8B900D6A794 /* formats.c */; };
|
83A3F0741E3AD8B900D6A794 /* formats.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F0711E3AD8B900D6A794 /* formats.c */; };
|
||||||
83A3F0751E3AD8B900D6A794 /* formats.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0721E3AD8B900D6A794 /* formats.h */; };
|
83A3F0751E3AD8B900D6A794 /* formats.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0721E3AD8B900D6A794 /* formats.h */; };
|
||||||
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */; };
|
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */; };
|
||||||
83A3F07C1E3AD92400D6A794 /* ps2.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F07A1E3AD92400D6A794 /* ps2.c */; };
|
|
||||||
83A3F07D1E3AD92400D6A794 /* x360.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F07B1E3AD92400D6A794 /* x360.c */; };
|
|
||||||
83A5F75F198DF021009AF94C /* bfwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A5F75E198DF021009AF94C /* bfwav.c */; };
|
83A5F75F198DF021009AF94C /* bfwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A5F75E198DF021009AF94C /* bfwav.c */; };
|
||||||
83AB8C751E8072A100086084 /* nub_vag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C731E8072A100086084 /* nub_vag.c */; };
|
83AB8C751E8072A100086084 /* nub_vag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C731E8072A100086084 /* nub_vag.c */; };
|
||||||
83AB8C761E8072A100086084 /* x360_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C741E8072A100086084 /* x360_ast.c */; };
|
83AB8C761E8072A100086084 /* x360_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AB8C741E8072A100086084 /* x360_ast.c */; };
|
||||||
|
@ -475,12 +485,27 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
48C2650E1A5D420800A0A3D6 /* vorbisfile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = vorbisfile.h; path = ../Vorbis/include/vorbis/vorbisfile.h; sourceTree = "<group>"; };
|
48C2650E1A5D420800A0A3D6 /* vorbisfile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = vorbisfile.h; path = ../Vorbis/include/vorbis/vorbisfile.h; sourceTree = "<group>"; };
|
||||||
8313E33D1901FBDC00B4B6F1 /* mpg123.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = mpg123.xcodeproj; path = ../mpg123/mpg123.xcodeproj; sourceTree = "<group>"; };
|
8313E33D1901FBDC00B4B6F1 /* mpg123.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = mpg123.xcodeproj; path = ../mpg123/mpg123.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
831BA60E1EAC61A500CF89B0 /* adx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adx.c; sourceTree = "<group>"; };
|
||||||
|
831BA60F1EAC61A500CF89B0 /* ogl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogl.c; sourceTree = "<group>"; };
|
||||||
|
831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vds_vdm.c; sourceTree = "<group>"; };
|
||||||
|
831BA6111EAC61A500CF89B0 /* sgxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sgxd.c; sourceTree = "<group>"; };
|
||||||
|
831BA6121EAC61A500CF89B0 /* sxd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sxd.c; sourceTree = "<group>"; };
|
||||||
|
831BA6131EAC61A500CF89B0 /* ubi_raki.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_raki.c; sourceTree = "<group>"; };
|
||||||
|
831BA6141EAC61A500CF89B0 /* vawx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vawx.c; sourceTree = "<group>"; };
|
||||||
|
831BA6151EAC61A500CF89B0 /* x360_cxs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_cxs.c; sourceTree = "<group>"; };
|
||||||
|
831BA6161EAC61A500CF89B0 /* x360_nub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_nub.c; sourceTree = "<group>"; };
|
||||||
|
831BA6171EAC61A500CF89B0 /* x360_pasx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_pasx.c; sourceTree = "<group>"; };
|
||||||
|
831BA6221EAC61CB00CF89B0 /* coding_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = coding_utils.c; sourceTree = "<group>"; };
|
||||||
|
831BA6231EAC61CB00CF89B0 /* ogl_vorbis_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogl_vorbis_decoder.c; sourceTree = "<group>"; };
|
||||||
|
831BA6241EAC61CB00CF89B0 /* wwise_vorbis_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wwise_vorbis_data.h; sourceTree = "<group>"; };
|
||||||
|
831BA6251EAC61CB00CF89B0 /* wwise_vorbis_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wwise_vorbis_decoder.c; sourceTree = "<group>"; };
|
||||||
|
831BA6261EAC61CB00CF89B0 /* wwise_vorbis_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wwise_vorbis_utils.c; sourceTree = "<group>"; };
|
||||||
|
831BA6271EAC61CB00CF89B0 /* wwise_vorbis_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wwise_vorbis_utils.h; sourceTree = "<group>"; };
|
||||||
832140591E8758D7001A8A5E /* fsb_vorbis_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fsb_vorbis_decoder.c; sourceTree = "<group>"; };
|
832140591E8758D7001A8A5E /* fsb_vorbis_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fsb_vorbis_decoder.c; sourceTree = "<group>"; };
|
||||||
832389481D22419B00482226 /* clHCA.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clHCA.c; sourceTree = "<group>"; };
|
832389481D22419B00482226 /* clHCA.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clHCA.c; sourceTree = "<group>"; };
|
||||||
832389491D22419B00482226 /* clHCA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = clHCA.h; sourceTree = "<group>"; };
|
832389491D22419B00482226 /* clHCA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = clHCA.h; sourceTree = "<group>"; };
|
||||||
8323894F1D2246C300482226 /* hca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hca.c; sourceTree = "<group>"; };
|
8323894F1D2246C300482226 /* hca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hca.c; sourceTree = "<group>"; };
|
||||||
832389511D224C0800482226 /* hca_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hca_decoder.c; sourceTree = "<group>"; };
|
832389511D224C0800482226 /* hca_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hca_decoder.c; sourceTree = "<group>"; };
|
||||||
83299FC51E76606B003A3242 /* ffmpeg_decoder_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils.c; sourceTree = "<group>"; };
|
|
||||||
83299FCA1E76607A003A3242 /* header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = header.c; sourceTree = "<group>"; };
|
83299FCA1E76607A003A3242 /* header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = header.c; sourceTree = "<group>"; };
|
||||||
83299FCB1E76607A003A3242 /* header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = header.h; sourceTree = "<group>"; };
|
83299FCB1E76607A003A3242 /* header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = header.h; sourceTree = "<group>"; };
|
||||||
83299FCE1E7660C7003A3242 /* bik.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bik.c; sourceTree = "<group>"; };
|
83299FCE1E7660C7003A3242 /* bik.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bik.c; sourceTree = "<group>"; };
|
||||||
|
@ -561,7 +586,6 @@
|
||||||
836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = "<group>"; };
|
836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = "<group>"; };
|
||||||
836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = "<group>"; };
|
836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = "<group>"; };
|
||||||
836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = "<group>"; };
|
836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = "<group>"; };
|
||||||
836F6E2D18BDC2180095E648 /* adx_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adx_header.c; sourceTree = "<group>"; };
|
|
||||||
836F6E2E18BDC2180095E648 /* afc_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = afc_header.c; sourceTree = "<group>"; };
|
836F6E2E18BDC2180095E648 /* afc_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = afc_header.c; sourceTree = "<group>"; };
|
||||||
836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = "<group>"; };
|
836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = "<group>"; };
|
||||||
836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = "<group>"; };
|
836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = "<group>"; };
|
||||||
|
@ -733,8 +757,6 @@
|
||||||
836F6ED718BDC2190095E648 /* ps3_klbs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_klbs.c; sourceTree = "<group>"; };
|
836F6ED718BDC2190095E648 /* ps3_klbs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_klbs.c; sourceTree = "<group>"; };
|
||||||
836F6ED818BDC2190095E648 /* ps3_msf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_msf.c; sourceTree = "<group>"; };
|
836F6ED818BDC2190095E648 /* ps3_msf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_msf.c; sourceTree = "<group>"; };
|
||||||
836F6ED918BDC2190095E648 /* ps3_past.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_past.c; sourceTree = "<group>"; };
|
836F6ED918BDC2190095E648 /* ps3_past.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_past.c; sourceTree = "<group>"; };
|
||||||
836F6EDA18BDC2190095E648 /* ps3_sgh_sgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_sgh_sgb.c; sourceTree = "<group>"; };
|
|
||||||
836F6EDB18BDC2190095E648 /* ps3_vawx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_vawx.c; sourceTree = "<group>"; };
|
|
||||||
836F6EDC18BDC2190095E648 /* ps3_xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_xvag.c; sourceTree = "<group>"; };
|
836F6EDC18BDC2190095E648 /* ps3_xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_xvag.c; sourceTree = "<group>"; };
|
||||||
836F6EDD18BDC2190095E648 /* psx_cdxa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_cdxa.c; sourceTree = "<group>"; };
|
836F6EDD18BDC2190095E648 /* psx_cdxa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_cdxa.c; sourceTree = "<group>"; };
|
||||||
836F6EDE18BDC2190095E648 /* psx_fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_fag.c; sourceTree = "<group>"; };
|
836F6EDE18BDC2190095E648 /* psx_fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_fag.c; sourceTree = "<group>"; };
|
||||||
|
@ -819,8 +841,6 @@
|
||||||
83A3F0711E3AD8B900D6A794 /* formats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = formats.c; sourceTree = "<group>"; };
|
83A3F0711E3AD8B900D6A794 /* formats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = formats.c; sourceTree = "<group>"; };
|
||||||
83A3F0721E3AD8B900D6A794 /* formats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = formats.h; sourceTree = "<group>"; };
|
83A3F0721E3AD8B900D6A794 /* formats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = formats.h; sourceTree = "<group>"; };
|
||||||
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; };
|
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; };
|
||||||
83A3F07A1E3AD92400D6A794 /* ps2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2.c; sourceTree = "<group>"; };
|
|
||||||
83A3F07B1E3AD92400D6A794 /* x360.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360.c; sourceTree = "<group>"; };
|
|
||||||
83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = "<group>"; };
|
83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = "<group>"; };
|
||||||
83AB8C731E8072A100086084 /* nub_vag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_vag.c; sourceTree = "<group>"; };
|
83AB8C731E8072A100086084 /* nub_vag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_vag.c; sourceTree = "<group>"; };
|
||||||
83AB8C741E8072A100086084 /* x360_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_ast.c; sourceTree = "<group>"; };
|
83AB8C741E8072A100086084 /* x360_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_ast.c; sourceTree = "<group>"; };
|
||||||
|
@ -974,9 +994,14 @@
|
||||||
836F6DDF18BDC2180095E648 /* coding */ = {
|
836F6DDF18BDC2180095E648 /* coding */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
831BA6221EAC61CB00CF89B0 /* coding_utils.c */,
|
||||||
|
831BA6231EAC61CB00CF89B0 /* ogl_vorbis_decoder.c */,
|
||||||
|
831BA6241EAC61CB00CF89B0 /* wwise_vorbis_data.h */,
|
||||||
|
831BA6251EAC61CB00CF89B0 /* wwise_vorbis_decoder.c */,
|
||||||
|
831BA6261EAC61CB00CF89B0 /* wwise_vorbis_utils.c */,
|
||||||
|
831BA6271EAC61CB00CF89B0 /* wwise_vorbis_utils.h */,
|
||||||
836E15DD1E88A3380029F8AD /* fsb_vorbis_data.h */,
|
836E15DD1E88A3380029F8AD /* fsb_vorbis_data.h */,
|
||||||
832140591E8758D7001A8A5E /* fsb_vorbis_decoder.c */,
|
832140591E8758D7001A8A5E /* fsb_vorbis_decoder.c */,
|
||||||
83299FC51E76606B003A3242 /* ffmpeg_decoder_utils.c */,
|
|
||||||
838BDB6B1D3AFAB10022CA6F /* ffmpeg_decoder.c */,
|
838BDB6B1D3AFAB10022CA6F /* ffmpeg_decoder.c */,
|
||||||
832389511D224C0800482226 /* hca_decoder.c */,
|
832389511D224C0800482226 /* hca_decoder.c */,
|
||||||
83D7318B1A749EEE00CA1366 /* g719_decoder.c */,
|
83D7318B1A749EEE00CA1366 /* g719_decoder.c */,
|
||||||
|
@ -1059,13 +1084,21 @@
|
||||||
836F6E2718BDC2180095E648 /* meta */ = {
|
836F6E2718BDC2180095E648 /* meta */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
831BA60E1EAC61A500CF89B0 /* adx.c */,
|
||||||
|
831BA60F1EAC61A500CF89B0 /* ogl.c */,
|
||||||
|
831BA6101EAC61A500CF89B0 /* ps2_vds_vdm.c */,
|
||||||
|
831BA6111EAC61A500CF89B0 /* sgxd.c */,
|
||||||
|
831BA6121EAC61A500CF89B0 /* sxd.c */,
|
||||||
|
831BA6131EAC61A500CF89B0 /* ubi_raki.c */,
|
||||||
|
831BA6141EAC61A500CF89B0 /* vawx.c */,
|
||||||
|
831BA6151EAC61A500CF89B0 /* x360_cxs.c */,
|
||||||
|
831BA6161EAC61A500CF89B0 /* x360_nub.c */,
|
||||||
|
831BA6171EAC61A500CF89B0 /* x360_pasx.c */,
|
||||||
83FF0EBB1E93282100C58054 /* wwise.c */,
|
83FF0EBB1E93282100C58054 /* wwise.c */,
|
||||||
83AB8C731E8072A100086084 /* nub_vag.c */,
|
83AB8C731E8072A100086084 /* nub_vag.c */,
|
||||||
83AB8C741E8072A100086084 /* x360_ast.c */,
|
83AB8C741E8072A100086084 /* x360_ast.c */,
|
||||||
83299FCE1E7660C7003A3242 /* bik.c */,
|
83299FCE1E7660C7003A3242 /* bik.c */,
|
||||||
83299FCF1E7660C7003A3242 /* dsp_adx.c */,
|
83299FCF1E7660C7003A3242 /* dsp_adx.c */,
|
||||||
83A3F07A1E3AD92400D6A794 /* ps2.c */,
|
|
||||||
83A3F07B1E3AD92400D6A794 /* x360.c */,
|
|
||||||
8350C0591E071990009E0A93 /* ps2_svag_snk.c */,
|
8350C0591E071990009E0A93 /* ps2_svag_snk.c */,
|
||||||
8350C0541E071881009E0A93 /* xma.c */,
|
8350C0541E071881009E0A93 /* xma.c */,
|
||||||
838BDB6D1D3B043C0022CA6F /* ffmpeg.c */,
|
838BDB6D1D3B043C0022CA6F /* ffmpeg.c */,
|
||||||
|
@ -1080,7 +1113,6 @@
|
||||||
836F6E2A18BDC2180095E648 /* aax.c */,
|
836F6E2A18BDC2180095E648 /* aax.c */,
|
||||||
836F6E2B18BDC2180095E648 /* acm.c */,
|
836F6E2B18BDC2180095E648 /* acm.c */,
|
||||||
836F6E2C18BDC2180095E648 /* ads.c */,
|
836F6E2C18BDC2180095E648 /* ads.c */,
|
||||||
836F6E2D18BDC2180095E648 /* adx_header.c */,
|
|
||||||
836F6E2E18BDC2180095E648 /* afc_header.c */,
|
836F6E2E18BDC2180095E648 /* afc_header.c */,
|
||||||
836F6E2F18BDC2180095E648 /* agsc.c */,
|
836F6E2F18BDC2180095E648 /* agsc.c */,
|
||||||
836F6E3018BDC2180095E648 /* ahx.c */,
|
836F6E3018BDC2180095E648 /* ahx.c */,
|
||||||
|
@ -1252,8 +1284,6 @@
|
||||||
836F6ED718BDC2190095E648 /* ps3_klbs.c */,
|
836F6ED718BDC2190095E648 /* ps3_klbs.c */,
|
||||||
836F6ED818BDC2190095E648 /* ps3_msf.c */,
|
836F6ED818BDC2190095E648 /* ps3_msf.c */,
|
||||||
836F6ED918BDC2190095E648 /* ps3_past.c */,
|
836F6ED918BDC2190095E648 /* ps3_past.c */,
|
||||||
836F6EDA18BDC2190095E648 /* ps3_sgh_sgb.c */,
|
|
||||||
836F6EDB18BDC2190095E648 /* ps3_vawx.c */,
|
|
||||||
836F6EDC18BDC2190095E648 /* ps3_xvag.c */,
|
836F6EDC18BDC2190095E648 /* ps3_xvag.c */,
|
||||||
836F6EDD18BDC2190095E648 /* psx_cdxa.c */,
|
836F6EDD18BDC2190095E648 /* psx_cdxa.c */,
|
||||||
836F6EDE18BDC2190095E648 /* psx_fag.c */,
|
836F6EDE18BDC2190095E648 /* psx_fag.c */,
|
||||||
|
@ -1353,12 +1383,14 @@
|
||||||
files = (
|
files = (
|
||||||
836F705518BDC2190095E648 /* streamtypes.h in Headers */,
|
836F705518BDC2190095E648 /* streamtypes.h in Headers */,
|
||||||
836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */,
|
836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */,
|
||||||
|
831BA62A1EAC61CB00CF89B0 /* wwise_vorbis_data.h in Headers */,
|
||||||
836F6F3518BDC2190095E648 /* nwa_decoder.h in Headers */,
|
836F6F3518BDC2190095E648 /* nwa_decoder.h in Headers */,
|
||||||
836F6F2718BDC2190095E648 /* g72x_state.h in Headers */,
|
836F6F2718BDC2190095E648 /* g72x_state.h in Headers */,
|
||||||
836F705418BDC2190095E648 /* streamfile.h in Headers */,
|
836F705418BDC2190095E648 /* streamfile.h in Headers */,
|
||||||
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */,
|
83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */,
|
||||||
8323894B1D22419B00482226 /* clHCA.h in Headers */,
|
8323894B1D22419B00482226 /* clHCA.h in Headers */,
|
||||||
83A3F0751E3AD8B900D6A794 /* formats.h in Headers */,
|
83A3F0751E3AD8B900D6A794 /* formats.h in Headers */,
|
||||||
|
831BA62D1EAC61CB00CF89B0 /* wwise_vorbis_utils.h in Headers */,
|
||||||
83299FCD1E76607A003A3242 /* header.h in Headers */,
|
83299FCD1E76607A003A3242 /* header.h in Headers */,
|
||||||
836F705918BDC2190095E648 /* vgmstream.h in Headers */,
|
836F705918BDC2190095E648 /* vgmstream.h in Headers */,
|
||||||
48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */,
|
48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */,
|
||||||
|
@ -1532,7 +1564,6 @@
|
||||||
836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */,
|
836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */,
|
||||||
836F700C18BDC2190095E648 /* ps2_wb.c in Sources */,
|
836F700C18BDC2190095E648 /* ps2_wb.c in Sources */,
|
||||||
836F6F7D18BDC2190095E648 /* dc_str.c in Sources */,
|
836F6F7D18BDC2190095E648 /* dc_str.c in Sources */,
|
||||||
836F701718BDC2190095E648 /* ps3_vawx.c in Sources */,
|
|
||||||
83A5F75F198DF021009AF94C /* bfwav.c in Sources */,
|
83A5F75F198DF021009AF94C /* bfwav.c in Sources */,
|
||||||
836F702018BDC2190095E648 /* rkv.c in Sources */,
|
836F702018BDC2190095E648 /* rkv.c in Sources */,
|
||||||
836F703218BDC2190095E648 /* str_asr.c in Sources */,
|
836F703218BDC2190095E648 /* str_asr.c in Sources */,
|
||||||
|
@ -1589,10 +1620,10 @@
|
||||||
836F6F2418BDC2190095E648 /* eaxa_decoder.c in Sources */,
|
836F6F2418BDC2190095E648 /* eaxa_decoder.c in Sources */,
|
||||||
836F6F7A18BDC2190095E648 /* dc_dcsw_dcs.c in Sources */,
|
836F6F7A18BDC2190095E648 /* dc_dcsw_dcs.c in Sources */,
|
||||||
836F6F5318BDC2190095E648 /* ps2_iab_blocked.c in Sources */,
|
836F6F5318BDC2190095E648 /* ps2_iab_blocked.c in Sources */,
|
||||||
|
831BA61A1EAC61A500CF89B0 /* ps2_vds_vdm.c in Sources */,
|
||||||
836F6FF218BDC2190095E648 /* ps2_rnd.c in Sources */,
|
836F6FF218BDC2190095E648 /* ps2_rnd.c in Sources */,
|
||||||
836F6FA818BDC2190095E648 /* nds_swav.c in Sources */,
|
836F6FA818BDC2190095E648 /* nds_swav.c in Sources */,
|
||||||
836F6F3F18BDC2190095E648 /* ast_blocked.c in Sources */,
|
836F6F3F18BDC2190095E648 /* ast_blocked.c in Sources */,
|
||||||
83299FC61E76606B003A3242 /* ffmpeg_decoder_utils.c in Sources */,
|
|
||||||
836F6F5018BDC2190095E648 /* mxch_blocked.c in Sources */,
|
836F6F5018BDC2190095E648 /* mxch_blocked.c in Sources */,
|
||||||
836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */,
|
836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */,
|
||||||
836F6F4F18BDC2190095E648 /* mus_acm_layout.c in Sources */,
|
836F6F4F18BDC2190095E648 /* mus_acm_layout.c in Sources */,
|
||||||
|
@ -1643,7 +1674,6 @@
|
||||||
836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */,
|
836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */,
|
||||||
836F6F7318BDC2190095E648 /* bcstm.c in Sources */,
|
836F6F7318BDC2190095E648 /* bcstm.c in Sources */,
|
||||||
83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */,
|
83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */,
|
||||||
83A3F07D1E3AD92400D6A794 /* x360.c in Sources */,
|
|
||||||
836F704018BDC2190095E648 /* wii_sng.c in Sources */,
|
836F704018BDC2190095E648 /* wii_sng.c in Sources */,
|
||||||
8350C0551E071881009E0A93 /* xma.c in Sources */,
|
8350C0551E071881009E0A93 /* xma.c in Sources */,
|
||||||
836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */,
|
836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */,
|
||||||
|
@ -1694,7 +1724,6 @@
|
||||||
836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */,
|
836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */,
|
||||||
836F6FE718BDC2190095E648 /* ps2_mib.c in Sources */,
|
836F6FE718BDC2190095E648 /* ps2_mib.c in Sources */,
|
||||||
836F6FAB18BDC2190095E648 /* ngc_bo2.c in Sources */,
|
836F6FAB18BDC2190095E648 /* ngc_bo2.c in Sources */,
|
||||||
83A3F07C1E3AD92400D6A794 /* ps2.c in Sources */,
|
|
||||||
836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */,
|
836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */,
|
||||||
836F702118BDC2190095E648 /* rs03.c in Sources */,
|
836F702118BDC2190095E648 /* rs03.c in Sources */,
|
||||||
836F6F8418BDC2190095E648 /* emff.c in Sources */,
|
836F6F8418BDC2190095E648 /* emff.c in Sources */,
|
||||||
|
@ -1703,6 +1732,7 @@
|
||||||
836F6F4618BDC2190095E648 /* filp_blocked.c in Sources */,
|
836F6F4618BDC2190095E648 /* filp_blocked.c in Sources */,
|
||||||
836F6FE518BDC2190095E648 /* ps2_lpcm.c in Sources */,
|
836F6FE518BDC2190095E648 /* ps2_lpcm.c in Sources */,
|
||||||
836F6FB318BDC2190095E648 /* ngc_lps.c in Sources */,
|
836F6FB318BDC2190095E648 /* ngc_lps.c in Sources */,
|
||||||
|
831BA6201EAC61A500CF89B0 /* x360_nub.c in Sources */,
|
||||||
836F6FC018BDC2190095E648 /* p3d.c in Sources */,
|
836F6FC018BDC2190095E648 /* p3d.c in Sources */,
|
||||||
836F6FC718BDC2190095E648 /* pona.c in Sources */,
|
836F6FC718BDC2190095E648 /* pona.c in Sources */,
|
||||||
836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */,
|
836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */,
|
||||||
|
@ -1710,19 +1740,24 @@
|
||||||
836F6F5118BDC2190095E648 /* nolayout.c in Sources */,
|
836F6F5118BDC2190095E648 /* nolayout.c in Sources */,
|
||||||
836F702918BDC2190095E648 /* sat_sap.c in Sources */,
|
836F702918BDC2190095E648 /* sat_sap.c in Sources */,
|
||||||
836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */,
|
836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */,
|
||||||
|
831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */,
|
||||||
836F6F5B18BDC2190095E648 /* ws_aud_blocked.c in Sources */,
|
836F6F5B18BDC2190095E648 /* ws_aud_blocked.c in Sources */,
|
||||||
836F700218BDC2190095E648 /* ps2_tk5.c in Sources */,
|
836F700218BDC2190095E648 /* ps2_tk5.c in Sources */,
|
||||||
|
831BA61D1EAC61A500CF89B0 /* ubi_raki.c in Sources */,
|
||||||
836F703F18BDC2190095E648 /* wii_smp.c in Sources */,
|
836F703F18BDC2190095E648 /* wii_smp.c in Sources */,
|
||||||
836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */,
|
836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */,
|
||||||
836F701518BDC2190095E648 /* ps3_past.c in Sources */,
|
836F701518BDC2190095E648 /* ps3_past.c in Sources */,
|
||||||
836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */,
|
836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */,
|
||||||
836F6FED18BDC2190095E648 /* ps2_npsf.c in Sources */,
|
836F6FED18BDC2190095E648 /* ps2_npsf.c in Sources */,
|
||||||
836F6F9E18BDC2190095E648 /* mus_acm.c in Sources */,
|
836F6F9E18BDC2190095E648 /* mus_acm.c in Sources */,
|
||||||
|
831BA6191EAC61A500CF89B0 /* ogl.c in Sources */,
|
||||||
|
831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */,
|
||||||
836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */,
|
836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */,
|
||||||
836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */,
|
836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */,
|
||||||
836F6F4A18BDC2190095E648 /* interleave.c in Sources */,
|
836F6F4A18BDC2190095E648 /* interleave.c in Sources */,
|
||||||
836F6FFD18BDC2190095E648 /* ps2_stm.c in Sources */,
|
836F6FFD18BDC2190095E648 /* ps2_stm.c in Sources */,
|
||||||
83EDE5D81A70951A005F5D84 /* mca.c in Sources */,
|
83EDE5D81A70951A005F5D84 /* mca.c in Sources */,
|
||||||
|
831BA61B1EAC61A500CF89B0 /* sgxd.c in Sources */,
|
||||||
838BDB6C1D3AFAB10022CA6F /* ffmpeg_decoder.c in Sources */,
|
838BDB6C1D3AFAB10022CA6F /* ffmpeg_decoder.c in Sources */,
|
||||||
836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */,
|
836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */,
|
||||||
836F702F18BDC2190095E648 /* spt_spd.c in Sources */,
|
836F702F18BDC2190095E648 /* spt_spd.c in Sources */,
|
||||||
|
@ -1736,6 +1771,7 @@
|
||||||
836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */,
|
836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */,
|
||||||
836F703D18BDC2190095E648 /* wii_mus.c in Sources */,
|
836F703D18BDC2190095E648 /* wii_mus.c in Sources */,
|
||||||
836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */,
|
836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */,
|
||||||
|
831BA61C1EAC61A500CF89B0 /* sxd.c in Sources */,
|
||||||
836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */,
|
836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */,
|
||||||
836F6F9618BDC2190095E648 /* lsf.c in Sources */,
|
836F6F9618BDC2190095E648 /* lsf.c in Sources */,
|
||||||
836F6FC818BDC2190095E648 /* pos.c in Sources */,
|
836F6FC818BDC2190095E648 /* pos.c in Sources */,
|
||||||
|
@ -1750,6 +1786,7 @@
|
||||||
836F703318BDC2190095E648 /* str_snds.c in Sources */,
|
836F703318BDC2190095E648 /* str_snds.c in Sources */,
|
||||||
836F703718BDC2190095E648 /* tun.c in Sources */,
|
836F703718BDC2190095E648 /* tun.c in Sources */,
|
||||||
836F700B18BDC2190095E648 /* ps2_wad.c in Sources */,
|
836F700B18BDC2190095E648 /* ps2_wad.c in Sources */,
|
||||||
|
831BA61E1EAC61A500CF89B0 /* vawx.c in Sources */,
|
||||||
836F702A18BDC2190095E648 /* sd9.c in Sources */,
|
836F702A18BDC2190095E648 /* sd9.c in Sources */,
|
||||||
836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */,
|
836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */,
|
||||||
836F6F4418BDC2190095E648 /* ea_block.c in Sources */,
|
836F6F4418BDC2190095E648 /* ea_block.c in Sources */,
|
||||||
|
@ -1768,11 +1805,14 @@
|
||||||
836F6F2118BDC2190095E648 /* aica_decoder.c in Sources */,
|
836F6F2118BDC2190095E648 /* aica_decoder.c in Sources */,
|
||||||
836F700318BDC2190095E648 /* ps2_vag.c in Sources */,
|
836F700318BDC2190095E648 /* ps2_vag.c in Sources */,
|
||||||
836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */,
|
836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */,
|
||||||
|
831BA6211EAC61A500CF89B0 /* x360_pasx.c in Sources */,
|
||||||
836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */,
|
836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */,
|
||||||
836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */,
|
836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */,
|
||||||
|
831BA6181EAC61A500CF89B0 /* adx.c in Sources */,
|
||||||
836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */,
|
836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */,
|
||||||
836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */,
|
836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */,
|
||||||
836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */,
|
836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */,
|
||||||
|
831BA62B1EAC61CB00CF89B0 /* wwise_vorbis_decoder.c in Sources */,
|
||||||
836F6FC918BDC2190095E648 /* ps2_2pfs.c in Sources */,
|
836F6FC918BDC2190095E648 /* ps2_2pfs.c in Sources */,
|
||||||
836F704818BDC2190095E648 /* xbox_ims.c in Sources */,
|
836F704818BDC2190095E648 /* xbox_ims.c in Sources */,
|
||||||
836F6F4918BDC2190095E648 /* ims_block.c in Sources */,
|
836F6F4918BDC2190095E648 /* ims_block.c in Sources */,
|
||||||
|
@ -1792,7 +1832,6 @@
|
||||||
836F703E18BDC2190095E648 /* wii_ras.c in Sources */,
|
836F703E18BDC2190095E648 /* wii_ras.c in Sources */,
|
||||||
836F6FF518BDC2190095E648 /* ps2_rxw.c in Sources */,
|
836F6FF518BDC2190095E648 /* ps2_rxw.c in Sources */,
|
||||||
836F6FEA18BDC2190095E648 /* ps2_msa.c in Sources */,
|
836F6FEA18BDC2190095E648 /* ps2_msa.c in Sources */,
|
||||||
836F701618BDC2190095E648 /* ps3_sgh_sgb.c in Sources */,
|
|
||||||
836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */,
|
836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */,
|
||||||
836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */,
|
836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */,
|
||||||
836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */,
|
836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */,
|
||||||
|
@ -1807,10 +1846,12 @@
|
||||||
836F6F3818BDC2190095E648 /* psx_decoder.c in Sources */,
|
836F6F3818BDC2190095E648 /* psx_decoder.c in Sources */,
|
||||||
836F6F2D18BDC2190095E648 /* mpeg_decoder.c in Sources */,
|
836F6F2D18BDC2190095E648 /* mpeg_decoder.c in Sources */,
|
||||||
836F6F2618BDC2190095E648 /* g7221_decoder.c in Sources */,
|
836F6F2618BDC2190095E648 /* g7221_decoder.c in Sources */,
|
||||||
|
831BA6291EAC61CB00CF89B0 /* ogl_vorbis_decoder.c in Sources */,
|
||||||
836F6FA218BDC2190095E648 /* naomi_adpcm.c in Sources */,
|
836F6FA218BDC2190095E648 /* naomi_adpcm.c in Sources */,
|
||||||
836F6FBF18BDC2190095E648 /* otm.c in Sources */,
|
836F6FBF18BDC2190095E648 /* otm.c in Sources */,
|
||||||
836F6FDD18BDC2190095E648 /* ps2_ikm.c in Sources */,
|
836F6FDD18BDC2190095E648 /* ps2_ikm.c in Sources */,
|
||||||
836F6FBD18BDC2190095E648 /* nwa.c in Sources */,
|
836F6FBD18BDC2190095E648 /* nwa.c in Sources */,
|
||||||
|
831BA62C1EAC61CB00CF89B0 /* wwise_vorbis_utils.c in Sources */,
|
||||||
836F6FC418BDC2190095E648 /* pc_snds.c in Sources */,
|
836F6FC418BDC2190095E648 /* pc_snds.c in Sources */,
|
||||||
836F704E18BDC2190095E648 /* xss.c in Sources */,
|
836F704E18BDC2190095E648 /* xss.c in Sources */,
|
||||||
836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */,
|
836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */,
|
||||||
|
@ -1820,7 +1861,6 @@
|
||||||
838BDB6E1D3B043C0022CA6F /* ffmpeg.c in Sources */,
|
838BDB6E1D3B043C0022CA6F /* ffmpeg.c in Sources */,
|
||||||
836F6F5D18BDC2190095E648 /* xa_blocked.c in Sources */,
|
836F6F5D18BDC2190095E648 /* xa_blocked.c in Sources */,
|
||||||
836F6F3418BDC2190095E648 /* nwa_decoder.c in Sources */,
|
836F6F3418BDC2190095E648 /* nwa_decoder.c in Sources */,
|
||||||
836F6F6918BDC2190095E648 /* adx_header.c in Sources */,
|
|
||||||
836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */,
|
836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */,
|
||||||
836F6F9218BDC2190095E648 /* ish_isd.c in Sources */,
|
836F6F9218BDC2190095E648 /* ish_isd.c in Sources */,
|
||||||
836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */,
|
836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */,
|
||||||
|
|
|
@ -32,5 +32,8 @@ libcoding_la_SOURCES += mtaf_decoder.c
|
||||||
libcoding_la_SOURCES += g719_decoder.c
|
libcoding_la_SOURCES += g719_decoder.c
|
||||||
libcoding_la_SOURCES += hca_decoder.c
|
libcoding_la_SOURCES += hca_decoder.c
|
||||||
libcoding_la_SOURCES += fsb_vorbis_decoder.c
|
libcoding_la_SOURCES += fsb_vorbis_decoder.c
|
||||||
|
libcoding_la_SOURCES += wwise_vorbis_decoder.c
|
||||||
|
libcoding_la_SOURCES += wwise_vorbis_utils.c
|
||||||
|
libcoding_la_SOURCES += ogl_vorbis_decoder.c
|
||||||
|
|
||||||
EXTRA_DIST = coding.h g72x_state.h clHCA.h
|
EXTRA_DIST = coding.h g72x_state.h clHCA.h
|
||||||
|
|
|
@ -27,11 +27,13 @@ void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelsp
|
||||||
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||||
void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||||
void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||||
|
void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||||
|
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
|
||||||
|
|
||||||
/* ngc_dsp_decoder */
|
/* ngc_dsp_decoder */
|
||||||
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem);
|
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem);
|
||||||
|
size_t dsp_bytes_to_samples(size_t bytes, int channels);
|
||||||
int32_t dsp_nibbles_to_samples(int32_t nibbles);
|
int32_t dsp_nibbles_to_samples(int32_t nibbles);
|
||||||
void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
|
void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
|
||||||
void dsp_read_coefs_le(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
|
void dsp_read_coefs_le(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
|
||||||
|
@ -53,6 +55,7 @@ void decode_pcm8_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac
|
||||||
void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
|
||||||
|
|
||||||
/* psx_decoder */
|
/* psx_decoder */
|
||||||
void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
@ -60,6 +63,7 @@ void decode_psx_badflags(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
|
||||||
void decode_psx_bmdx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_psx_bmdx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size);
|
void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size);
|
||||||
void decode_hevag(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_hevag(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
size_t ps_bytes_to_samples(size_t bytes, int channels);
|
||||||
|
|
||||||
/* xa_decoder */
|
/* xa_decoder */
|
||||||
void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||||
|
@ -87,9 +91,9 @@ void decode_acm(ACMStream * acm, sample * outbuf, int32_t samples_to_do, int cha
|
||||||
void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do);
|
void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do);
|
||||||
|
|
||||||
/* msadpcm_decoder */
|
/* msadpcm_decoder */
|
||||||
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
|
|
||||||
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
|
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
|
||||||
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
|
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
|
||||||
|
|
||||||
/* aica_decoder */
|
/* aica_decoder */
|
||||||
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
@ -124,6 +128,23 @@ void decode_fsb_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_t
|
||||||
void free_fsb_vorbis(vorbis_codec_data *data);
|
void free_fsb_vorbis(vorbis_codec_data *data);
|
||||||
void reset_fsb_vorbis(VGMSTREAM *vgmstream);
|
void reset_fsb_vorbis(VGMSTREAM *vgmstream);
|
||||||
void seek_fsb_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
void seek_fsb_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||||
|
|
||||||
|
/* wwise_vorbis_decoder */
|
||||||
|
vorbis_codec_data * init_wwise_vorbis_codec_data(STREAMFILE *streamfile, off_t start_offset, int channels, int sample_rate, int blocksize_0_exp, int blocksize_1_exp,
|
||||||
|
wwise_setup_type setup_type, wwise_header_type header_type, wwise_packet_type packet_type, int big_endian);
|
||||||
|
void decode_wwise_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||||
|
|
||||||
|
void free_wwise_vorbis(vorbis_codec_data *data);
|
||||||
|
void reset_wwise_vorbis(VGMSTREAM *vgmstream);
|
||||||
|
void seek_wwise_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||||
|
|
||||||
|
/* ogl_vorbis_decoder */
|
||||||
|
vorbis_codec_data * init_ogl_vorbis_codec_data(STREAMFILE *streamFile, off_t start_offset, off_t * data_start_offset);
|
||||||
|
void decode_ogl_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||||
|
|
||||||
|
void free_ogl_vorbis(vorbis_codec_data *data);
|
||||||
|
void reset_ogl_vorbis(VGMSTREAM *vgmstream);
|
||||||
|
void seek_ogl_vorbis(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* mpeg_decoder */
|
/* mpeg_decoder */
|
||||||
|
@ -163,33 +184,35 @@ void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_
|
||||||
void decode_at3plus(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
void decode_at3plus(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
|
||||||
/* ffmpeg_decoder */
|
/* ffmpeg_decoder */
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels);
|
void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels);
|
||||||
void reset_ffmpeg(VGMSTREAM *vgmstream);
|
void reset_ffmpeg(VGMSTREAM *vgmstream);
|
||||||
void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample);
|
void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample);
|
||||||
|
|
||||||
void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples);
|
void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ffmpeg_decoder_utils */
|
/* coding_utils */
|
||||||
int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, size_t chunk_size, uint16_t codec);
|
int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, size_t chunk_size, uint16_t codec);
|
||||||
int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay);
|
int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay);
|
||||||
int ffmpeg_make_riff_atrac3plus(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay);
|
int ffmpeg_make_riff_atrac3plus(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay);
|
||||||
int ffmpeg_make_riff_xma1(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode);
|
int ffmpeg_make_riff_xma1(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode);
|
||||||
int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size);
|
int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size);
|
||||||
int ffmpeg_make_riff_xma_from_fmt(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian);
|
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian);
|
||||||
int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t sample_count, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align);
|
int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t * buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE *streamFile);
|
||||||
|
int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align);
|
||||||
|
|
||||||
/* XMA sample parser info (struct to avoid passing so much stuff, separate for reusing) */
|
/* MS audio format's sample info (struct to avoid passing so much stuff, separate for reusing) */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int xma_version;
|
int xma_version;
|
||||||
int channels;
|
int channels;
|
||||||
int stream_mode;
|
int stream_mode;
|
||||||
off_t data_offset;
|
off_t data_offset;
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
int loop_flag;
|
|
||||||
/* frame offsets */
|
/* frame offsets */
|
||||||
|
int loop_flag;
|
||||||
uint32_t loop_start_b;
|
uint32_t loop_start_b;
|
||||||
uint32_t loop_end_b;
|
uint32_t loop_end_b;
|
||||||
uint32_t loop_start_subframe;
|
uint32_t loop_start_subframe;
|
||||||
|
@ -200,9 +223,17 @@ typedef struct {
|
||||||
int32_t skip_samples;
|
int32_t skip_samples;
|
||||||
int32_t loop_start_sample;
|
int32_t loop_start_sample;
|
||||||
int32_t loop_end_sample;
|
int32_t loop_end_sample;
|
||||||
} xma_sample_data;
|
} ms_sample_data;
|
||||||
void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile);
|
void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile);
|
||||||
|
void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags);
|
||||||
|
void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags);
|
||||||
|
|
||||||
|
void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * loop_start_b, int32_t * loop_end_b, int32_t * loop_subframe, int be);
|
||||||
|
void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample, int be);
|
||||||
|
void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample);
|
||||||
|
|
||||||
|
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
|
||||||
|
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*_CODING_H*/
|
#endif /*_CODING_H*/
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
#include "coding.h"
|
#include "coding.h"
|
||||||
|
#include "math.h"
|
||||||
#include "../vgmstream.h"
|
#include "../vgmstream.h"
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
|
||||||
|
|
||||||
#define XMA_CHECK_SKIPS 0
|
/**
|
||||||
#define XMA_BYTES_PER_PACKET 2048
|
* Various utils for formats that aren't handled their own decoder or meta
|
||||||
#define XMA_SAMPLES_PER_FRAME 512
|
*
|
||||||
#define XMA_SAMPLES_PER_SUBFRAME 128
|
* ffmpeg_make_riff_* utils don't depend on FFmpeg, but rather, they make headers that FFmpeg
|
||||||
|
* can use (it doesn't understand all valid RIFF headers, nor the utils make 100% correct headers).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* ******************************************** */
|
/* ******************************************** */
|
||||||
/* INTERNAL UTILS */
|
/* INTERNAL UTILS */
|
||||||
|
@ -256,11 +259,13 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s
|
||||||
return riff_size;
|
return riff_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ffmpeg_make_riff_xma_from_fmt(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian) {
|
/* Makes a XMA1/2 RIFF header for FFmpeg using a "fmt " chunk (XMAWAVEFORMAT or XMA2WAVEFORMATEX) as a base:
|
||||||
|
* Useful to preserve the stream layout */
|
||||||
|
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian) {
|
||||||
size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4;
|
size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4;
|
||||||
uint8_t chunk[100];
|
uint8_t chunk[0x100];
|
||||||
|
|
||||||
if (buf_size < riff_size || fmt_size > 100)
|
if (buf_size < riff_size || fmt_size > 0x100)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (read_streamfile(chunk,fmt_offset,fmt_size, streamFile) != fmt_size)
|
if (read_streamfile(chunk,fmt_offset,fmt_size, streamFile) != fmt_size)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -287,7 +292,52 @@ fail:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t sample_count, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align) {
|
/* Makes a XMA2 RIFF header for FFmpeg using a "XMA2" chunk (XMA2WAVEFORMAT) as a base.
|
||||||
|
* Useful to preserve the stream layout */
|
||||||
|
int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t * buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE *streamFile) {
|
||||||
|
uint8_t chunk[0x100];
|
||||||
|
size_t riff_size;
|
||||||
|
size_t xma2_final_size = xma2_size;
|
||||||
|
int xma2_chunk_version = read_8bit(xma2_offset,streamFile);
|
||||||
|
|
||||||
|
/* FFmpeg can't parse v3 "XMA2" chunks so we'll have to extend (8 bytes in the middle) */
|
||||||
|
if (xma2_chunk_version == 3)
|
||||||
|
xma2_final_size += 0x8;
|
||||||
|
riff_size = 4+4+ 4 + 4+4+xma2_final_size + 4+4;
|
||||||
|
|
||||||
|
if (buf_size < riff_size || xma2_final_size > 0x100)
|
||||||
|
goto fail;
|
||||||
|
if (read_streamfile(chunk,xma2_offset,xma2_size, streamFile) != xma2_size)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
memcpy(buf+0x00, "RIFF", 4);
|
||||||
|
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
|
||||||
|
memcpy(buf+0x08, "WAVE", 4);
|
||||||
|
|
||||||
|
memcpy(buf+0x0c, "XMA2", 4);
|
||||||
|
put_32bitLE(buf+0x10, xma2_final_size);
|
||||||
|
if (xma2_chunk_version == 3) {
|
||||||
|
/* old XMA2 v3: change to v4 (extra 8 bytes in the middle); always BE */
|
||||||
|
put_8bit (buf+0x14 + 0x00, 4); /* v4 */
|
||||||
|
memcpy (buf+0x14 + 0x01, chunk+1, 0xF); /* first v3 part (fixed) */
|
||||||
|
put_32bitBE(buf+0x14 + 0x10, 0x000010D6); /* extra v4 BE: "EncodeOptions" (not used by FFmpeg) */
|
||||||
|
put_32bitBE(buf+0x14 + 0x14, 0); /* extra v4 BE: "PsuedoBytesPerSec" (not used by FFmpeg) */
|
||||||
|
memcpy (buf+0x14 + 0x18, chunk+0x10, xma2_size - 0x10); /* second v3 part (variable size) */
|
||||||
|
} else {
|
||||||
|
memcpy(buf+0x14, chunk, xma2_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf+0x14+xma2_final_size, "data", 4);
|
||||||
|
put_32bitLE(buf+0x14+xma2_final_size+4, data_size); /* data size */
|
||||||
|
|
||||||
|
return riff_size;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align) {
|
||||||
size_t riff_size = 4+4+ 4 + 0x1a + 4+4;
|
size_t riff_size = 4+4+ 4 + 0x1a + 4+4;
|
||||||
|
|
||||||
if (buf_size < riff_size)
|
if (buf_size < riff_size)
|
||||||
|
@ -302,11 +352,11 @@ int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t samp
|
||||||
put_16bitLE(buf+0x14, codec);
|
put_16bitLE(buf+0x14, codec);
|
||||||
put_16bitLE(buf+0x16, channels);
|
put_16bitLE(buf+0x16, channels);
|
||||||
put_32bitLE(buf+0x18, sample_rate);
|
put_32bitLE(buf+0x18, sample_rate);
|
||||||
put_32bitLE(buf+0x1c, avg_bps); /* average bits per second, somehow vital for XWMA */
|
put_32bitLE(buf+0x1c, avg_bps); /* average bytes per second, somehow vital for XWMA */
|
||||||
put_16bitLE(buf+0x20, block_align); /* block align */
|
put_16bitLE(buf+0x20, block_align); /* block align */
|
||||||
put_16bitLE(buf+0x22, 16); /* bits per sample */
|
put_16bitLE(buf+0x22, 16); /* bits per sample */
|
||||||
put_16bitLE(buf+0x24, 0); /* unk */
|
put_16bitLE(buf+0x24, 0); /* extra size */
|
||||||
/* here goes the "dpds" table, but it's not needed by FFmpeg */
|
/* here goes the "dpds" table, but it's optional and not needed by FFmpeg */
|
||||||
|
|
||||||
memcpy(buf+0x26, "data", 4);
|
memcpy(buf+0x26, "data", 4);
|
||||||
put_32bitLE(buf+0x2a, data_size); /* data size */
|
put_32bitLE(buf+0x2a, data_size); /* data size */
|
||||||
|
@ -374,33 +424,33 @@ fail:
|
||||||
/* ******************************************** */
|
/* ******************************************** */
|
||||||
/* XMA PARSING */
|
/* XMA PARSING */
|
||||||
/* ******************************************** */
|
/* ******************************************** */
|
||||||
|
#define XMA_CHECK_SKIPS 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find total and loop samples by reading XMA frame headers.
|
* Find total and loop samples of Microsoft audio formats (WMAPRO/XMA1/XMA2) by reading frame headers.
|
||||||
*
|
*
|
||||||
* A XMA stream is made of packets, each containing N small frames of X samples.
|
* The stream is made of packets, each containing N small frames of X samples. Frames are further divided into subframes.
|
||||||
* Frames are further divided into subframes for looping purposes.
|
* XMA1/XMA2/WMAPRO only differ in the packet headers.
|
||||||
* XMA1 and XMA2 only differ in the packet headers.
|
|
||||||
*/
|
*/
|
||||||
void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int bytes_per_packet, int samples_per_frame, int samples_per_subframe, int bits_frame_size) {
|
||||||
int frames = 0, samples = 0, loop_start_frame = 0, loop_end_frame = 0, skip_packets;
|
int frames = 0, samples = 0, loop_start_frame = 0, loop_end_frame = 0, skip_packets;
|
||||||
#if XMA_CHECK_SKIPS
|
#if XMA_CHECK_SKIPS
|
||||||
int start_skip = 0, end_skip = 0, first_start_skip = 0, last_end_skip = 0;
|
int start_skip = 0, end_skip = 0, first_start_skip = 0, last_end_skip = 0;
|
||||||
#endif
|
#endif
|
||||||
uint32_t first_frame_b, packet_skip_count = 0, frame_size_b, packet_size_b;
|
uint32_t first_frame_b, packet_skip_count = 0, frame_size_b, packet_size_b, header_size_b;
|
||||||
uint64_t offset_b, packet_offset_b, frame_offset_b;
|
uint64_t offset_b, packet_offset_b, frame_offset_b;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
uint32_t packet_size = XMA_BYTES_PER_PACKET;
|
uint32_t packet_size = bytes_per_packet;
|
||||||
off_t offset = xma->data_offset;
|
off_t offset = msd->data_offset;
|
||||||
uint32_t stream_offset_b = xma->data_offset * 8;
|
uint32_t stream_offset_b = msd->data_offset * 8;
|
||||||
|
|
||||||
size = offset + xma->data_size;
|
size = offset + msd->data_size;
|
||||||
packet_size_b = packet_size * 8;
|
packet_size_b = packet_size * 8;
|
||||||
|
|
||||||
/* if we knew the streams mode then we could read just the first one and adjust samples later
|
/* if we knew the streams mode then we could read just the first one and adjust samples later
|
||||||
* not a big deal but maybe important for skip stuff */
|
* not a big deal but maybe important for skip stuff */
|
||||||
//streams = (xma->stream_mode==0 ? (xma->channels + 1) / 2 : xma->channels)
|
//streams = (msd->stream_mode==0 ? (msd->channels + 1) / 2 : msd->channels)
|
||||||
skip_packets = 0;
|
skip_packets = 0;
|
||||||
|
|
||||||
/* read packets */
|
/* read packets */
|
||||||
|
@ -414,19 +464,28 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XMA1 or XMA2 packet header */
|
/* packet header */
|
||||||
if (xma->xma_version == 1) {
|
if (msd->xma_version == 1) { /* XMA1 */
|
||||||
//packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */
|
//packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */
|
||||||
//unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */
|
//unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */
|
||||||
first_frame_b = read_bitsBE_b(offset_b+6, 15, streamFile); /* offset in bits inside the packet */
|
first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */
|
||||||
packet_skip_count = read_bitsBE_b(offset_b+21, 11, streamFile); /* packets to skip for next packet of this stream */
|
packet_skip_count = read_bitsBE_b(offset_b+21, 11, streamFile); /* packets to skip for next packet of this stream */
|
||||||
} else {
|
header_size_b = 32;
|
||||||
|
} else if (msd->xma_version == 2) { /* XMA2 */
|
||||||
//frame_count = read_bitsBE_b(offset_b+0, 6, streamFile); /* frames that begin in this packet */
|
//frame_count = read_bitsBE_b(offset_b+0, 6, streamFile); /* frames that begin in this packet */
|
||||||
first_frame_b = read_bitsBE_b(offset_b+6, 15, streamFile); /* offset in bits inside this packet */
|
first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside this packet */
|
||||||
//packet_metadata = read_bitsBE_b(offset_b+21, 3, streamFile); /* packet_metadata (always 1) */
|
//packet_metadata = read_bitsBE_b(offset_b+21, 3, streamFile); /* packet_metadata (always 1) */
|
||||||
packet_skip_count = read_bitsBE_b(offset_b+24, 8, streamFile); /* packets to skip for next packet of this stream */
|
packet_skip_count = read_bitsBE_b(offset_b+24, 8, streamFile); /* packets to skip for next packet of this stream */
|
||||||
|
header_size_b = 32;
|
||||||
|
} else { /* WMAPRO(v3) */
|
||||||
|
//packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */
|
||||||
|
//unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */
|
||||||
|
first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */
|
||||||
|
packet_skip_count = 0; /* xwma probably has no need to skip packets since it uses real multichannel ch audio */
|
||||||
|
header_size_b = 4+2+bits_frame_size; /* variable-size header */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* full packet skip */
|
/* full packet skip */
|
||||||
if (packet_skip_count == 0x7FF) {
|
if (packet_skip_count == 0x7FF) {
|
||||||
packet_skip_count = 0;
|
packet_skip_count = 0;
|
||||||
|
@ -438,22 +497,22 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
VGM_ASSERT(packet_skip_count > 10, "XMA: found big packet skip %i\n", packet_skip_count);//a bit unusual...
|
VGM_ASSERT(packet_skip_count > 10, "XMA: found big packet skip %i\n", packet_skip_count);//a bit unusual...
|
||||||
//VGM_LOG("packet: off=%x, ff=%i, ps=%i\n", offset, first_frame_b, packet_skip_b);
|
//VGM_LOG("packet: off=%x, ff=%i, ps=%i\n", offset, first_frame_b, packet_skip_b);
|
||||||
|
|
||||||
packet_offset_b = 4*8 + first_frame_b; /* packet offset in bits */
|
packet_offset_b = header_size_b + first_frame_b; /* packet offset in bits */
|
||||||
|
|
||||||
/* read packet frames */
|
/* read packet frames */
|
||||||
while (packet_offset_b < packet_size_b) {
|
while (packet_offset_b < packet_size_b) {
|
||||||
frame_offset_b = offset_b + packet_offset_b; /* in bits for aligment stuff */
|
frame_offset_b = offset_b + packet_offset_b; /* in bits for aligment stuff */
|
||||||
|
|
||||||
//todo not sure if frames or frames+1 (considering skip_samples)
|
//todo not sure if frames or frames+1 (considering skip_samples)
|
||||||
if (xma->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == xma->loop_start_b)
|
if (msd->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == msd->loop_start_b)
|
||||||
loop_start_frame = frames;
|
loop_start_frame = frames;
|
||||||
if (xma->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == xma->loop_end_b)
|
if (msd->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == msd->loop_end_b)
|
||||||
loop_end_frame = frames;
|
loop_end_frame = frames;
|
||||||
|
|
||||||
|
|
||||||
/* XMA1/2 frame header */
|
/* frame header */
|
||||||
frame_size_b = read_bitsBE_b(frame_offset_b, 15, streamFile);
|
frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, streamFile);
|
||||||
frame_offset_b += 15;
|
frame_offset_b += bits_frame_size;
|
||||||
if (frame_size_b == 0) /* observed in some files with empty frames/packets */
|
if (frame_size_b == 0) /* observed in some files with empty frames/packets */
|
||||||
break;
|
break;
|
||||||
packet_offset_b += frame_size_b; /* including header */
|
packet_offset_b += frame_size_b; /* including header */
|
||||||
|
@ -469,7 +528,7 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
// continue; // todo read packet end bit instead
|
// continue; // todo read packet end bit instead
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
frame_offset_b += 15;
|
frame_offset_b += 15; //todo bits_frame_size?
|
||||||
|
|
||||||
if (frame_size_b == 0x7FFF) { /* end packet frame marker */
|
if (frame_size_b == 0x7FFF) { /* end packet frame marker */
|
||||||
break;
|
break;
|
||||||
|
@ -481,14 +540,14 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
int flag;
|
int flag;
|
||||||
|
|
||||||
/* ignore "postproc transform" */
|
/* ignore "postproc transform" */
|
||||||
if (xma->channels > 1) {
|
if (msd->channels > 1) {
|
||||||
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
|
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
|
||||||
frame_offset_b += 1;
|
frame_offset_b += 1;
|
||||||
if (flag) {
|
if (flag) {
|
||||||
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
|
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
|
||||||
frame_offset_b += 1;
|
frame_offset_b += 1;
|
||||||
if (flag) {
|
if (flag) {
|
||||||
frame_offset_b += 1 + 4 * xma->channels*xma->channels; /* 4-something per double channel? */
|
frame_offset_b += 1 + 4 * msd->channels*msd->channels; /* 4-something per double channel? */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,9 +567,9 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
frame_offset_b += 10;
|
frame_offset_b += 10;
|
||||||
VGM_ASSERT(start_skip, "XMA: more than one start_skip (%i)\n", new_skip);
|
VGM_ASSERT(start_skip, "XMA: more than one start_skip (%i)\n", new_skip);
|
||||||
|
|
||||||
if (new_skip > XMA_SAMPLES_PER_FRAME) { /* from xmaencode */
|
if (new_skip > samples_per_frame) { /* from xmaencode */
|
||||||
VGM_LOG("XMA: bad start_skip (%i)\n", new_skip);
|
VGM_LOG("XMA: bad start_skip (%i)\n", new_skip);
|
||||||
new_skip = XMA_SAMPLES_PER_FRAME;
|
new_skip = samples_per_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frames==0) first_start_skip = new_skip; /* sometimes in the middle */
|
if (frames==0) first_start_skip = new_skip; /* sometimes in the middle */
|
||||||
|
@ -526,9 +585,9 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
frame_offset_b += 10;
|
frame_offset_b += 10;
|
||||||
VGM_ASSERT(end_skip, "XMA: more than one end_skip (%i)\n", new_skip);
|
VGM_ASSERT(end_skip, "XMA: more than one end_skip (%i)\n", new_skip);
|
||||||
|
|
||||||
if (new_skip > XMA_SAMPLES_PER_FRAME) { /* from xmaencode */
|
if (new_skip > samples_per_frame) { /* from xmaencode */
|
||||||
VGM_LOG("XMA: bad end_skip (%i)\n", new_skip);
|
VGM_LOG("XMA: bad end_skip (%i)\n", new_skip);
|
||||||
new_skip = XMA_SAMPLES_PER_FRAME;
|
new_skip = samples_per_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_end_skip = new_skip; /* not seen */
|
last_end_skip = new_skip; /* not seen */
|
||||||
|
@ -540,7 +599,7 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
samples += XMA_SAMPLES_PER_FRAME;
|
samples += samples_per_frame;
|
||||||
frames++;
|
frames++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -551,20 +610,208 @@ void xma_get_samples(xma_sample_data * xma, STREAMFILE *streamFile) {
|
||||||
samples = samples + 64 - start_skip;
|
samples = samples + 64 - start_skip;
|
||||||
samples = samples + 64 - end_skip;
|
samples = samples + 64 - end_skip;
|
||||||
|
|
||||||
xma->skip_samples = 64 + 512; //todo not always correct
|
msd->skip_samples = 64 + samples_per_frame; //todo not always correct
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xma->num_samples = samples;
|
msd->num_samples = samples;
|
||||||
|
|
||||||
if (xma->loop_flag && loop_end_frame > loop_start_frame) {
|
if (msd->loop_flag && loop_end_frame > loop_start_frame) {
|
||||||
xma->loop_start_sample = loop_start_frame * XMA_SAMPLES_PER_FRAME + xma->loop_start_subframe * XMA_SAMPLES_PER_SUBFRAME;
|
msd->loop_start_sample = loop_start_frame * samples_per_frame + msd->loop_start_subframe * samples_per_subframe;
|
||||||
xma->loop_end_sample = loop_end_frame * XMA_SAMPLES_PER_FRAME + xma->loop_end_subframe * XMA_SAMPLES_PER_SUBFRAME;
|
msd->loop_end_sample = loop_end_frame * samples_per_frame + msd->loop_end_subframe * samples_per_subframe;
|
||||||
#if XMA_CHECK_SKIPS
|
#if XMA_CHECK_SKIPS
|
||||||
/* maybe this is needed */
|
/* maybe this is needed */
|
||||||
//xma->loop_start_sample -= xma->skip_samples;
|
//msd->loop_start_sample -= msd->skip_samples;
|
||||||
//xma->loop_end_sample -= xma->skip_samples;
|
//msd->loop_end_sample -= msd->skip_samples;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
static int wma_get_samples_per_frame(int version, int sample_rate, uint32_t decode_flags) {
|
||||||
|
int frame_len_bits;
|
||||||
|
|
||||||
|
if (sample_rate <= 16000)
|
||||||
|
frame_len_bits = 9;
|
||||||
|
else if (sample_rate <= 22050 || (sample_rate <= 32000 && version == 1))
|
||||||
|
frame_len_bits = 10;
|
||||||
|
else if (sample_rate <= 48000 || version < 3)
|
||||||
|
frame_len_bits = 11;
|
||||||
|
else if (sample_rate <= 96000)
|
||||||
|
frame_len_bits = 12;
|
||||||
|
else
|
||||||
|
frame_len_bits = 13;
|
||||||
|
|
||||||
|
if (version == 3) {
|
||||||
|
int tmp = decode_flags & 0x6;
|
||||||
|
if (tmp == 0x2)
|
||||||
|
++frame_len_bits;
|
||||||
|
else if (tmp == 0x4)
|
||||||
|
--frame_len_bits;
|
||||||
|
else if (tmp == 0x6)
|
||||||
|
frame_len_bits -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 << frame_len_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile) {
|
||||||
|
const int bytes_per_packet = 2048;
|
||||||
|
const int samples_per_frame = 512;
|
||||||
|
const int samples_per_subframe = 128;
|
||||||
|
|
||||||
|
ms_audio_get_samples(msd, streamFile, bytes_per_packet, samples_per_frame, samples_per_subframe, 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) {
|
||||||
|
const int version = 3; /* WMAPRO = WMAv3 */
|
||||||
|
int bytes_per_packet = block_align;
|
||||||
|
int samples_per_frame = 0;
|
||||||
|
int samples_per_subframe = 0;
|
||||||
|
int bits_frame_size = 0;
|
||||||
|
|
||||||
|
/* do some WMAPRO setup (code from ffmpeg) */
|
||||||
|
samples_per_frame = wma_get_samples_per_frame(version, sample_rate, decode_flags);
|
||||||
|
|
||||||
|
/* max bits needed to represent this block_align */
|
||||||
|
bits_frame_size = floor(log(block_align) / log(2)) + 4;
|
||||||
|
|
||||||
|
/* not really needed as I've never seen loop subframe data for WMA (probably possible though)
|
||||||
|
* (FFmpeg has code to get min_samples_per subframe) */
|
||||||
|
samples_per_subframe = 0;
|
||||||
|
|
||||||
|
/* signal it's not XMA */
|
||||||
|
msd->xma_version = 0;
|
||||||
|
|
||||||
|
ms_audio_get_samples(msd, streamFile, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) {
|
||||||
|
const int version = 2; /* WMAv1 rarely used */
|
||||||
|
int use_bit_reservoir = 0; /* last packet frame can spill into the next packet */
|
||||||
|
int samples_per_frame = 0;
|
||||||
|
int num_frames = 0;
|
||||||
|
|
||||||
|
samples_per_frame = wma_get_samples_per_frame(version, sample_rate, decode_flags);
|
||||||
|
|
||||||
|
/* assumed (ASF has a flag for this but XWMA doesn't) */
|
||||||
|
if (version == 2)
|
||||||
|
use_bit_reservoir = 1;
|
||||||
|
|
||||||
|
|
||||||
|
if (!use_bit_reservoir) {
|
||||||
|
/* 1 frame per packet */
|
||||||
|
num_frames = msd->data_size / block_align + (msd->data_size % block_align ? 1 : 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* variable frames per packet (mini-header values) */
|
||||||
|
off_t offset = msd->data_offset;
|
||||||
|
while (offset < msd->data_size) { /* read packets (superframes) */
|
||||||
|
int packet_frames;
|
||||||
|
uint8_t header = read_8bit(offset, streamFile); /* upper nibble: index; lower nibble: frames */
|
||||||
|
|
||||||
|
/* frames starting in this packet (ie. counts frames that spill due to bit_reservoir) */
|
||||||
|
packet_frames = (header & 0xf);
|
||||||
|
|
||||||
|
num_frames += packet_frames;
|
||||||
|
offset += block_align;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msd->num_samples = num_frames * samples_per_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ******************************************** */
|
||||||
|
/* HEADER PARSING */
|
||||||
|
/* ******************************************** */
|
||||||
|
|
||||||
|
/* Read values from a XMA1 RIFF "fmt" chunk (XMAWAVEFORMAT), starting from an offset *after* chunk type+size.
|
||||||
|
* Useful as custom X360 headers commonly have it lurking inside. */
|
||||||
|
void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * loop_start_b, int32_t * loop_end_b, int32_t * loop_subframe, int be) {
|
||||||
|
int16_t (*read_16bit)(off_t,STREAMFILE*) = be ? read_16bitBE : read_16bitLE;
|
||||||
|
int32_t (*read_32bit)(off_t,STREAMFILE*) = be ? read_32bitBE : read_32bitLE;
|
||||||
|
int i, num_streams, total_channels = 0;
|
||||||
|
|
||||||
|
if (read_16bit(chunk_offset+0x00,streamFile) != 0x165) return;
|
||||||
|
|
||||||
|
num_streams = read_16bit(chunk_offset+0x08,streamFile);
|
||||||
|
if(loop_flag) *loop_flag = (uint8_t)read_8bit(chunk_offset+0xA,streamFile) > 0;
|
||||||
|
|
||||||
|
/* sample rate and loop bit offsets are defined per stream, but the first is enough */
|
||||||
|
if(sample_rate) *sample_rate = read_32bit(chunk_offset+0x10,streamFile);
|
||||||
|
if(loop_start_b) *loop_start_b = read_32bit(chunk_offset+0x14,streamFile);
|
||||||
|
if(loop_end_b) *loop_end_b = read_32bit(chunk_offset+0x18,streamFile);
|
||||||
|
if(loop_subframe) *loop_subframe = (uint8_t)read_8bit(chunk_offset+0x1C,streamFile);
|
||||||
|
|
||||||
|
/* channels is the sum of all streams */
|
||||||
|
for (i = 0; i < num_streams; i++) {
|
||||||
|
total_channels += read_8bit(chunk_offset+0x0C+0x11+i*0x10,streamFile);
|
||||||
|
}
|
||||||
|
if(channels) *channels = total_channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read values from a 'new' XMA2 RIFF "fmt" chunk (XMA2WAVEFORMATEX), starting from an offset *after* chunk type+size.
|
||||||
|
* Useful as custom X360 headers commonly have it lurking inside. Only the extra data, the first part is a normal WAVEFORMATEX. */
|
||||||
|
void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample, int be) {
|
||||||
|
int16_t (*read_16bit)(off_t,STREAMFILE*) = be ? read_16bitBE : read_16bitLE;
|
||||||
|
int32_t (*read_32bit)(off_t,STREAMFILE*) = be ? read_32bitBE : read_32bitLE;
|
||||||
|
|
||||||
|
if (read_16bit(chunk_offset+0x00,streamFile) != 0x166) return;
|
||||||
|
/* up to extra data is a WAVEFORMATEX */
|
||||||
|
if (read_16bit(chunk_offset+0x10,streamFile) < 0x22) return; /* expected extra data size */
|
||||||
|
|
||||||
|
if(num_samples) *num_samples = read_32bit(chunk_offset+0x18,streamFile);
|
||||||
|
if(loop_start_sample) *loop_start_sample = read_32bit(chunk_offset+0x28,streamFile);
|
||||||
|
if(loop_end_sample) *loop_end_sample = read_32bit(chunk_offset+0x28,streamFile) + read_32bit(chunk_offset+0x2C,streamFile);
|
||||||
|
if(loop_flag) *loop_flag = (uint8_t)read_8bit(chunk_offset+0x30,streamFile) > 0 /* never set in practice */
|
||||||
|
|| read_32bit(chunk_offset+0x2C,streamFile); /*loop_end_sample*/
|
||||||
|
/* play_begin+end = probably pcm_samples (for original sample rate), don't seem to affect anything */
|
||||||
|
/* int32_t play_begin_sample = read_32bit(xma->chunk_offset+0x20,streamFile); */
|
||||||
|
/* int32_t play_end_sample = play_begin_sample + read_32bit(xma->chunk_offset+0x24,streamFile); */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read values from an 'old' XMA2 RIFF "XMA2" chunk (XMA2WAVEFORMAT), starting from an offset *after* chunk type+size.
|
||||||
|
* Useful as custom X360 headers commonly have it lurking inside. */
|
||||||
|
void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample) {
|
||||||
|
int32_t (*read_32bit)(off_t,STREAMFILE*) = read_32bitBE; /* XMA2WAVEFORMAT is always big endian */
|
||||||
|
int i, xma2_chunk_version, num_streams, total_channels = 0;
|
||||||
|
off_t off;
|
||||||
|
|
||||||
|
xma2_chunk_version = read_8bit(chunk_offset+0x00,streamFile);
|
||||||
|
num_streams = read_8bit(chunk_offset+0x01,streamFile);
|
||||||
|
if(loop_start_sample) *loop_start_sample = read_32bit(chunk_offset+0x04,streamFile);
|
||||||
|
if(loop_end_sample) *loop_end_sample = read_32bit(chunk_offset+0x08,streamFile);
|
||||||
|
if(loop_flag) *loop_flag = (uint8_t)read_8bit(chunk_offset+0x03,streamFile) > 0 /* rarely not set, encoder default */
|
||||||
|
|| read_32bit(chunk_offset+0x08,streamFile); /* loop_end_sample */
|
||||||
|
if(sample_rate) *sample_rate = read_32bit(chunk_offset+0x0c,streamFile);;
|
||||||
|
|
||||||
|
off = xma2_chunk_version == 3 ? 0x14 : 0x1C;
|
||||||
|
if(num_samples) *num_samples = read_32bit(chunk_offset+off,streamFile);
|
||||||
|
/*xma->pcm_samples = read_32bitBE(xma->chunk_offset+off+0x04,streamFile)*/
|
||||||
|
/* num_samples is the max samples in the file (apparently not including encoder delay) */
|
||||||
|
/* pcm_samples are original WAV's; not current since samples and sample rate may be adjusted for looping purposes */
|
||||||
|
|
||||||
|
off = xma2_chunk_version == 3 ? 0x20 : 0x28;
|
||||||
|
/* channels is the sum of all streams */
|
||||||
|
for (i = 0; i < num_streams; i++) {
|
||||||
|
total_channels += read_8bit(chunk_offset+off+i*0x04,streamFile);
|
||||||
|
}
|
||||||
|
if (channels) *channels = total_channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ******************************************** */
|
||||||
|
/* OTHER STUFF */
|
||||||
|
/* ******************************************** */
|
||||||
|
|
||||||
|
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align) {
|
||||||
|
/* ATRAC3 expects full block align since as is can mix joint stereo with mono blocks;
|
||||||
|
* so (full_block_align / channels) DOESN'T give the size of a single channel (uncommon in ATRAC3 though) */
|
||||||
|
return (bytes / full_block_align) * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) {
|
||||||
|
/* ATRAC3plus expects full block align since as is can mix joint stereo with mono blocks;
|
||||||
|
* so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */
|
||||||
|
return (bytes / full_block_align) * 2048;
|
||||||
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
#include "coding.h"
|
#include "coding.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
#include <vorbis/codec.h>
|
#include <vorbis/codec.h>
|
||||||
|
|
||||||
#define FSB_VORBIS_ON 1 //todo remove once battle-tested
|
|
||||||
#define FSB_VORBIS_USE_PRECOMPILED_FVS 1 /* if enabled vgmstream weights ~600kb more but doesn't need external .fvs packets */
|
#define FSB_VORBIS_USE_PRECOMPILED_FVS 1 /* if enabled vgmstream weights ~600kb more but doesn't need external .fvs packets */
|
||||||
|
|
||||||
#if FSB_VORBIS_ON
|
|
||||||
#if FSB_VORBIS_USE_PRECOMPILED_FVS
|
#if FSB_VORBIS_USE_PRECOMPILED_FVS
|
||||||
#include "fsb_vorbis_data.h"
|
#include "fsb_vorbis_data.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,7 +20,6 @@ static int vorbis_make_header_setup(uint8_t * buf, size_t bufsize, uint32_t setu
|
||||||
static int load_fvs_file_single(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
static int load_fvs_file_single(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
||||||
static int load_fvs_file_multi(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
static int load_fvs_file_multi(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
||||||
static int load_fvs_array(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
static int load_fvs_array(uint8_t * buf, size_t bufsize, uint32_t setup_id, STREAMFILE *streamFile);
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inits a raw FSB vorbis stream.
|
* Inits a raw FSB vorbis stream.
|
||||||
|
@ -37,7 +35,6 @@ static int load_fvs_array(uint8_t * buf, size_t bufsize, uint32_t setup_id, STRE
|
||||||
* Also from the official docs (https://www.xiph.org/vorbis/doc/libvorbis/overview.html).
|
* Also from the official docs (https://www.xiph.org/vorbis/doc/libvorbis/overview.html).
|
||||||
*/
|
*/
|
||||||
vorbis_codec_data * init_fsb_vorbis_codec_data(STREAMFILE *streamfile, off_t start_offset, int channels, int sample_rate, uint32_t setup_id) {
|
vorbis_codec_data * init_fsb_vorbis_codec_data(STREAMFILE *streamfile, off_t start_offset, int channels, int sample_rate, uint32_t setup_id) {
|
||||||
#if FSB_VORBIS_ON
|
|
||||||
vorbis_codec_data * data = NULL;
|
vorbis_codec_data * data = NULL;
|
||||||
|
|
||||||
/* init stuff */
|
/* init stuff */
|
||||||
|
@ -80,7 +77,6 @@ vorbis_codec_data * init_fsb_vorbis_codec_data(STREAMFILE *streamfile, off_t sta
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
free_fsb_vorbis(data);
|
free_fsb_vorbis(data);
|
||||||
#endif
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +84,6 @@ fail:
|
||||||
* Decodes raw FSB vorbis
|
* Decodes raw FSB vorbis
|
||||||
*/
|
*/
|
||||||
void decode_fsb_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels) {
|
void decode_fsb_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels) {
|
||||||
#if FSB_VORBIS_ON
|
|
||||||
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
|
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
|
||||||
vorbis_codec_data * data = vgmstream->codec_data;
|
vorbis_codec_data * data = vgmstream->codec_data;
|
||||||
size_t stream_size = get_streamfile_size(stream->streamfile);
|
size_t stream_size = get_streamfile_size(stream->streamfile);
|
||||||
|
@ -177,10 +172,8 @@ void decode_fsb_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_t
|
||||||
decode_fail:
|
decode_fail:
|
||||||
/* on error just put some 0 samples */
|
/* on error just put some 0 samples */
|
||||||
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FSB_VORBIS_ON
|
|
||||||
|
|
||||||
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm) {
|
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm) {
|
||||||
/* mostly from Xiph's decoder_example.c */
|
/* mostly from Xiph's decoder_example.c */
|
||||||
|
@ -391,12 +384,9 @@ fail:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ********************************************** */
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void free_fsb_vorbis(vorbis_codec_data * data) {
|
void free_fsb_vorbis(vorbis_codec_data * data) {
|
||||||
#if FSB_VORBIS_ON
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -407,23 +397,26 @@ void free_fsb_vorbis(vorbis_codec_data * data) {
|
||||||
|
|
||||||
free(data->buffer);
|
free(data->buffer);
|
||||||
free(data);
|
free(data);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_fsb_vorbis(VGMSTREAM *vgmstream) {
|
void reset_fsb_vorbis(VGMSTREAM *vgmstream) {
|
||||||
seek_fsb_vorbis(vgmstream, 0);
|
vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
|
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||||
|
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||||
|
vorbis_synthesis_restart(&data->vd);
|
||||||
|
data->samples_to_discard = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void seek_fsb_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
void seek_fsb_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||||
#if FSB_VORBIS_ON
|
|
||||||
vorbis_codec_data *data = vgmstream->codec_data;
|
vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||||
* To avoid having to parse different formats we'll just discard until the expected sample */
|
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||||
vorbis_synthesis_restart(&data->vd);
|
vorbis_synthesis_restart(&data->vd);
|
||||||
data->samples_to_discard = num_sample;
|
data->samples_to_discard = num_sample;
|
||||||
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset;
|
if (vgmstream->loop_ch)
|
||||||
#endif
|
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -604,3 +604,57 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
|
||||||
stream->adpcm_history1_32 = hist1;
|
stream->adpcm_history1_32 = hist1;
|
||||||
stream->adpcm_step_index = step_index;
|
stream->adpcm_step_index = step_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||||
|
int i, sample_count = 0;
|
||||||
|
|
||||||
|
int32_t hist1 = stream->adpcm_history1_32;
|
||||||
|
int step_index = stream->adpcm_step_index;
|
||||||
|
|
||||||
|
//internal interleave (configurable size), block-interleave multichannel (ex. if block is 0xD8 in 6ch: 6 blocks of 4+0x20)
|
||||||
|
int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels;
|
||||||
|
first_sample = first_sample % block_samples;
|
||||||
|
|
||||||
|
//block-interleaved header (1 header per channel block); can be LE or BE
|
||||||
|
if (first_sample == 0) {
|
||||||
|
int16_t (*read_16bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_16bitBE : read_16bitLE;
|
||||||
|
off_t header_offset = stream->offset + (vgmstream->interleave_block_size / vgmstream->channels)*channel;
|
||||||
|
|
||||||
|
hist1 = read_16bit(header_offset,stream->streamfile);
|
||||||
|
step_index = read_8bit(header_offset+2,stream->streamfile);
|
||||||
|
if (step_index < 0) step_index=0;
|
||||||
|
if (step_index > 88) step_index=88;
|
||||||
|
|
||||||
|
//must write history from header as last nibble/sample in block is almost always 0 / not encoded
|
||||||
|
outbuf[sample_count] = (short)(hist1);
|
||||||
|
sample_count += channelspacing;
|
||||||
|
first_sample += 1;
|
||||||
|
samples_to_do -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=first_sample; i < first_sample + samples_to_do; i++) { /* first_sample + samples_to_do should be block_samples at most */
|
||||||
|
off_t byte_offset = stream->offset + (vgmstream->interleave_block_size / vgmstream->channels)*channel + 4 + (i-1)/2;
|
||||||
|
int nibble_shift = ((i-1)&1?4:0); //low nibble first
|
||||||
|
|
||||||
|
//last nibble/sample in block is ignored (next header sample contains it)
|
||||||
|
if (i < block_samples) {
|
||||||
|
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||||
|
outbuf[sample_count] = (short)(hist1);
|
||||||
|
sample_count+=channelspacing;
|
||||||
|
//todo atenuation: apparently from hcs's analysis Wwise IMA decodes nibbles slightly different, reducing dbs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//internal interleave: increment offset on complete frame
|
||||||
|
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
|
||||||
|
|
||||||
|
stream->adpcm_history1_32 = hist1;
|
||||||
|
stream->adpcm_step_index = step_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) {
|
||||||
|
/* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
|
||||||
|
return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels;
|
||||||
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset
|
||||||
|
|
||||||
rc = mpg123_decode(main_m, data->buffer,data->buffer_size, NULL,0, &bytes_done);
|
rc = mpg123_decode(main_m, data->buffer,data->buffer_size, NULL,0, &bytes_done);
|
||||||
if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT && rc != MPG123_NEED_MORE) {
|
if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT && rc != MPG123_NEED_MORE) {
|
||||||
VGM_LOG("MPEG: unable to set up mpp123 @ 0x%08lx to 0x%08lx\n", start_offset, read_offset);
|
VGM_LOG("MPEG: unable to set up mpg123 @ 0x%08lx to 0x%08lx\n", start_offset, read_offset);
|
||||||
goto fail; //todo handle MPG123_DONE?
|
goto fail; //todo handle MPG123_DONE?
|
||||||
}
|
}
|
||||||
if (read_offset > 0x5000) { /* don't hang in some incorrectly detected formats */
|
if (read_offset > 0x5000) { /* don't hang in some incorrectly detected formats */
|
||||||
|
@ -170,7 +170,12 @@ mpeg_codec_data *init_mpeg_codec_data_interleaved(STREAMFILE *streamfile, off_t
|
||||||
/* get frame size from the first frame as it can be used externally to calc interleave */
|
/* get frame size from the first frame as it can be used externally to calc interleave */
|
||||||
if ( !update_frame_sizes(data, streamfile, start_offset) )
|
if ( !update_frame_sizes(data, streamfile, start_offset) )
|
||||||
goto fail;
|
goto fail;
|
||||||
|
//VGM_LOG("ch=%i, sr=%i, spf=%i, v=%i, l=%i\n", data->channels_per_frame, data->sample_rate_per_frame, data->samples_per_frame, info.version, info.layer);
|
||||||
|
|
||||||
|
//mpg123_handle *main_m = data->m;
|
||||||
|
//struct mpg123_frameinfo mi;
|
||||||
|
//mpg123_info(main_m,&mi);
|
||||||
|
//VGM_LOG("mi.framesize=%x\n", mi.framesize);
|
||||||
/* unlikely, can fixed with bigger buffer or a feed loop */
|
/* unlikely, can fixed with bigger buffer or a feed loop */
|
||||||
if (info.frame_size > data->buffer_size)
|
if (info.frame_size > data->buffer_size)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -404,12 +409,16 @@ static void decode_mpeg_interleave_samples(VGMSTREAMCHANNEL *stream, mpeg_codec_
|
||||||
/* decode samples from 1 full frame */
|
/* decode samples from 1 full frame */
|
||||||
do {
|
do {
|
||||||
int rc;
|
int rc;
|
||||||
|
//int first_frame = stream->offset == stream->channel_start_offset;
|
||||||
|
|
||||||
/* padded frame stuff */
|
/* padded frame stuff */
|
||||||
rc = update_frame_sizes(data, stream->streamfile, stream->offset);
|
rc = update_frame_sizes(data, stream->streamfile, stream->offset);
|
||||||
/* ignore any errors and continue; mpg123 will probably sync */
|
/* ignore any errors and continue; mpg123 will probably sync */
|
||||||
VGM_ASSERT(rc==0, "MPEG: frame error @ 0x%08lx (prev size=0x%x / padding=0x%x)\n", stream->offset, data->current_frame_size, data->current_padding);
|
VGM_ASSERT(rc==0, "MPEG: frame error @ 0x%08lx (prev size=0x%x / padding=0x%x)\n", stream->offset, data->current_frame_size, data->current_padding);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* extra EOF check for edge cases when the caller tries to read more samples than possible */
|
/* extra EOF check for edge cases when the caller tries to read more samples than possible */
|
||||||
if (stream->offset > stream_size) {
|
if (stream->offset > stream_size) {
|
||||||
memset(data->frame_buffer, 0, data->frame_buffer_size);
|
memset(data->frame_buffer, 0, data->frame_buffer_size);
|
||||||
|
@ -421,6 +430,7 @@ static void decode_mpeg_interleave_samples(VGMSTREAMCHANNEL *stream, mpeg_codec_
|
||||||
/* read more raw data (only 1 frame, to check interleave block end) */
|
/* read more raw data (only 1 frame, to check interleave block end) */
|
||||||
if (!data->buffer_full) {
|
if (!data->buffer_full) {
|
||||||
data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset,data->current_frame_size,stream->streamfile);
|
data->bytes_in_buffer = read_streamfile(data->buffer,stream->offset,data->current_frame_size,stream->streamfile);
|
||||||
|
//VGM_LOG("read raw: cfs=%x, cp=%x, tot=%x, off=%x\n", data->current_frame_size, data->current_padding, data->current_frame_size + data->current_padding, stream->offset);
|
||||||
|
|
||||||
/* end of stream, fill frame buffer with 0s but continue normally with other streams */
|
/* end of stream, fill frame buffer with 0s but continue normally with other streams */
|
||||||
if (!data->bytes_in_buffer) {
|
if (!data->bytes_in_buffer) {
|
||||||
|
@ -436,16 +446,37 @@ static void decode_mpeg_interleave_samples(VGMSTREAMCHANNEL *stream, mpeg_codec_
|
||||||
if (block_size && ((stream->offset - stream->channel_start_offset) % block_size==0)) {
|
if (block_size && ((stream->offset - stream->channel_start_offset) % block_size==0)) {
|
||||||
stream->offset += block_size * (data->ms_size-1); /* skip a block per stream if block done */
|
stream->offset += block_size * (data->ms_size-1); /* skip a block per stream if block done */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
/// TODO: skip very first frame but add fake silence?
|
||||||
|
//todo skip only if first frame is fully decodable? (ie.- blank below)
|
||||||
|
//todo for multich files idem
|
||||||
|
if (first_frame) {
|
||||||
|
data->buffer_full = 0;
|
||||||
|
|
||||||
|
VGM_LOG("skip first frame @ %x - %x\n", stream->offset, stream->channel_start_offset);
|
||||||
|
memset(data->frame_buffer, 0, data->frame_buffer_size);
|
||||||
|
bytes_done = data->frame_buffer_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* feed new raw data to the decoder if needed, copy decoded results to frame buffer output */
|
/* feed new raw data to the decoder if needed, copy decoded results to frame buffer output */
|
||||||
if (!data->buffer_used) {
|
if (!data->buffer_used) {
|
||||||
|
//VGM_LOG("feed unused: cfs=%x, cp=%x, tot=%x, off=%x\n", data->current_frame_size, data->current_padding, data->current_frame_size + data->current_padding, stream->offset);
|
||||||
|
//getchar();
|
||||||
|
|
||||||
rc = mpg123_decode(m,
|
rc = mpg123_decode(m,
|
||||||
data->buffer, data->bytes_in_buffer,
|
data->buffer, data->bytes_in_buffer,
|
||||||
(unsigned char *)data->frame_buffer, data->frame_buffer_size,
|
(unsigned char *)data->frame_buffer, data->frame_buffer_size,
|
||||||
&bytes_done);
|
&bytes_done);
|
||||||
data->buffer_used = 1;
|
data->buffer_used = 1;
|
||||||
} else {
|
} else {
|
||||||
|
//VGM_LOG("feed used: cfs=%x, cp=%x, tot=%x, off=%x\n", data->current_frame_size, data->current_padding, data->current_frame_size + data->current_padding, stream->offset);
|
||||||
|
//getchar();
|
||||||
|
|
||||||
rc = mpg123_decode(m,
|
rc = mpg123_decode(m,
|
||||||
NULL,0,
|
NULL,0,
|
||||||
(unsigned char *)data->frame_buffer, data->frame_buffer_size,
|
(unsigned char *)data->frame_buffer, data->frame_buffer_size,
|
||||||
|
@ -515,6 +546,9 @@ static int update_frame_sizes(mpeg_codec_data * data, STREAMFILE *streamfile, of
|
||||||
data->current_padding = (data->current_frame_size % data->fsb_padding) ?
|
data->current_padding = (data->current_frame_size % data->fsb_padding) ?
|
||||||
data->fsb_padding - (data->current_frame_size % data->fsb_padding) : 0;
|
data->fsb_padding - (data->current_frame_size % data->fsb_padding) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//VGM_LOG("off=%lx, ch=%i, sr=%i, spf=%i, fs=%x, v=%i, l=%i\n", offset, info.channels, info.sample_rate, info.frame_samples, info.frame_size, info.version, info.layer);
|
||||||
|
//getchar();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -649,7 +683,6 @@ void reset_mpeg(VGMSTREAM *vgmstream) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i < data->ms_size; i++) {
|
for (i=0; i < data->ms_size; i++) {
|
||||||
mpg123_feedseek(data->ms[i],0,SEEK_SET,&input_offset);
|
mpg123_feedseek(data->ms[i],0,SEEK_SET,&input_offset);
|
||||||
vgmstream->loop_ch[i].offset = vgmstream->loop_ch[i].channel_start_offset + input_offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data->bytes_in_interleave_buffer = 0;
|
data->bytes_in_interleave_buffer = 0;
|
||||||
|
@ -665,13 +698,15 @@ void seek_mpeg(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||||
/* seek multistream */
|
/* seek multistream */
|
||||||
if (!data->interleaved) {
|
if (!data->interleaved) {
|
||||||
mpg123_feedseek(data->m, num_sample,SEEK_SET,&input_offset);
|
mpg123_feedseek(data->m, num_sample,SEEK_SET,&input_offset);
|
||||||
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset + input_offset;
|
if (vgmstream->loop_ch)
|
||||||
|
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset + input_offset;
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
/* re-start from 0 */
|
/* re-start from 0 */
|
||||||
for (i=0; i < data->ms_size; i++) {
|
for (i=0; i < data->ms_size; i++) {
|
||||||
mpg123_feedseek(data->ms[i],0,SEEK_SET,&input_offset);
|
mpg123_feedseek(data->ms[i],0,SEEK_SET,&input_offset);
|
||||||
vgmstream->loop_ch[i].offset = vgmstream->loop_ch[i].channel_start_offset;
|
if (vgmstream->loop_ch)
|
||||||
|
vgmstream->loop_ch[i].offset = vgmstream->loop_ch[i].channel_start_offset;
|
||||||
}
|
}
|
||||||
/* manually add skip samples, since we don't really know the correct offset */
|
/* manually add skip samples, since we don't really know the correct offset */
|
||||||
data->samples_to_discard = num_sample;
|
data->samples_to_discard = num_sample;
|
||||||
|
@ -793,6 +828,9 @@ static int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_
|
||||||
case 576: info->frame_size = (72l * info->bit_rate * 1000l / info->sample_rate + padding); break;
|
case 576: info->frame_size = (72l * info->bit_rate * 1000l / info->sample_rate + padding); break;
|
||||||
case 1152: info->frame_size = (144l * info->bit_rate * 1000l / info->sample_rate + padding); break;
|
case 1152: info->frame_size = (144l * info->bit_rate * 1000l / info->sample_rate + padding); break;
|
||||||
}
|
}
|
||||||
|
//int fs2 = (info->frame_samples / 8 * info->bit_rate * 1000l) / info->sample_rate + padding;
|
||||||
|
//VGM_LOG("fs=%x, fs2=%x, fsp=%i, br=%i\n", info->frame_size, fs2, info->frame_samples, info->bit_rate);
|
||||||
|
//getchar();
|
||||||
|
|
||||||
info->coding_type = coding_types[info->version-1][info->layer-1];
|
info->coding_type = coding_types[info->version-1][info->layer-1];
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,10 @@ int32_t dsp_nibbles_to_samples(int32_t nibbles) {
|
||||||
else return whole_frames*14;
|
else return whole_frames*14;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t dsp_bytes_to_samples(size_t bytes, int channels) {
|
||||||
|
return bytes / channels / 8 * 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reads DSP coefs built in the streamfile
|
* reads DSP coefs built in the streamfile
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
#include "coding.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef VGM_USE_VORBIS
|
||||||
|
#include <vorbis/codec.h>
|
||||||
|
|
||||||
|
#define ogl_vorbis_DEFAULT_BUFFER_SIZE 0x8000 /* should be at least the size of the setup header, ~0x2000 */
|
||||||
|
|
||||||
|
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inits a raw OGL vorbis stream.
|
||||||
|
*
|
||||||
|
* Vorbis packets are stored in .ogg, which is divided into ogg pages/packets, and the first packets contain necessary
|
||||||
|
* vorbis setup. For raw vorbis the setup is stored it elsewhere (i.e.- in the .exe), presumably to shave off some kb
|
||||||
|
* per stream and codec startup time. We'll read the external setup and raw data and decode it with libvorbis.
|
||||||
|
*
|
||||||
|
* OGL simply removes the Ogg layer and uses 16b packet headers, that have the size of the next packet, but
|
||||||
|
* the lower 2b need to be removed (usually 00 but 01 for the id packet, not sure about the meaning).
|
||||||
|
*/
|
||||||
|
vorbis_codec_data * init_ogl_vorbis_codec_data(STREAMFILE *streamFile, off_t start_offset, off_t * data_start_offset) {
|
||||||
|
vorbis_codec_data * data = NULL;
|
||||||
|
|
||||||
|
/* init stuff */
|
||||||
|
data = calloc(1,sizeof(vorbis_codec_data));
|
||||||
|
if (!data) goto fail;
|
||||||
|
|
||||||
|
data->buffer_size = ogl_vorbis_DEFAULT_BUFFER_SIZE;
|
||||||
|
data->buffer = calloc(sizeof(uint8_t), data->buffer_size);
|
||||||
|
if (!data->buffer) goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
/* init vorbis stream state, using 3 fake Ogg setup packets (info, comments, setup/codebooks)
|
||||||
|
* libvorbis expects parsed Ogg pages, but we'll fake them with our raw data instead */
|
||||||
|
vorbis_info_init(&data->vi);
|
||||||
|
vorbis_comment_init(&data->vc);
|
||||||
|
|
||||||
|
data->op.packet = data->buffer;
|
||||||
|
data->op.b_o_s = 1; /* fake headers start */
|
||||||
|
|
||||||
|
{
|
||||||
|
/* read 3 packets with triad (id/comment/setup), each with an OGL header */
|
||||||
|
off_t offset = start_offset;
|
||||||
|
size_t packet_size;
|
||||||
|
|
||||||
|
/* normal identificacion packet */
|
||||||
|
packet_size = (uint16_t)read_16bitLE(offset, streamFile) >> 2;
|
||||||
|
if (packet_size > data->buffer_size) goto fail;
|
||||||
|
data->op.bytes = read_streamfile(data->buffer,offset+2,packet_size, streamFile);
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||||
|
offset += 2+packet_size;
|
||||||
|
|
||||||
|
/* normal comment packet */
|
||||||
|
packet_size = (uint16_t)read_16bitLE(offset, streamFile) >> 2;
|
||||||
|
if (packet_size > data->buffer_size) goto fail;
|
||||||
|
data->op.bytes = read_streamfile(data->buffer,offset+2,packet_size, streamFile);
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||||
|
offset += 2+packet_size;
|
||||||
|
|
||||||
|
/* normal setup packet */
|
||||||
|
packet_size = (uint16_t)read_16bitLE(offset, streamFile) >> 2;
|
||||||
|
if (packet_size > data->buffer_size) goto fail;
|
||||||
|
data->op.bytes = read_streamfile(data->buffer,offset+2,packet_size, streamFile);
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||||
|
offset += 2+packet_size;
|
||||||
|
|
||||||
|
/* data starts after triad */
|
||||||
|
*data_start_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->op.b_o_s = 0; /* end of fake headers */
|
||||||
|
|
||||||
|
/* init vorbis global and block state */
|
||||||
|
if (vorbis_synthesis_init(&data->vd,&data->vi) != 0) goto fail;
|
||||||
|
if (vorbis_block_init(&data->vd,&data->vb) != 0) goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
return data;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free_ogl_vorbis(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes raw OGL vorbis
|
||||||
|
*/
|
||||||
|
void decode_ogl_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels) {
|
||||||
|
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
|
||||||
|
vorbis_codec_data * data = vgmstream->codec_data;
|
||||||
|
size_t stream_size = get_streamfile_size(stream->streamfile);
|
||||||
|
//data->op.packet = data->buffer;/* implicit from init */
|
||||||
|
int samples_done = 0;
|
||||||
|
|
||||||
|
while (samples_done < samples_to_do) {
|
||||||
|
|
||||||
|
/* extra EOF check for edge cases */
|
||||||
|
if (stream->offset > stream_size) {
|
||||||
|
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (data->samples_full) { /* read more samples */
|
||||||
|
int samples_to_get;
|
||||||
|
float **pcm;
|
||||||
|
|
||||||
|
/* get PCM samples from libvorbis buffers */
|
||||||
|
samples_to_get = vorbis_synthesis_pcmout(&data->vd, &pcm);
|
||||||
|
if (!samples_to_get) {
|
||||||
|
data->samples_full = 0; /* request more if empty*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->samples_to_discard) {
|
||||||
|
/* discard samples for looping */
|
||||||
|
if (samples_to_get > data->samples_to_discard)
|
||||||
|
samples_to_get = data->samples_to_discard;
|
||||||
|
data->samples_to_discard -= samples_to_get;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* get max samples and convert from Vorbis float pcm to 16bit pcm */
|
||||||
|
if (samples_to_get > samples_to_do - samples_done)
|
||||||
|
samples_to_get = samples_to_do - samples_done;
|
||||||
|
pcm_convert_float_to_16(data, outbuf + samples_done * channels, samples_to_get, pcm);
|
||||||
|
samples_done += samples_to_get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark consumed samples from the buffer
|
||||||
|
* (non-consumed samples are returned in next vorbis_synthesis_pcmout calls) */
|
||||||
|
vorbis_synthesis_read(&data->vd, samples_to_get);
|
||||||
|
}
|
||||||
|
else { /* read more data */
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* this is not actually needed, but feels nicer */
|
||||||
|
data->op.granulepos += samples_to_do;
|
||||||
|
data->op.packetno++;
|
||||||
|
|
||||||
|
/* get next packet size from the OGL 16b header */
|
||||||
|
data->op.bytes = (uint16_t)read_16bitLE(stream->offset, stream->streamfile) >> 2;
|
||||||
|
stream->offset += 2;
|
||||||
|
if (data->op.bytes == 0 || data->op.bytes == 0xFFFF) {
|
||||||
|
goto decode_fail; /* eof or end padding */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read raw block */
|
||||||
|
if (read_streamfile(data->buffer,stream->offset, data->op.bytes,stream->streamfile) != data->op.bytes) {
|
||||||
|
goto decode_fail; /* wrong packet? */
|
||||||
|
}
|
||||||
|
stream->offset += data->op.bytes;
|
||||||
|
|
||||||
|
/* parse the fake ogg packet into a logical vorbis block */
|
||||||
|
rc = vorbis_synthesis(&data->vb,&data->op);
|
||||||
|
if (rc == OV_ENOTAUDIO) {
|
||||||
|
VGM_LOG("vorbis_synthesis: not audio packet @ %lx\n",stream->offset); getchar();
|
||||||
|
continue; /* not tested */
|
||||||
|
} else if (rc != 0) {
|
||||||
|
goto decode_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* finally decode the logical block into samples */
|
||||||
|
rc = vorbis_synthesis_blockin(&data->vd,&data->vb);
|
||||||
|
if (rc != 0) {
|
||||||
|
goto decode_fail; /* ? */
|
||||||
|
}
|
||||||
|
|
||||||
|
data->samples_full = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
decode_fail:
|
||||||
|
/* on error just put some 0 samples */
|
||||||
|
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm) {
|
||||||
|
/* mostly from Xiph's decoder_example.c */
|
||||||
|
int i,j;
|
||||||
|
|
||||||
|
/* convert float PCM (multichannel float array, with pcm[0]=ch0, pcm[1]=ch1, pcm[2]=ch0, etc)
|
||||||
|
* to 16 bit signed PCM ints (host order) and interleave + fix clipping */
|
||||||
|
for (i = 0; i < data->vi.channels; i++) {
|
||||||
|
sample *ptr = outbuf + i;
|
||||||
|
float *mono = pcm[i];
|
||||||
|
for (j = 0; j < samples_to_do; j++) {
|
||||||
|
int val = floor(mono[j] * 32767.f + .5f);
|
||||||
|
if (val > 32767) val = 32767;
|
||||||
|
if (val < -32768) val = -32768;
|
||||||
|
|
||||||
|
*ptr = val;
|
||||||
|
ptr += data->vi.channels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ********************************************** */
|
||||||
|
|
||||||
|
void free_ogl_vorbis(vorbis_codec_data * data) {
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* internal decoder cleanp */
|
||||||
|
vorbis_info_clear(&data->vi);
|
||||||
|
vorbis_comment_clear(&data->vc);
|
||||||
|
vorbis_dsp_clear(&data->vd);
|
||||||
|
|
||||||
|
free(data->buffer);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_ogl_vorbis(VGMSTREAM *vgmstream) {
|
||||||
|
vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
|
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||||
|
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||||
|
vorbis_synthesis_restart(&data->vd);
|
||||||
|
data->samples_to_discard = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void seek_ogl_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||||
|
vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
|
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||||
|
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||||
|
vorbis_synthesis_restart(&data->vd);
|
||||||
|
data->samples_to_discard = num_sample;
|
||||||
|
if (vgmstream->loop_ch)
|
||||||
|
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -85,3 +85,7 @@ void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int chan
|
||||||
outbuf[sample_count]=read_16bitLE(stream->offset+i*2*channelspacing,stream->streamfile)^stream->key_xor;
|
outbuf[sample_count]=read_16bitLE(stream->offset+i*2*channelspacing,stream->streamfile)^stream->key_xor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) {
|
||||||
|
return bytes / channels / (bits_per_sample/8);
|
||||||
|
}
|
||||||
|
|
|
@ -432,3 +432,8 @@ void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample * outbuf, int cha
|
||||||
stream->adpcm_history1_32 = hist1;
|
stream->adpcm_history1_32 = hist1;
|
||||||
stream->adpcm_history2_32 = hist2;
|
stream->adpcm_history2_32 = hist2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t ps_bytes_to_samples(size_t bytes, int channels) {
|
||||||
|
return bytes / channels / 16 * 28;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,305 @@
|
||||||
|
#include "coding.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifdef VGM_USE_VORBIS
|
||||||
|
#include <vorbis/codec.h>
|
||||||
|
|
||||||
|
#include "wwise_vorbis_utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define WWISE_VORBIS_DEFAULT_BUFFER_SIZE 0x8000 /* should be at least the size of the setup header, ~0x2000 */
|
||||||
|
|
||||||
|
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm);
|
||||||
|
static int vorbis_make_header_identification(uint8_t * buf, size_t bufsize, int channels, int sample_rate, int blocksize_short, int blocksize_long);
|
||||||
|
static int vorbis_make_header_comment(uint8_t * buf, size_t bufsize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inits a raw Wwise vorbis stream.
|
||||||
|
*
|
||||||
|
* Vorbis packets are stored in .ogg, which is divided into ogg pages/packets, and the first packets contain necessary
|
||||||
|
* vorbis setup. For raw vorbis the setup is stored it elsewhere (i.e.- in the .exe), presumably to shave off some kb
|
||||||
|
* per stream and codec startup time. We'll read the external setup and raw data and decode it with libvorbis.
|
||||||
|
*
|
||||||
|
* Wwise stores a reduced setup, and the raw vorbis packets have mini headers with the block size,
|
||||||
|
* and vorbis packets themselves may reduced as well. The format evolved over time so there are some variations.
|
||||||
|
* The Wwise implementation uses Tremor (fixed-point Vorbis) but shouldn't matter.
|
||||||
|
*
|
||||||
|
* Format reverse engineered by hcs in ww2ogg (https://github.com/hcs64/ww2ogg).
|
||||||
|
* Info from the official docs (https://www.xiph.org/vorbis/doc/libvorbis/overview.html).
|
||||||
|
*/
|
||||||
|
vorbis_codec_data * init_wwise_vorbis_codec_data(STREAMFILE *streamFile, off_t start_offset, int channels, int sample_rate, int blocksize_0_exp, int blocksize_1_exp,
|
||||||
|
wwise_setup_type setup_type, wwise_header_type header_type, wwise_packet_type packet_type, int big_endian) {
|
||||||
|
vorbis_codec_data * data = NULL;
|
||||||
|
size_t header_size, packet_size;
|
||||||
|
|
||||||
|
/* init stuff */
|
||||||
|
data = calloc(1,sizeof(vorbis_codec_data));
|
||||||
|
if (!data) goto fail;
|
||||||
|
|
||||||
|
data->buffer_size = WWISE_VORBIS_DEFAULT_BUFFER_SIZE;
|
||||||
|
data->buffer = calloc(sizeof(uint8_t), data->buffer_size);
|
||||||
|
if (!data->buffer) goto fail;
|
||||||
|
|
||||||
|
data->setup_type = setup_type;
|
||||||
|
data->header_type = header_type;
|
||||||
|
data->packet_type = packet_type;
|
||||||
|
|
||||||
|
/* init vorbis stream state, using 3 fake Ogg setup packets (info, comments, setup/codebooks)
|
||||||
|
* libvorbis expects parsed Ogg pages, but we'll fake them with our raw data instead */
|
||||||
|
vorbis_info_init(&data->vi);
|
||||||
|
vorbis_comment_init(&data->vc);
|
||||||
|
|
||||||
|
data->op.packet = data->buffer;
|
||||||
|
data->op.b_o_s = 1; /* fake headers start */
|
||||||
|
|
||||||
|
if (setup_type == HEADER_TRIAD) {
|
||||||
|
/* read 3 Wwise packets with triad (id/comment/setup), each with a Wwise header */
|
||||||
|
off_t offset = start_offset;
|
||||||
|
|
||||||
|
/* normal identificacion packet */
|
||||||
|
header_size = wwise_vorbis_get_header(streamFile, offset, data->header_type, (int*)&data->op.granulepos, &packet_size, big_endian);
|
||||||
|
if (!header_size || packet_size > data->buffer_size) goto fail;
|
||||||
|
data->op.bytes = read_streamfile(data->buffer,offset+header_size,packet_size, streamFile);
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||||
|
offset += header_size + packet_size;
|
||||||
|
|
||||||
|
/* normal comment packet */
|
||||||
|
header_size = wwise_vorbis_get_header(streamFile, offset, data->header_type, (int*)&data->op.granulepos, &packet_size, big_endian);
|
||||||
|
if (!header_size || packet_size > data->buffer_size) goto fail;
|
||||||
|
data->op.bytes = read_streamfile(data->buffer,offset+header_size,packet_size, streamFile);
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||||
|
offset += header_size + packet_size;
|
||||||
|
|
||||||
|
/* normal setup packet */
|
||||||
|
header_size = wwise_vorbis_get_header(streamFile, offset, data->header_type, (int*)&data->op.granulepos, &packet_size, big_endian);
|
||||||
|
if (!header_size || packet_size > data->buffer_size) goto fail;
|
||||||
|
data->op.bytes = read_streamfile(data->buffer,offset+header_size,packet_size, streamFile);
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||||
|
offset += header_size + packet_size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* rebuild headers */
|
||||||
|
|
||||||
|
/* new identificacion packet */
|
||||||
|
data->op.bytes = vorbis_make_header_identification(data->buffer, data->buffer_size, channels, sample_rate, blocksize_0_exp, blocksize_1_exp);
|
||||||
|
if (!data->op.bytes) goto fail;
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||||
|
|
||||||
|
/* new comment packet */
|
||||||
|
data->op.bytes = vorbis_make_header_comment(data->buffer, data->buffer_size);
|
||||||
|
if (!data->op.bytes) goto fail;
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||||
|
|
||||||
|
/* rebuild setup packet */
|
||||||
|
data->op.bytes = wwise_vorbis_rebuild_setup(data->buffer, data->buffer_size, streamFile, start_offset, data, big_endian, channels);
|
||||||
|
if (!data->op.bytes) goto fail;
|
||||||
|
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||||
|
}
|
||||||
|
|
||||||
|
data->op.b_o_s = 0; /* end of fake headers */
|
||||||
|
|
||||||
|
/* init vorbis global and block state */
|
||||||
|
if (vorbis_synthesis_init(&data->vd,&data->vi) != 0) goto fail;
|
||||||
|
if (vorbis_block_init(&data->vd,&data->vb) != 0) goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return data;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free_wwise_vorbis(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes raw Wwise Vorbis
|
||||||
|
*/
|
||||||
|
void decode_wwise_vorbis(VGMSTREAM * vgmstream, sample * outbuf, int32_t samples_to_do, int channels) {
|
||||||
|
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
|
||||||
|
vorbis_codec_data * data = vgmstream->codec_data;
|
||||||
|
size_t stream_size = get_streamfile_size(stream->streamfile);
|
||||||
|
//data->op.packet = data->buffer;/* implicit from init */
|
||||||
|
int samples_done = 0;
|
||||||
|
|
||||||
|
|
||||||
|
while (samples_done < samples_to_do) {
|
||||||
|
|
||||||
|
/* extra EOF check for edge cases */
|
||||||
|
if (stream->offset > stream_size) {
|
||||||
|
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (data->samples_full) { /* read more samples */
|
||||||
|
int samples_to_get;
|
||||||
|
float **pcm;
|
||||||
|
|
||||||
|
/* get PCM samples from libvorbis buffers */
|
||||||
|
samples_to_get = vorbis_synthesis_pcmout(&data->vd, &pcm);
|
||||||
|
if (!samples_to_get) {
|
||||||
|
data->samples_full = 0; /* request more if empty*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->samples_to_discard) {
|
||||||
|
/* discard samples for looping */
|
||||||
|
if (samples_to_get > data->samples_to_discard)
|
||||||
|
samples_to_get = data->samples_to_discard;
|
||||||
|
data->samples_to_discard -= samples_to_get;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* get max samples and convert from Vorbis float pcm to 16bit pcm */
|
||||||
|
if (samples_to_get > samples_to_do - samples_done)
|
||||||
|
samples_to_get = samples_to_do - samples_done;
|
||||||
|
pcm_convert_float_to_16(data, outbuf + samples_done * channels, samples_to_get, pcm);
|
||||||
|
samples_done += samples_to_get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark consumed samples from the buffer
|
||||||
|
* (non-consumed samples are returned in next vorbis_synthesis_pcmout calls) */
|
||||||
|
vorbis_synthesis_read(&data->vd, samples_to_get);
|
||||||
|
}
|
||||||
|
else { /* read more data */
|
||||||
|
int rc;
|
||||||
|
size_t header_size, packet_size;
|
||||||
|
|
||||||
|
data->op.packetno++; /* not actually needed, but feels nicer */
|
||||||
|
|
||||||
|
/* reconstruct a Wwise packet, if needed; final bytes may be bigger than packet_size so we get the header offsets here */
|
||||||
|
header_size = wwise_vorbis_get_header(stream->streamfile, stream->offset, data->header_type, (int*)&data->op.granulepos, &packet_size, vgmstream->codec_endian);
|
||||||
|
if (!header_size || packet_size > data->buffer_size) {
|
||||||
|
VGM_LOG("Wwise Vorbis: wrong packet (0x%x) @ %lx\n", packet_size, stream->offset);
|
||||||
|
goto decode_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->op.bytes = wwise_vorbis_rebuild_packet(data->buffer, data->buffer_size, stream->streamfile,stream->offset, data, vgmstream->codec_endian);
|
||||||
|
stream->offset += header_size + packet_size; /* update first to avoid infinite loops */
|
||||||
|
if (!data->op.bytes || data->op.bytes >= 0xFFFF) {
|
||||||
|
VGM_LOG("Wwise Vorbis: wrong bytes (0x%lx) @ %lx\n", data->op.bytes, stream->offset);
|
||||||
|
goto decode_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse the fake ogg packet into a logical vorbis block */
|
||||||
|
rc = vorbis_synthesis(&data->vb,&data->op);
|
||||||
|
if (rc == OV_ENOTAUDIO) {
|
||||||
|
VGM_LOG("Wwise Vorbis: not audio packet @ %lx\n",stream->offset);
|
||||||
|
continue; /* bad packet parsing */
|
||||||
|
} else if (rc != 0) {
|
||||||
|
VGM_LOG("Wwise Vorbis: cannot parse Vorbis block @ %lx\n",stream->offset);
|
||||||
|
goto decode_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* finally decode the logical block into samples */
|
||||||
|
rc = vorbis_synthesis_blockin(&data->vd,&data->vb);
|
||||||
|
if (rc != 0) {
|
||||||
|
VGM_LOG("Wwise Vorbis: cannot decode Vorbis block @ %lx\n",stream->offset);
|
||||||
|
goto decode_fail; /* ? */
|
||||||
|
}
|
||||||
|
|
||||||
|
data->samples_full = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
decode_fail:
|
||||||
|
/* on error just put some 0 samples */
|
||||||
|
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* *************************************************** */
|
||||||
|
|
||||||
|
static void pcm_convert_float_to_16(vorbis_codec_data * data, sample * outbuf, int samples_to_do, float ** pcm) {
|
||||||
|
/* mostly from Xiph's decoder_example.c */
|
||||||
|
int i,j;
|
||||||
|
|
||||||
|
/* convert float PCM (multichannel float array, with pcm[0]=ch0, pcm[1]=ch1, pcm[2]=ch0, etc)
|
||||||
|
* to 16 bit signed PCM ints (host order) and interleave + fix clipping */
|
||||||
|
for (i = 0; i < data->vi.channels; i++) {
|
||||||
|
sample *ptr = outbuf + i;
|
||||||
|
float *mono = pcm[i];
|
||||||
|
for (j = 0; j < samples_to_do; j++) {
|
||||||
|
int val = floor(mono[j] * 32767.f + .5f);
|
||||||
|
if (val > 32767) val = 32767;
|
||||||
|
if (val < -32768) val = -32768;
|
||||||
|
|
||||||
|
*ptr = val;
|
||||||
|
ptr += data->vi.channels;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vorbis_make_header_identification(uint8_t * buf, size_t bufsize, int channels, int sample_rate, int blocksize_0_exp, int blocksize_1_exp) {
|
||||||
|
int bytes = 0x1e;
|
||||||
|
uint8_t blocksizes;
|
||||||
|
|
||||||
|
if (bytes > bufsize) return 0;
|
||||||
|
|
||||||
|
blocksizes = (blocksize_0_exp << 4) | (blocksize_1_exp);
|
||||||
|
|
||||||
|
put_8bit (buf+0x00, 0x01); /* packet_type (id) */
|
||||||
|
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||||
|
put_32bitLE(buf+0x07, 0x00); /* vorbis_version (fixed) */
|
||||||
|
put_8bit (buf+0x0b, channels); /* audio_channels */
|
||||||
|
put_32bitLE(buf+0x0c, sample_rate); /* audio_sample_rate */
|
||||||
|
put_32bitLE(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */
|
||||||
|
put_32bitLE(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */
|
||||||
|
put_32bitLE(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */
|
||||||
|
put_8bit (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */
|
||||||
|
put_8bit (buf+0x1d, 0x01); /* framing_flag (fixed) */
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vorbis_make_header_comment(uint8_t * buf, size_t bufsize) {
|
||||||
|
int bytes = 0x19;
|
||||||
|
|
||||||
|
if (bytes > bufsize) return 0;
|
||||||
|
|
||||||
|
put_8bit (buf+0x00, 0x03); /* packet_type (comments) */
|
||||||
|
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||||
|
put_32bitLE(buf+0x07, 0x09); /* vendor_length */
|
||||||
|
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
|
||||||
|
put_32bitLE(buf+0x14, 0x00); /* user_comment_list_length */
|
||||||
|
put_8bit (buf+0x18, 0x01); /* framing_flag (fixed) */
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* *************************************** */
|
||||||
|
|
||||||
|
void free_wwise_vorbis(vorbis_codec_data * data) {
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* internal decoder cleanp */
|
||||||
|
vorbis_info_clear(&data->vi);
|
||||||
|
vorbis_comment_clear(&data->vc);
|
||||||
|
vorbis_dsp_clear(&data->vd);
|
||||||
|
|
||||||
|
free(data->buffer);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_wwise_vorbis(VGMSTREAM *vgmstream) {
|
||||||
|
vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
|
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||||
|
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||||
|
vorbis_synthesis_restart(&data->vd);
|
||||||
|
data->samples_to_discard = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void seek_wwise_vorbis(VGMSTREAM *vgmstream, int32_t num_sample) {
|
||||||
|
vorbis_codec_data *data = vgmstream->codec_data;
|
||||||
|
|
||||||
|
/* Seeking is provided by the Ogg layer, so with raw vorbis we need seek tables instead.
|
||||||
|
* To avoid having to parse different formats we'll just discard until the expected sample */
|
||||||
|
vorbis_synthesis_restart(&data->vd);
|
||||||
|
data->samples_to_discard = num_sample;
|
||||||
|
if (vgmstream->loop_ch) /* this func is only using for looping though */
|
||||||
|
vgmstream->loop_ch[0].offset = vgmstream->loop_ch[0].channel_start_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef _WWISE_VORBIS_UTILS_H_
|
||||||
|
#define _WWISE_VORBIS_UTILS_H_
|
||||||
|
|
||||||
|
#include "coding.h"
|
||||||
|
|
||||||
|
int wwise_vorbis_get_header(STREAMFILE *streamFile, off_t offset, wwise_header_type header_type, int * granulepos, size_t * packet_size, int big_endian);
|
||||||
|
int wwise_vorbis_rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_codec_data * data, int big_endian);
|
||||||
|
int wwise_vorbis_rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_codec_data * data, int big_endian, int channels);
|
||||||
|
|
||||||
|
|
||||||
|
#endif/*_WWISE_VORBIS_UTILS_H_ */
|
|
@ -180,6 +180,7 @@ static const char* extension_list[] = {
|
||||||
"nwa",
|
"nwa",
|
||||||
|
|
||||||
//"ogg", //common
|
//"ogg", //common
|
||||||
|
"ogl",
|
||||||
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
|
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
|
||||||
"omu",
|
"omu",
|
||||||
"otm",
|
"otm",
|
||||||
|
@ -197,6 +198,7 @@ static const char* extension_list[] = {
|
||||||
"psnd",
|
"psnd",
|
||||||
"psw",
|
"psw",
|
||||||
|
|
||||||
|
"rak",
|
||||||
"ras",
|
"ras",
|
||||||
"raw",
|
"raw",
|
||||||
"rkv",
|
"rkv",
|
||||||
|
@ -261,6 +263,8 @@ static const char* extension_list[] = {
|
||||||
"swag",
|
"swag",
|
||||||
"swav",
|
"swav",
|
||||||
"swd",
|
"swd",
|
||||||
|
"sxd",
|
||||||
|
"sxd2",
|
||||||
|
|
||||||
"tec",
|
"tec",
|
||||||
"thp",
|
"thp",
|
||||||
|
@ -419,6 +423,7 @@ static const coding_info coding_info_list[] = {
|
||||||
{coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"},
|
{coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"},
|
||||||
{coding_OTNS_IMA, "Omikron: The Nomad Soul 4-bit IMA ADPCM"},
|
{coding_OTNS_IMA, "Omikron: The Nomad Soul 4-bit IMA ADPCM"},
|
||||||
{coding_FSB_IMA, "FSB multichannel 4-bit IMA ADPCM"},
|
{coding_FSB_IMA, "FSB multichannel 4-bit IMA ADPCM"},
|
||||||
|
{coding_WWISE_IMA, "Audiokinetic Wwise 4-bit IMA ADPCM"},
|
||||||
{coding_WS, "Westwood Studios ADPCM"},
|
{coding_WS, "Westwood Studios ADPCM"},
|
||||||
{coding_ACM, "InterPlay ACM"},
|
{coding_ACM, "InterPlay ACM"},
|
||||||
{coding_NWA0, "NWA DPCM Level 0"},
|
{coding_NWA0, "NWA DPCM Level 0"},
|
||||||
|
@ -437,6 +442,8 @@ static const coding_info coding_info_list[] = {
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
{coding_ogg_vorbis, "Ogg Vorbis"},
|
{coding_ogg_vorbis, "Ogg Vorbis"},
|
||||||
{coding_fsb_vorbis, "FSB Vorbis"},
|
{coding_fsb_vorbis, "FSB Vorbis"},
|
||||||
|
{coding_wwise_vorbis, "Wwise Vorbis"},
|
||||||
|
{coding_ogl_vorbis, "OGL Vorbis"},
|
||||||
#endif
|
#endif
|
||||||
#ifdef VGM_USE_MPEG
|
#ifdef VGM_USE_MPEG
|
||||||
{coding_fake_MPEG2_L2, "MPEG-2 Layer II Audio"},
|
{coding_fake_MPEG2_L2, "MPEG-2 Layer II Audio"},
|
||||||
|
@ -817,7 +824,7 @@ static const meta_info meta_info_list[] = {
|
||||||
{meta_PS3_IVAG, "PS3 'IVAG' Header"},
|
{meta_PS3_IVAG, "PS3 'IVAG' Header"},
|
||||||
{meta_PS2_2PFS, "Konami 2PFS header"},
|
{meta_PS2_2PFS, "Konami 2PFS header"},
|
||||||
{meta_RSD6OOGV, "RSD6/OOGV Header"},
|
{meta_RSD6OOGV, "RSD6/OOGV Header"},
|
||||||
{meta_UBI_CKD, "CKD 'RIFF' Header"},
|
{meta_UBI_CKD, "Ubisoft CKD RIFF header"},
|
||||||
{meta_PS2_VBK, "PS2 VBK Header"},
|
{meta_PS2_VBK, "PS2 VBK Header"},
|
||||||
{meta_OTM, "Otomedius OTM Header"},
|
{meta_OTM, "Otomedius OTM Header"},
|
||||||
{meta_CSTM, "Nintendo 3DS CSTM Header"},
|
{meta_CSTM, "Nintendo 3DS CSTM Header"},
|
||||||
|
@ -837,6 +844,9 @@ static const meta_info meta_info_list[] = {
|
||||||
{meta_XMA_RIFF, "Microsoft XMA RIFF header"},
|
{meta_XMA_RIFF, "Microsoft XMA RIFF header"},
|
||||||
{meta_X360_AST, "Capcom AST header"},
|
{meta_X360_AST, "Capcom AST header"},
|
||||||
{meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"},
|
{meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"},
|
||||||
|
{meta_UBI_RAKI, "Ubisoft RAKI header"},
|
||||||
|
{meta_SXD, "Sony SXD header"},
|
||||||
|
{meta_OGL, "Shin'en OGL header"},
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
||||||
|
|
|
@ -203,8 +203,11 @@ VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile) {
|
||||||
if (!(double_loop_end &&
|
if (!(double_loop_end &&
|
||||||
read_32bitBE(0x30,streamFile) +
|
read_32bitBE(0x30,streamFile) +
|
||||||
read_32bitBE(0x0c,streamFile) + 8 ==
|
read_32bitBE(0x0c,streamFile) + 8 ==
|
||||||
read_32bitBE(0x10,streamFile)*2))
|
read_32bitBE(0x10,streamFile)*2)) {
|
||||||
goto fail;
|
/* for Mr.Driller Drill Land, no idea about the above but seems to play and loop ok */
|
||||||
|
VGM_LOG("Cstr: bad loop check ignored\n");
|
||||||
|
//goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr,"loop points agree\n");
|
fprintf(stderr,"loop points agree\n");
|
||||||
|
|
|
@ -1,259 +1,264 @@
|
||||||
noinst_LTLIBRARIES = libmeta.la
|
noinst_LTLIBRARIES = libmeta.la
|
||||||
|
|
||||||
AM_CFLAGS = -Wall @CFLAGS@ -DVAR_ARRAYS -I$(top_builddir) -I$(top_srcdir)
|
AM_CFLAGS = -Wall @CFLAGS@ -DVAR_ARRAYS -I$(top_builddir) -I$(top_srcdir)
|
||||||
AM_MAKEFLAGS=-f Makefile.unix
|
AM_MAKEFLAGS=-f Makefile.unix
|
||||||
|
|
||||||
libmeta_la_LDFLAGS =
|
libmeta_la_LDFLAGS =
|
||||||
libmeta_la_SOURCES =
|
libmeta_la_SOURCES =
|
||||||
libmeta_la_SOURCES += Cstr.c
|
libmeta_la_SOURCES += Cstr.c
|
||||||
libmeta_la_SOURCES += adx_header.c
|
libmeta_la_SOURCES += adx.c
|
||||||
libmeta_la_SOURCES += afc_header.c
|
libmeta_la_SOURCES += afc_header.c
|
||||||
libmeta_la_SOURCES += agsc.c
|
libmeta_la_SOURCES += agsc.c
|
||||||
libmeta_la_SOURCES += ast.c
|
libmeta_la_SOURCES += ast.c
|
||||||
libmeta_la_SOURCES += brstm.c
|
libmeta_la_SOURCES += brstm.c
|
||||||
libmeta_la_SOURCES += ea_header.c
|
libmeta_la_SOURCES += ea_header.c
|
||||||
libmeta_la_SOURCES += gcsw.c halpst.c
|
libmeta_la_SOURCES += gcsw.c halpst.c
|
||||||
libmeta_la_SOURCES += nds_strm.c
|
libmeta_la_SOURCES += nds_strm.c
|
||||||
libmeta_la_SOURCES += ngc_adpdtk.c
|
libmeta_la_SOURCES += ngc_adpdtk.c
|
||||||
libmeta_la_SOURCES += ngc_caf.c
|
libmeta_la_SOURCES += ngc_caf.c
|
||||||
libmeta_la_SOURCES += ngc_dsp_std.c
|
libmeta_la_SOURCES += ngc_dsp_std.c
|
||||||
libmeta_la_SOURCES += ps2_ads.c
|
libmeta_la_SOURCES += ps2_ads.c
|
||||||
libmeta_la_SOURCES += ps2_exst.c
|
libmeta_la_SOURCES += ps2_exst.c
|
||||||
libmeta_la_SOURCES += ps2_ild.c
|
libmeta_la_SOURCES += ps2_ild.c
|
||||||
libmeta_la_SOURCES += ps2_int.c
|
libmeta_la_SOURCES += ps2_int.c
|
||||||
libmeta_la_SOURCES += ps2_mib.c
|
libmeta_la_SOURCES += ps2_mib.c
|
||||||
libmeta_la_SOURCES += ps2_mic.c
|
libmeta_la_SOURCES += ps2_mic.c
|
||||||
libmeta_la_SOURCES += ps2_npsf.c
|
libmeta_la_SOURCES += ps2_npsf.c
|
||||||
libmeta_la_SOURCES += ps2_pnb.c
|
libmeta_la_SOURCES += ps2_pnb.c
|
||||||
libmeta_la_SOURCES += ps2_rxw.c
|
libmeta_la_SOURCES += ps2_rxw.c
|
||||||
libmeta_la_SOURCES += ps2_str.c
|
libmeta_la_SOURCES += ps2_str.c
|
||||||
libmeta_la_SOURCES += ps2_svag.c
|
libmeta_la_SOURCES += ps2_svag.c
|
||||||
libmeta_la_SOURCES += ps2_vag.c
|
libmeta_la_SOURCES += ps2_vag.c
|
||||||
libmeta_la_SOURCES += ps2_vpk.c
|
libmeta_la_SOURCES += ps2_vpk.c
|
||||||
libmeta_la_SOURCES += psx_cdxa.c
|
libmeta_la_SOURCES += psx_cdxa.c
|
||||||
libmeta_la_SOURCES += raw.c
|
libmeta_la_SOURCES += raw.c
|
||||||
libmeta_la_SOURCES += rs03.c
|
libmeta_la_SOURCES += rs03.c
|
||||||
libmeta_la_SOURCES += rsf.c
|
libmeta_la_SOURCES += rsf.c
|
||||||
libmeta_la_SOURCES += rwsd.c
|
libmeta_la_SOURCES += rwsd.c
|
||||||
libmeta_la_SOURCES += psx_gms.c
|
libmeta_la_SOURCES += psx_gms.c
|
||||||
libmeta_la_SOURCES += xbox_xwav.c
|
libmeta_la_SOURCES += xbox_xwav.c
|
||||||
libmeta_la_SOURCES += xbox_wavm.c
|
libmeta_la_SOURCES += xbox_wavm.c
|
||||||
libmeta_la_SOURCES += genh.c
|
libmeta_la_SOURCES += genh.c
|
||||||
libmeta_la_SOURCES += ogg_vorbis_file.c
|
libmeta_la_SOURCES += ogg_vorbis_file.c
|
||||||
libmeta_la_SOURCES += ps2_bmdx.c
|
libmeta_la_SOURCES += ps2_bmdx.c
|
||||||
libmeta_la_SOURCES += aifc.c
|
libmeta_la_SOURCES += aifc.c
|
||||||
libmeta_la_SOURCES += str_snds.c
|
libmeta_la_SOURCES += str_snds.c
|
||||||
libmeta_la_SOURCES += ws_aud.c
|
libmeta_la_SOURCES += ws_aud.c
|
||||||
libmeta_la_SOURCES += ahx.c
|
libmeta_la_SOURCES += ahx.c
|
||||||
libmeta_la_SOURCES += ivb.c
|
libmeta_la_SOURCES += ivb.c
|
||||||
libmeta_la_SOURCES += svs.c
|
libmeta_la_SOURCES += svs.c
|
||||||
libmeta_la_SOURCES += riff.c
|
libmeta_la_SOURCES += riff.c
|
||||||
libmeta_la_SOURCES += pos.c
|
libmeta_la_SOURCES += pos.c
|
||||||
libmeta_la_SOURCES += nwa.c
|
libmeta_la_SOURCES += nwa.c
|
||||||
libmeta_la_SOURCES += ps2_rws.c
|
libmeta_la_SOURCES += ps2_rws.c
|
||||||
libmeta_la_SOURCES += ps2_hgc1.c
|
libmeta_la_SOURCES += ps2_hgc1.c
|
||||||
libmeta_la_SOURCES += xss.c
|
libmeta_la_SOURCES += xss.c
|
||||||
libmeta_la_SOURCES += ps2_sl3.c
|
libmeta_la_SOURCES += ps2_sl3.c
|
||||||
libmeta_la_SOURCES += ps2_aus.c
|
libmeta_la_SOURCES += ps2_aus.c
|
||||||
libmeta_la_SOURCES += fsb.c
|
libmeta_la_SOURCES += fsb.c
|
||||||
libmeta_la_SOURCES += fsb5.c
|
libmeta_la_SOURCES += fsb5.c
|
||||||
libmeta_la_SOURCES += rsd.c
|
libmeta_la_SOURCES += rsd.c
|
||||||
libmeta_la_SOURCES += rwx.c
|
libmeta_la_SOURCES += rwx.c
|
||||||
libmeta_la_SOURCES += xwb.c
|
libmeta_la_SOURCES += xwb.c
|
||||||
libmeta_la_SOURCES += ea_old.c
|
libmeta_la_SOURCES += ea_old.c
|
||||||
libmeta_la_SOURCES += ps2_xa30.c
|
libmeta_la_SOURCES += ps2_xa30.c
|
||||||
libmeta_la_SOURCES += musc.c
|
libmeta_la_SOURCES += musc.c
|
||||||
libmeta_la_SOURCES += ps2_leg.c
|
libmeta_la_SOURCES += ps2_leg.c
|
||||||
libmeta_la_SOURCES += ps2_filp.c
|
libmeta_la_SOURCES += ps2_filp.c
|
||||||
libmeta_la_SOURCES += ps2_ikm.c
|
libmeta_la_SOURCES += ps2_ikm.c
|
||||||
libmeta_la_SOURCES += musx.c
|
libmeta_la_SOURCES += musx.c
|
||||||
libmeta_la_SOURCES += ps2_sfs.c
|
libmeta_la_SOURCES += ps2_sfs.c
|
||||||
libmeta_la_SOURCES += sat_dvi.c
|
libmeta_la_SOURCES += sat_dvi.c
|
||||||
libmeta_la_SOURCES += ps2_bg00.c
|
libmeta_la_SOURCES += ps2_bg00.c
|
||||||
libmeta_la_SOURCES += dc_kcey.c
|
libmeta_la_SOURCES += dc_kcey.c
|
||||||
libmeta_la_SOURCES += ps2_rstm.c
|
libmeta_la_SOURCES += ps2_rstm.c
|
||||||
libmeta_la_SOURCES += acm.c
|
libmeta_la_SOURCES += acm.c
|
||||||
libmeta_la_SOURCES += ps2_kces.c
|
libmeta_la_SOURCES += ps2_kces.c
|
||||||
libmeta_la_SOURCES += ps2_dxh.c
|
libmeta_la_SOURCES += ps2_dxh.c
|
||||||
libmeta_la_SOURCES += ps2_psh.c
|
libmeta_la_SOURCES += ps2_psh.c
|
||||||
libmeta_la_SOURCES += mus_acm.c
|
libmeta_la_SOURCES += mus_acm.c
|
||||||
libmeta_la_SOURCES += sli.c
|
libmeta_la_SOURCES += sli.c
|
||||||
libmeta_la_SOURCES += sfl.c
|
libmeta_la_SOURCES += sfl.c
|
||||||
libmeta_la_SOURCES += pcm.c
|
libmeta_la_SOURCES += pcm.c
|
||||||
libmeta_la_SOURCES += ps2_psw.c
|
libmeta_la_SOURCES += ps2_psw.c
|
||||||
libmeta_la_SOURCES += rkv.c
|
libmeta_la_SOURCES += rkv.c
|
||||||
libmeta_la_SOURCES += ps2_vas.c
|
libmeta_la_SOURCES += ps2_vas.c
|
||||||
libmeta_la_SOURCES += ps2_tec.c
|
libmeta_la_SOURCES += ps2_tec.c
|
||||||
libmeta_la_SOURCES += ps2_enth.c
|
libmeta_la_SOURCES += ps2_enth.c
|
||||||
libmeta_la_SOURCES += sdt.c
|
libmeta_la_SOURCES += sdt.c
|
||||||
libmeta_la_SOURCES += aix.c
|
libmeta_la_SOURCES += aix.c
|
||||||
libmeta_la_SOURCES += ngc_tydsp.c
|
libmeta_la_SOURCES += ngc_tydsp.c
|
||||||
libmeta_la_SOURCES += wvs.c
|
libmeta_la_SOURCES += wvs.c
|
||||||
libmeta_la_SOURCES += xbox_stma.c
|
libmeta_la_SOURCES += xbox_stma.c
|
||||||
libmeta_la_SOURCES += xbox_ims.c
|
libmeta_la_SOURCES += xbox_ims.c
|
||||||
libmeta_la_SOURCES += de2.c
|
libmeta_la_SOURCES += de2.c
|
||||||
libmeta_la_SOURCES += dc_str.c
|
libmeta_la_SOURCES += dc_str.c
|
||||||
libmeta_la_SOURCES += xbox_xmu.c
|
libmeta_la_SOURCES += xbox_xmu.c
|
||||||
libmeta_la_SOURCES += ngc_bh2pcm.c
|
libmeta_la_SOURCES += ngc_bh2pcm.c
|
||||||
libmeta_la_SOURCES += sat_sap.c
|
libmeta_la_SOURCES += sat_sap.c
|
||||||
libmeta_la_SOURCES += dc_idvi.c
|
libmeta_la_SOURCES += dc_idvi.c
|
||||||
libmeta_la_SOURCES += ps2_rnd.c
|
libmeta_la_SOURCES += ps2_rnd.c
|
||||||
libmeta_la_SOURCES += xbox_xvas.c
|
libmeta_la_SOURCES += xbox_xvas.c
|
||||||
libmeta_la_SOURCES += kraw.c
|
libmeta_la_SOURCES += kraw.c
|
||||||
libmeta_la_SOURCES += ps2_xa2.c
|
libmeta_la_SOURCES += ps2_xa2.c
|
||||||
libmeta_la_SOURCES += idsp.c
|
libmeta_la_SOURCES += idsp.c
|
||||||
libmeta_la_SOURCES += ngc_ymf.c
|
libmeta_la_SOURCES += ngc_ymf.c
|
||||||
libmeta_la_SOURCES += nds_sad.c
|
libmeta_la_SOURCES += nds_sad.c
|
||||||
libmeta_la_SOURCES += ps2_ccc.c
|
libmeta_la_SOURCES += ps2_ccc.c
|
||||||
libmeta_la_SOURCES += psx_fag.c
|
libmeta_la_SOURCES += psx_fag.c
|
||||||
libmeta_la_SOURCES += ps2_mihb.c
|
libmeta_la_SOURCES += ps2_mihb.c
|
||||||
libmeta_la_SOURCES += ngc_pdt.c
|
libmeta_la_SOURCES += ngc_pdt.c
|
||||||
libmeta_la_SOURCES += wii_mus.c
|
libmeta_la_SOURCES += wii_mus.c
|
||||||
libmeta_la_SOURCES += dc_asd.c
|
libmeta_la_SOURCES += dc_asd.c
|
||||||
libmeta_la_SOURCES += naomi_spsd.c
|
libmeta_la_SOURCES += naomi_spsd.c
|
||||||
libmeta_la_SOURCES += bgw.c
|
libmeta_la_SOURCES += bgw.c
|
||||||
libmeta_la_SOURCES += ps2_ass.c
|
libmeta_la_SOURCES += ps2_ass.c
|
||||||
libmeta_la_SOURCES += ngc_waa_wac_wad_wam.c
|
libmeta_la_SOURCES += ngc_waa_wac_wad_wam.c
|
||||||
libmeta_la_SOURCES += seg.c
|
libmeta_la_SOURCES += seg.c
|
||||||
libmeta_la_SOURCES += str_asr.c
|
libmeta_la_SOURCES += str_asr.c
|
||||||
libmeta_la_SOURCES += zwdsp.c
|
libmeta_la_SOURCES += zwdsp.c
|
||||||
libmeta_la_SOURCES += gca.c
|
libmeta_la_SOURCES += gca.c
|
||||||
libmeta_la_SOURCES += ish_isd.c
|
libmeta_la_SOURCES += ish_isd.c
|
||||||
libmeta_la_SOURCES += spt_spd.c
|
libmeta_la_SOURCES += spt_spd.c
|
||||||
libmeta_la_SOURCES += ydsp.c
|
libmeta_la_SOURCES += ydsp.c
|
||||||
libmeta_la_SOURCES += gsp_gsb.c
|
libmeta_la_SOURCES += gsp_gsb.c
|
||||||
libmeta_la_SOURCES += ngc_ssm.c
|
libmeta_la_SOURCES += ngc_ssm.c
|
||||||
libmeta_la_SOURCES += msvp.c
|
libmeta_la_SOURCES += msvp.c
|
||||||
libmeta_la_SOURCES += ps2_joe.c
|
libmeta_la_SOURCES += ps2_joe.c
|
||||||
libmeta_la_SOURCES += vs.c
|
libmeta_la_SOURCES += vs.c
|
||||||
libmeta_la_SOURCES += vgs.c
|
libmeta_la_SOURCES += vgs.c
|
||||||
libmeta_la_SOURCES += dc_dcsw_dcs.c
|
libmeta_la_SOURCES += dc_dcsw_dcs.c
|
||||||
libmeta_la_SOURCES += wii_smp.c
|
libmeta_la_SOURCES += wii_smp.c
|
||||||
libmeta_la_SOURCES += ss_stream.c
|
libmeta_la_SOURCES += ss_stream.c
|
||||||
libmeta_la_SOURCES += emff.c
|
libmeta_la_SOURCES += emff.c
|
||||||
libmeta_la_SOURCES += thp.c
|
libmeta_la_SOURCES += thp.c
|
||||||
libmeta_la_SOURCES += wii_sts.c
|
libmeta_la_SOURCES += wii_sts.c
|
||||||
libmeta_la_SOURCES += capdsp.c
|
libmeta_la_SOURCES += capdsp.c
|
||||||
libmeta_la_SOURCES += wii_sng.c
|
libmeta_la_SOURCES += wii_sng.c
|
||||||
libmeta_la_SOURCES += aax.c
|
libmeta_la_SOURCES += aax.c
|
||||||
libmeta_la_SOURCES += ps2_p2bt.c
|
libmeta_la_SOURCES += ps2_p2bt.c
|
||||||
libmeta_la_SOURCES += ps2_gbts.c
|
libmeta_la_SOURCES += ps2_gbts.c
|
||||||
libmeta_la_SOURCES += ngc_ffcc_str.c
|
libmeta_la_SOURCES += ngc_ffcc_str.c
|
||||||
libmeta_la_SOURCES += sat_baka.c
|
libmeta_la_SOURCES += sat_baka.c
|
||||||
libmeta_la_SOURCES += nds_swav.c
|
libmeta_la_SOURCES += nds_swav.c
|
||||||
libmeta_la_SOURCES += vsf.c
|
libmeta_la_SOURCES += vsf.c
|
||||||
libmeta_la_SOURCES += nds_rrds.c
|
libmeta_la_SOURCES += nds_rrds.c
|
||||||
libmeta_la_SOURCES += ps2_tk5.c
|
libmeta_la_SOURCES += ps2_tk5.c
|
||||||
libmeta_la_SOURCES += ads.c
|
libmeta_la_SOURCES += ads.c
|
||||||
libmeta_la_SOURCES += wii_str.c
|
libmeta_la_SOURCES += wii_str.c
|
||||||
libmeta_la_SOURCES += zsd.c
|
libmeta_la_SOURCES += zsd.c
|
||||||
libmeta_la_SOURCES += ps2_mcg.c
|
libmeta_la_SOURCES += ps2_mcg.c
|
||||||
libmeta_la_SOURCES += redspark.c
|
libmeta_la_SOURCES += redspark.c
|
||||||
libmeta_la_SOURCES += ivaud.c
|
libmeta_la_SOURCES += ivaud.c
|
||||||
libmeta_la_SOURCES += ps2_vgs.c
|
libmeta_la_SOURCES += ps2_vgs.c
|
||||||
libmeta_la_SOURCES += ps2_sps.c
|
libmeta_la_SOURCES += ps2_sps.c
|
||||||
libmeta_la_SOURCES += nds_hwas.c
|
libmeta_la_SOURCES += nds_hwas.c
|
||||||
libmeta_la_SOURCES += ngc_lps.c
|
libmeta_la_SOURCES += ngc_lps.c
|
||||||
libmeta_la_SOURCES += ps2_snd.c
|
libmeta_la_SOURCES += ps2_snd.c
|
||||||
libmeta_la_SOURCES += naomi_adpcm.c
|
libmeta_la_SOURCES += naomi_adpcm.c
|
||||||
libmeta_la_SOURCES += sd9.c
|
libmeta_la_SOURCES += sd9.c
|
||||||
libmeta_la_SOURCES += 2dx9.c
|
libmeta_la_SOURCES += 2dx9.c
|
||||||
libmeta_la_SOURCES += ngc_dsp_ygo.c
|
libmeta_la_SOURCES += ngc_dsp_ygo.c
|
||||||
libmeta_la_SOURCES += ps2_vgv.c
|
libmeta_la_SOURCES += ps2_vgv.c
|
||||||
libmeta_la_SOURCES += ngc_gcub.c
|
libmeta_la_SOURCES += ngc_gcub.c
|
||||||
libmeta_la_SOURCES += maxis_xa.c
|
libmeta_la_SOURCES += maxis_xa.c
|
||||||
libmeta_la_SOURCES += ngc_sck_dsp.c
|
libmeta_la_SOURCES += ngc_sck_dsp.c
|
||||||
libmeta_la_SOURCES += apple_caff.c
|
libmeta_la_SOURCES += apple_caff.c
|
||||||
libmeta_la_SOURCES += pc_mxst.c
|
libmeta_la_SOURCES += pc_mxst.c
|
||||||
libmeta_la_SOURCES += pc_sob.c
|
libmeta_la_SOURCES += pc_sob.c
|
||||||
libmeta_la_SOURCES += exakt_sc.c
|
libmeta_la_SOURCES += exakt_sc.c
|
||||||
libmeta_la_SOURCES += wii_bns.c
|
libmeta_la_SOURCES += wii_bns.c
|
||||||
libmeta_la_SOURCES += pona.c
|
libmeta_la_SOURCES += pona.c
|
||||||
libmeta_la_SOURCES += xbox_hlwav.c
|
libmeta_la_SOURCES += xbox_hlwav.c
|
||||||
libmeta_la_SOURCES += stx.c
|
libmeta_la_SOURCES += stx.c
|
||||||
libmeta_la_SOURCES += ps2_stm.c
|
libmeta_la_SOURCES += ps2_stm.c
|
||||||
libmeta_la_SOURCES += myspd.c
|
libmeta_la_SOURCES += myspd.c
|
||||||
libmeta_la_SOURCES += his.c
|
libmeta_la_SOURCES += his.c
|
||||||
libmeta_la_SOURCES += ps2_ast.c
|
libmeta_la_SOURCES += ps2_ast.c
|
||||||
libmeta_la_SOURCES += dmsg_segh.c
|
libmeta_la_SOURCES += dmsg_segh.c
|
||||||
libmeta_la_SOURCES += ngc_dsp_konami.c
|
libmeta_la_SOURCES += ngc_dsp_konami.c
|
||||||
libmeta_la_SOURCES += ps2_ster.c
|
libmeta_la_SOURCES += ps2_ster.c
|
||||||
libmeta_la_SOURCES += bnsf.c
|
libmeta_la_SOURCES += bnsf.c
|
||||||
libmeta_la_SOURCES += ps2_wb.c
|
libmeta_la_SOURCES += ps2_wb.c
|
||||||
libmeta_la_SOURCES += s14_sss.c
|
libmeta_la_SOURCES += s14_sss.c
|
||||||
libmeta_la_SOURCES += ps2_gcm.c
|
libmeta_la_SOURCES += ps2_gcm.c
|
||||||
libmeta_la_SOURCES += ps2_smpl.c
|
libmeta_la_SOURCES += ps2_smpl.c
|
||||||
libmeta_la_SOURCES += ps2_msa.c
|
libmeta_la_SOURCES += ps2_msa.c
|
||||||
libmeta_la_SOURCES += pc_smp.c
|
libmeta_la_SOURCES += pc_smp.c
|
||||||
libmeta_la_SOURCES += p3d.c
|
libmeta_la_SOURCES += p3d.c
|
||||||
libmeta_la_SOURCES += ps2_adsc.c
|
libmeta_la_SOURCES += ps2_adsc.c
|
||||||
libmeta_la_SOURCES += psx_str_mgav.c
|
libmeta_la_SOURCES += psx_str_mgav.c
|
||||||
libmeta_la_SOURCES += ngc_bo2.c
|
libmeta_la_SOURCES += ngc_bo2.c
|
||||||
libmeta_la_SOURCES += ngc_dsp_mpds.c
|
libmeta_la_SOURCES += ngc_dsp_mpds.c
|
||||||
libmeta_la_SOURCES += ps2_khv.c
|
libmeta_la_SOURCES += ps2_khv.c
|
||||||
libmeta_la_SOURCES += ps2_voi.c
|
libmeta_la_SOURCES += ps2_voi.c
|
||||||
libmeta_la_SOURCES += dsp_sth_str.c
|
libmeta_la_SOURCES += dsp_sth_str.c
|
||||||
libmeta_la_SOURCES += ps2_b1s.c
|
libmeta_la_SOURCES += ps2_b1s.c
|
||||||
libmeta_la_SOURCES += ps2_wad.c
|
libmeta_la_SOURCES += ps2_wad.c
|
||||||
libmeta_la_SOURCES += ps2_lpcm.c
|
libmeta_la_SOURCES += ps2_lpcm.c
|
||||||
libmeta_la_SOURCES += ps2_adm.c
|
libmeta_la_SOURCES += ps2_adm.c
|
||||||
libmeta_la_SOURCES += dsp_bdsp.c
|
libmeta_la_SOURCES += dsp_bdsp.c
|
||||||
libmeta_la_SOURCES += ps2_vms.c
|
libmeta_la_SOURCES += ps2_vms.c
|
||||||
libmeta_la_SOURCES += ps2_xau.c
|
libmeta_la_SOURCES += ps2_xau.c
|
||||||
libmeta_la_SOURCES += gh3_bar.c
|
libmeta_la_SOURCES += gh3_bar.c
|
||||||
libmeta_la_SOURCES += ffw.c
|
libmeta_la_SOURCES += ffw.c
|
||||||
libmeta_la_SOURCES += ps2_jstm.c
|
libmeta_la_SOURCES += ps2_jstm.c
|
||||||
libmeta_la_SOURCES += ps3_xvag.c
|
libmeta_la_SOURCES += ps3_xvag.c
|
||||||
libmeta_la_SOURCES += ps3_cps.c
|
libmeta_la_SOURCES += ps3_cps.c
|
||||||
libmeta_la_SOURCES += sqex_scd.c
|
libmeta_la_SOURCES += sqex_scd.c
|
||||||
libmeta_la_SOURCES += ngc_nst_dsp.c
|
libmeta_la_SOURCES += ngc_nst_dsp.c
|
||||||
libmeta_la_SOURCES += baf.c
|
libmeta_la_SOURCES += baf.c
|
||||||
libmeta_la_SOURCES += ps3_msf.c
|
libmeta_la_SOURCES += ps3_msf.c
|
||||||
libmeta_la_SOURCES += nub_vag.c
|
libmeta_la_SOURCES += nub_vag.c
|
||||||
libmeta_la_SOURCES += ps3_past.c
|
libmeta_la_SOURCES += ps3_past.c
|
||||||
libmeta_la_SOURCES += sgxd.c
|
libmeta_la_SOURCES += sgxd.c
|
||||||
libmeta_la_SOURCES += ngca.c
|
libmeta_la_SOURCES += ngca.c
|
||||||
libmeta_la_SOURCES += wii_ras.c
|
libmeta_la_SOURCES += wii_ras.c
|
||||||
libmeta_la_SOURCES += ps2_spm.c
|
libmeta_la_SOURCES += ps2_spm.c
|
||||||
libmeta_la_SOURCES += x360_tra.c
|
libmeta_la_SOURCES += x360_tra.c
|
||||||
libmeta_la_SOURCES += ps2_iab.c
|
libmeta_la_SOURCES += ps2_iab.c
|
||||||
libmeta_la_SOURCES += ps2_strlr.c
|
libmeta_la_SOURCES += ps2_strlr.c
|
||||||
libmeta_la_SOURCES += lsf.c
|
libmeta_la_SOURCES += lsf.c
|
||||||
libmeta_la_SOURCES += vawx.c
|
libmeta_la_SOURCES += vawx.c
|
||||||
libmeta_la_SOURCES += pc_snds.c
|
libmeta_la_SOURCES += pc_snds.c
|
||||||
libmeta_la_SOURCES += ps2_wmus.c
|
libmeta_la_SOURCES += ps2_wmus.c
|
||||||
libmeta_la_SOURCES += mattel_hyperscan.c
|
libmeta_la_SOURCES += mattel_hyperscan.c
|
||||||
libmeta_la_SOURCES += ios_psnd.c
|
libmeta_la_SOURCES += ios_psnd.c
|
||||||
libmeta_la_SOURCES += pc_adp.c
|
libmeta_la_SOURCES += pc_adp.c
|
||||||
libmeta_la_SOURCES += excitebots.c
|
libmeta_la_SOURCES += excitebots.c
|
||||||
libmeta_la_SOURCES += ps2_mtaf.c
|
libmeta_la_SOURCES += ps2_mtaf.c
|
||||||
libmeta_la_SOURCES += ps3_klbs.c
|
libmeta_la_SOURCES += ps3_klbs.c
|
||||||
libmeta_la_SOURCES += tun.c
|
libmeta_la_SOURCES += tun.c
|
||||||
libmeta_la_SOURCES += wpd.c
|
libmeta_la_SOURCES += wpd.c
|
||||||
libmeta_la_SOURCES += mn_str.c
|
libmeta_la_SOURCES += mn_str.c
|
||||||
libmeta_la_SOURCES += ps2_mss.c
|
libmeta_la_SOURCES += ps2_mss.c
|
||||||
libmeta_la_SOURCES += ps2_hsf.c
|
libmeta_la_SOURCES += ps2_hsf.c
|
||||||
libmeta_la_SOURCES += ps3_ivag.c
|
libmeta_la_SOURCES += ps3_ivag.c
|
||||||
libmeta_la_SOURCES += ps2_2pfs.c
|
libmeta_la_SOURCES += ps2_2pfs.c
|
||||||
libmeta_la_SOURCES += ubi_ckd.c
|
libmeta_la_SOURCES += ubi_ckd.c
|
||||||
libmeta_la_SOURCES += otm.c
|
libmeta_la_SOURCES += otm.c
|
||||||
libmeta_la_SOURCES += bcstm.c
|
libmeta_la_SOURCES += bcstm.c
|
||||||
libmeta_la_SOURCES += bfwav.c
|
libmeta_la_SOURCES += bfwav.c
|
||||||
libmeta_la_SOURCES += bfstm.c
|
libmeta_la_SOURCES += bfstm.c
|
||||||
libmeta_la_SOURCES += g1l.c
|
libmeta_la_SOURCES += g1l.c
|
||||||
libmeta_la_SOURCES += ps2_vbk.c
|
libmeta_la_SOURCES += ps2_vbk.c
|
||||||
libmeta_la_SOURCES += mca.c
|
libmeta_la_SOURCES += mca.c
|
||||||
libmeta_la_SOURCES += btsnd.c
|
libmeta_la_SOURCES += btsnd.c
|
||||||
libmeta_la_SOURCES += hca.c
|
libmeta_la_SOURCES += hca.c
|
||||||
libmeta_la_SOURCES += ps2_svag_snk.c
|
libmeta_la_SOURCES += ps2_svag_snk.c
|
||||||
libmeta_la_SOURCES += mp4.c
|
libmeta_la_SOURCES += mp4.c
|
||||||
libmeta_la_SOURCES += xma.c
|
libmeta_la_SOURCES += xma.c
|
||||||
libmeta_la_SOURCES += ps2_vds_vdm.c
|
libmeta_la_SOURCES += ps2_vds_vdm.c
|
||||||
libmeta_la_SOURCES += x360_cxs.c
|
libmeta_la_SOURCES += x360_cxs.c
|
||||||
libmeta_la_SOURCES += dsp_adx.c
|
libmeta_la_SOURCES += dsp_adx.c
|
||||||
libmeta_la_SOURCES += bik.c
|
libmeta_la_SOURCES += bik.c
|
||||||
libmeta_la_SOURCES += akb.c
|
libmeta_la_SOURCES += akb.c
|
||||||
libmeta_la_SOURCES += x360_ast.c
|
libmeta_la_SOURCES += x360_ast.c
|
||||||
libmeta_la_SOURCES += wwise.c
|
libmeta_la_SOURCES += wwise.c
|
||||||
|
libmeta_la_SOURCES += ubi_raki.c
|
||||||
EXTRA_DIST = meta.h
|
libmeta_la_SOURCES += x360_pasx.c
|
||||||
|
libmeta_la_SOURCES += x360_nub.c
|
||||||
|
libmeta_la_SOURCES += sxd.c
|
||||||
|
libmeta_la_SOURCES += ogl.c
|
||||||
|
|
||||||
|
EXTRA_DIST = meta.h
|
||||||
|
|
|
@ -11,138 +11,146 @@
|
||||||
|
|
||||||
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add);
|
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add);
|
||||||
|
|
||||||
|
/* ADX - CRI Middleware format */
|
||||||
VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM * vgmstream = NULL;
|
||||||
off_t stream_offset;
|
off_t start_offset, hist_offset = 0;
|
||||||
|
int loop_flag = 0, channel_count;
|
||||||
|
int32_t loop_start_sample = 0, loop_end_sample = 0;
|
||||||
uint16_t version_signature;
|
uint16_t version_signature;
|
||||||
int loop_flag=0;
|
|
||||||
int channel_count;
|
|
||||||
int32_t loop_start_sample=0;
|
|
||||||
int32_t loop_end_sample=0;
|
|
||||||
meta_t header_type;
|
meta_t header_type;
|
||||||
|
coding_t coding_type = coding_CRI_ADX;
|
||||||
int16_t coef1, coef2;
|
int16_t coef1, coef2;
|
||||||
uint16_t cutoff;
|
|
||||||
char filename[PATH_LIMIT];
|
|
||||||
int coding_type = coding_CRI_ADX;
|
|
||||||
uint16_t xor_start=0,xor_mult=0,xor_add=0;
|
uint16_t xor_start=0,xor_mult=0,xor_add=0;
|
||||||
|
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
/* check extension, case insensitive */
|
||||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
if (!check_extensions(streamFile,"adx")) goto fail;
|
||||||
if (strcasecmp("adx",filename_extension(filename))) goto fail;
|
|
||||||
|
|
||||||
/* check first 2 bytes */
|
/* check first 2 bytes */
|
||||||
if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail;
|
if ((uint16_t)read_16bitBE(0x00,streamFile)!=0x8000) goto fail;
|
||||||
|
|
||||||
/* get stream offset, check for CRI signature just before */
|
/* get stream offset, check for CRI signature just before */
|
||||||
stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4;
|
start_offset = (uint16_t)read_16bitBE(0x02,streamFile) + 4;
|
||||||
if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */
|
if ((uint16_t)read_16bitBE(start_offset-6,streamFile)!=0x2863 || /* "(c" */
|
||||||
(uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */
|
(uint32_t)read_32bitBE(start_offset-4,streamFile)!=0x29435249 /* ")CRI" */
|
||||||
) goto fail;
|
) goto fail;
|
||||||
|
|
||||||
/* check for encoding type */
|
/* check for encoding type */
|
||||||
/* 2 is for some unknown fixed filter, 3 is standard ADX, 4 is
|
/* 0x02 is for some unknown fixed filter, 0x03 is standard ADX, 0x04 is
|
||||||
* ADX with exponential scale, 0x11 is AHX */
|
* ADX with exponential scale, 0x10 is AHX for DC, 0x11 is AHX */
|
||||||
if (read_8bit(4,streamFile) != 3) goto fail;
|
if (read_8bit(0x04,streamFile) != 3) goto fail;
|
||||||
|
|
||||||
/* check for frame size (only 18 is supported at the moment) */
|
/* check for frame size (only 18 is supported at the moment) */
|
||||||
if (read_8bit(5,streamFile) != 18) goto fail;
|
if (read_8bit(0x05,streamFile) != 18) goto fail;
|
||||||
|
|
||||||
/* check for bits per sample? (only 4 makes sense for ADX) */
|
/* check for bits per sample? (only 4 makes sense for ADX) */
|
||||||
if (read_8bit(6,streamFile) != 4) goto fail;
|
if (read_8bit(0x06,streamFile) != 4) goto fail;
|
||||||
|
|
||||||
|
/* older ADX (adxencd) up to 2ch, newer ADX (criatomencd) up to 8 */
|
||||||
|
channel_count = read_8bit(0x07,streamFile);
|
||||||
|
|
||||||
/* check version signature, read loop info */
|
/* check version signature, read loop info */
|
||||||
version_signature = read_16bitBE(0x12,streamFile);
|
version_signature = read_16bitBE(0x12,streamFile);
|
||||||
|
|
||||||
|
|
||||||
/* encryption */
|
/* encryption */
|
||||||
if (version_signature == 0x0408) {
|
if (version_signature == 0x0408) {
|
||||||
if (find_key(streamFile, 8, &xor_start, &xor_mult, &xor_add))
|
if (find_key(streamFile, 8, &xor_start, &xor_mult, &xor_add)) {
|
||||||
{
|
|
||||||
coding_type = coding_CRI_ADX_enc_8;
|
coding_type = coding_CRI_ADX_enc_8;
|
||||||
version_signature = 0x0400;
|
version_signature = 0x0400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (version_signature == 0x0409) {
|
else if (version_signature == 0x0409) {
|
||||||
if (find_key(streamFile, 9, &xor_start, &xor_mult, &xor_add))
|
if (find_key(streamFile, 9, &xor_start, &xor_mult, &xor_add)) {
|
||||||
{
|
|
||||||
coding_type = coding_CRI_ADX_enc_9;
|
coding_type = coding_CRI_ADX_enc_9;
|
||||||
version_signature = 0x0400;
|
version_signature = 0x0400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version_signature == 0x0300) { /* type 03 */
|
|
||||||
|
/* version + extra data */
|
||||||
|
if (version_signature == 0x0300) { /* early ADX (~2004?) */
|
||||||
|
size_t base_size = 0x14, loops_size = 0x18;
|
||||||
|
|
||||||
header_type = meta_ADX_03;
|
header_type = meta_ADX_03;
|
||||||
if (stream_offset-6 >= 0x2c) { /* enough space for loop info? */
|
|
||||||
loop_flag = (read_32bitBE(0x18,streamFile) != 0);
|
/* no sample history */
|
||||||
loop_start_sample = read_32bitBE(0x1c,streamFile);
|
|
||||||
//loop_start_offset = read_32bitBE(0x20,streamFile);
|
if (start_offset - 6 >= base_size + loops_size) { /* enough space for loop info? */
|
||||||
loop_end_sample = read_32bitBE(0x24,streamFile);
|
off_t loops_offset = base_size;
|
||||||
//loop_end_offset = read_32bitBE(0x28,streamFile);
|
|
||||||
|
/* off+0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||||
|
* ex. loop_start=12: enc_start=32, padding=20 (32-20=12); loop_start=35: enc_start=64, padding=29 (64-29=35)
|
||||||
|
* off+0x02 (2): loop sample(?) flag (always 1) */
|
||||||
|
loop_flag = read_32bitBE(loops_offset+0x04,streamFile) != 0; /* loop offset(?) flag (always 1) */
|
||||||
|
loop_start_sample = read_32bitBE(loops_offset+0x08,streamFile);
|
||||||
|
//loop_start_offset = read_32bitBE(loops_offset+0x0c,streamFile);
|
||||||
|
loop_end_sample = read_32bitBE(loops_offset+0x10,streamFile);
|
||||||
|
//loop_end_offset = read_32bitBE(loops_offset+0x14,streamFile);
|
||||||
}
|
}
|
||||||
} else if (version_signature == 0x0400) {
|
}
|
||||||
|
else if (version_signature == 0x0400) { /* common */
|
||||||
off_t ainf_info_length=0;
|
size_t base_size = 0x18, hist_size, ainf_size = 0, loops_size = 0x18;
|
||||||
|
off_t ainf_offset;
|
||||||
if((uint32_t)read_32bitBE(0x24,streamFile)==0x41494E46) /* AINF Header */
|
|
||||||
ainf_info_length = (off_t)read_32bitBE(0x28,streamFile);
|
|
||||||
|
|
||||||
header_type = meta_ADX_04;
|
header_type = meta_ADX_04;
|
||||||
if (stream_offset-ainf_info_length-6 >= 0x38) { /* enough space for loop info? */
|
|
||||||
if (read_32bitBE(0x24,streamFile) == 0xFFFEFFFE)
|
|
||||||
loop_flag = 0;
|
|
||||||
else
|
|
||||||
loop_flag = (read_32bitBE(0x24,streamFile) != 0);
|
|
||||||
|
|
||||||
loop_start_sample = read_32bitBE(0x28,streamFile);
|
hist_offset = base_size; /* always present but often blank */
|
||||||
//loop_start_offset = read_32bitBE(0x2c,streamFile);
|
hist_size = (channel_count > 1 ? 4*channel_count : 4+4); /* min is 8, even in 1ch files */
|
||||||
loop_end_sample = read_32bitBE(0x30,streamFile);
|
|
||||||
//loop_end_offset = read_32bitBE(0x34,streamFile);
|
ainf_offset = base_size + hist_size + 0x4; /* not seen with >2ch though */
|
||||||
|
if ((uint32_t)read_32bitBE(ainf_offset+0x00,streamFile) == 0x41494E46) /* "AINF" */
|
||||||
|
ainf_size = read_32bitBE(ainf_offset+0x04,streamFile);
|
||||||
|
|
||||||
|
if (start_offset - ainf_size - 6 >= hist_offset + hist_size + loops_size) { /* enough space for loop info? */
|
||||||
|
off_t loops_offset = base_size + hist_size;
|
||||||
|
|
||||||
|
/* off+0x00 (2): initial loop padding (the encoder adds a few blank samples so loop start is block-aligned; max 31)
|
||||||
|
* ex. loop_start=12: enc_start=32, padding=20 (32-20=12); loop_start=35: enc_start=64, padding=29 (64-29=35)
|
||||||
|
* off+0x02 (2): loop sample(?) flag (always 1) */
|
||||||
|
loop_flag = read_32bitBE(loops_offset+0x04,streamFile) != 0; /* loop offset(?) flag (always 1) */
|
||||||
|
loop_start_sample = read_32bitBE(loops_offset+0x08,streamFile);
|
||||||
|
//loop_start_offset = read_32bitBE(loops_offset+0x0c,streamFile);
|
||||||
|
loop_end_sample = read_32bitBE(loops_offset+0x10,streamFile);
|
||||||
|
//loop_end_offset = read_32bitBE(loops_offset+0x14,streamFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* AINF header can also start after the loop points
|
/* AINF header info (may be inserted by CRI's tools but is rarely used)
|
||||||
* (may be inserted by CRI's tools but is rarely used) */
|
* Can also start right after the loop points (base_size + hist_size + loops_size)
|
||||||
/* ainf_magic = read_32bitBE(0x38,streamFile); */ /* 0x41494E46 */
|
* 0x00 (4): "AINF"; 0x04 (4): size; 0x08 (10): str_id
|
||||||
/* ainf_length = read_32bitBE(0x3c,streamFile); */
|
* 0x18 (2): volume (0=base/max?, negative=reduce)
|
||||||
/* ainf_str_id = read_string(0x40,streamFile); */ /* max size 0x10 */
|
* 0x1c (2): pan l; 0x1e (2): pan r (0=base, max +-128) */
|
||||||
/* ainf_volume = read_16bitBE(0x50,streamFile); */ /* 0=base/max?, negative=reduce */
|
}
|
||||||
/* ainf_pan_l = read_16bitBE(0x54,streamFile); */ /* 0=base, max +-128 */
|
else if (version_signature == 0x0500) { /* found in some SFD: Buggy Heat, appears to have no loop */
|
||||||
/* ainf_pan_r = read_16bitBE(0x56,streamFile); */
|
|
||||||
|
|
||||||
} else if (version_signature == 0x0500) { /* found in some SFD : Buggy Heat, appears to have no loop */
|
|
||||||
header_type = meta_ADX_05;
|
header_type = meta_ADX_05;
|
||||||
} else goto fail; /* not a known/supported version signature */
|
}
|
||||||
|
else { /* not a known/supported version signature */
|
||||||
/* At this point we almost certainly have an ADX file,
|
goto fail;
|
||||||
* so let's build the VGMSTREAM. */
|
|
||||||
|
|
||||||
/* high-pass cutoff frequency, always 500 that I've seen */
|
|
||||||
cutoff = (uint16_t)read_16bitBE(0x10,streamFile);
|
|
||||||
|
|
||||||
if (loop_start_sample == 0 && loop_end_sample == 0) {
|
|
||||||
loop_flag = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_count = read_8bit(7,streamFile);
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
/* fill in the vital statistics */
|
|
||||||
vgmstream->num_samples = read_32bitBE(0xc,streamFile);
|
vgmstream->num_samples = read_32bitBE(0xc,streamFile);
|
||||||
vgmstream->sample_rate = read_32bitBE(8,streamFile);
|
vgmstream->sample_rate = read_32bitBE(0x8,streamFile);
|
||||||
/* channels and loop flag are set by allocate_vgmstream */
|
|
||||||
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;
|
||||||
|
|
||||||
vgmstream->coding_type = coding_type;
|
vgmstream->coding_type = coding_type;
|
||||||
if (channel_count==1)
|
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->interleave_block_size = 18;
|
||||||
else
|
|
||||||
vgmstream->layout_type = layout_interleave;
|
|
||||||
vgmstream->meta_type = header_type;
|
vgmstream->meta_type = header_type;
|
||||||
|
|
||||||
vgmstream->interleave_block_size=18;
|
|
||||||
|
|
||||||
/* calculate filter coefficients */
|
/* calculate filter coefficients */
|
||||||
{
|
{
|
||||||
double x,y,z,a,b,c;
|
double x,y,z,a,b,c;
|
||||||
|
/* high-pass cutoff frequency, always 500 that I've seen */
|
||||||
|
uint16_t cutoff = (uint16_t)read_16bitBE(0x10,streamFile);
|
||||||
|
|
||||||
x = cutoff;
|
x = cutoff;
|
||||||
y = vgmstream->sample_rate;
|
y = vgmstream->sample_rate;
|
||||||
|
@ -156,27 +164,22 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||||
coef2 = floor(c*c*-4096);
|
coef2 = floor(c*c*-4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* init decoder */
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
STREAMFILE * chstreamfile;
|
|
||||||
|
|
||||||
/* ADX is so tightly interleaved that having two buffers is silly */
|
|
||||||
chstreamfile = streamFile->open(streamFile,filename,18*0x400);
|
|
||||||
if (!chstreamfile) goto fail;
|
|
||||||
|
|
||||||
for (i=0;i<channel_count;i++) {
|
for (i=0;i<channel_count;i++) {
|
||||||
vgmstream->ch[i].streamfile = chstreamfile;
|
|
||||||
|
|
||||||
vgmstream->ch[i].channel_start_offset=
|
|
||||||
vgmstream->ch[i].offset=
|
|
||||||
stream_offset+18*i;
|
|
||||||
|
|
||||||
vgmstream->ch[i].adpcm_coef[0] = coef1;
|
vgmstream->ch[i].adpcm_coef[0] = coef1;
|
||||||
vgmstream->ch[i].adpcm_coef[1] = coef2;
|
vgmstream->ch[i].adpcm_coef[1] = coef2;
|
||||||
|
|
||||||
if (coding_type == coding_CRI_ADX_enc_8 ||
|
/* 2 hist shorts per ch, corresponding to the very first original sample repeated (verified with CRI's encoders).
|
||||||
coding_type == coding_CRI_ADX_enc_9)
|
* Not vital as their effect is small, after a few samples they don't matter, and most songs start in silence. */
|
||||||
{
|
if (hist_offset) {
|
||||||
|
vgmstream->ch[i].adpcm_history1_32 = read_16bitBE(hist_offset + i*4 + 0x00,streamFile);
|
||||||
|
vgmstream->ch[i].adpcm_history2_32 = read_16bitBE(hist_offset + i*4 + 0x02,streamFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coding_type == coding_CRI_ADX_enc_8 || coding_type == coding_CRI_ADX_enc_9) {
|
||||||
int j;
|
int j;
|
||||||
vgmstream->ch[i].adx_channels = channel_count;
|
vgmstream->ch[i].adx_channels = channel_count;
|
||||||
vgmstream->ch[i].adx_xor = xor_start;
|
vgmstream->ch[i].adx_xor = xor_start;
|
||||||
|
@ -189,11 +192,13 @@ VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
||||||
|
goto fail;
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
|
|
||||||
/* clean up anything we may have opened */
|
|
||||||
fail:
|
fail:
|
||||||
if (vgmstream) close_vgmstream(vgmstream);
|
close_vgmstream(vgmstream);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +431,7 @@ static struct {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* type 9 keys */
|
/* type 9 keys (may not be autodetected correctly) */
|
||||||
static struct {
|
static struct {
|
||||||
uint16_t start,mult,add;
|
uint16_t start,mult,add;
|
||||||
} keys_9[] = {
|
} keys_9[] = {
|
||||||
|
@ -442,6 +447,10 @@ static struct {
|
||||||
* guessed with degod */
|
* guessed with degod */
|
||||||
{0x0005,0x0bcd,0x1add},
|
{0x0005,0x0bcd,0x1add},
|
||||||
|
|
||||||
|
/* Raramagi [Android]
|
||||||
|
* found in 2ch */
|
||||||
|
{0x0000,0x0b99,0x1e33},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]);
|
static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]);
|
|
@ -138,6 +138,7 @@ VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||||
off_t start_offset, header_offset;
|
off_t start_offset, header_offset;
|
||||||
size_t datasize;
|
size_t datasize;
|
||||||
int loop_flag = 0, channel_count, codec;
|
int loop_flag = 0, channel_count, codec;
|
||||||
|
int akb_header_size, sound_index = 0, sound_offset_data, sound, sound_header_size, material_offset_data, material_index = 0, material, extradata, encryption_flag;
|
||||||
|
|
||||||
/* check extensions */
|
/* check extensions */
|
||||||
if ( !check_extensions(streamFile, "akb") )
|
if ( !check_extensions(streamFile, "akb") )
|
||||||
|
@ -147,10 +148,17 @@ VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||||
if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */
|
if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* this is weird (BE?) but seems to work */
|
akb_header_size = read_16bitLE(0x06, streamFile);
|
||||||
start_offset = (uint16_t)read_16bitBE(0x21,streamFile);
|
sound_offset_data = akb_header_size + sound_index * 0x10;
|
||||||
header_offset = start_offset - 0x50;
|
sound = read_32bitLE(sound_offset_data + 0x04, streamFile);
|
||||||
if (header_offset < 0x30) goto fail;
|
sound_header_size = read_16bitLE(sound + 0x02, streamFile);
|
||||||
|
material_offset_data = sound + sound_header_size + material_index * 0x10;
|
||||||
|
material = sound + read_32bitLE(material_offset_data + 0x04, streamFile);
|
||||||
|
encryption_flag = read_8bit(material + 0x03, streamFile) & 0x08;
|
||||||
|
extradata = material + read_16bitLE(material + 0x04, streamFile);
|
||||||
|
|
||||||
|
start_offset = material + read_16bitLE(material + 0x04, streamFile) + read_32bitLE(material + 0x18, streamFile);
|
||||||
|
header_offset = material;
|
||||||
|
|
||||||
channel_count = read_8bit(header_offset+0x02,streamFile);
|
channel_count = read_8bit(header_offset+0x02,streamFile);
|
||||||
loop_flag = read_32bitLE(header_offset+0x14,streamFile) > 0;
|
loop_flag = read_32bitLE(header_offset+0x14,streamFile) > 0;
|
||||||
|
@ -172,6 +180,15 @@ VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||||
vgmstream->meta_type = meta_AKB;
|
vgmstream->meta_type = meta_AKB;
|
||||||
|
|
||||||
switch (codec) {
|
switch (codec) {
|
||||||
|
case 0x02: { /* msadpcm [The Irregular at Magic High School Lost Zero (Android)] */
|
||||||
|
if (encryption_flag) goto fail;
|
||||||
|
vgmstream->num_samples = read_32bitLE(extradata + 0x04, streamFile);
|
||||||
|
vgmstream->coding_type = coding_MSADPCM;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->interleave_block_size = read_16bitLE(extradata + 0x02, streamFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case 0x05: { /* ogg vorbis [The World Ends with You (iPhone / latest update)] */
|
case 0x05: { /* ogg vorbis [The World Ends with You (iPhone / latest update)] */
|
||||||
ffmpeg_codec_data *ffmpeg_data;
|
ffmpeg_codec_data *ffmpeg_data;
|
||||||
|
|
|
@ -82,9 +82,9 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
||||||
uint8_t buf[100];
|
uint8_t buf[100];
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
|
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
|
||||||
|
|
||||||
block_size = 0x98 * vgmstream->channels;
|
block_size = 0x98 * vgmstream->channels;
|
||||||
joint_stereo = 0;
|
joint_stereo = 0;
|
||||||
max_samples = (datasize / block_size) * 1024;
|
max_samples = atrac3_bytes_to_samples(datasize, block_size);;
|
||||||
encoder_delay = max_samples - vgmstream->num_samples; /* todo guessed */
|
encoder_delay = max_samples - vgmstream->num_samples; /* todo guessed */
|
||||||
|
|
||||||
vgmstream->num_samples += encoder_delay;
|
vgmstream->num_samples += encoder_delay;
|
||||||
|
@ -113,7 +113,7 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
|
||||||
if (!find_chunk_be(streamFileGSP, 0x584D4558,first_offset,1, &chunk_offset,NULL)) goto fail; /*"XMEX"*/
|
if (!find_chunk_be(streamFileGSP, 0x584D4558,first_offset,1, &chunk_offset,NULL)) goto fail; /*"XMEX"*/
|
||||||
/* 0x00: fmt0x166 header (BE), 0x34: seek table */
|
/* 0x00: fmt0x166 header (BE), 0x34: seek table */
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xma_from_fmt(buf,200, chunk_offset,0x34, datasize, streamFileGSP, 1);
|
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, datasize, streamFileGSP, 1);
|
||||||
if (bytes <= 0) goto fail;
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
|
||||||
|
|
|
@ -656,9 +656,9 @@ VGMSTREAM * init_vgmstream_btsnd(STREAMFILE* streamFile);
|
||||||
|
|
||||||
VGMSTREAM * init_vgmstream_ps2_svag_snk(STREAMFILE* streamFile);
|
VGMSTREAM * init_vgmstream_ps2_svag_snk(STREAMFILE* streamFile);
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
|
||||||
VGMSTREAM * init_vgmstream_xma(STREAMFILE* streamFile);
|
VGMSTREAM * init_vgmstream_xma(STREAMFILE* streamFile);
|
||||||
|
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
VGMSTREAM * init_vgmstream_bik(STREAMFILE* streamFile);
|
VGMSTREAM * init_vgmstream_bik(STREAMFILE* streamFile);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -676,4 +676,14 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile);
|
||||||
|
|
||||||
VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile);
|
VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE* streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_x360_nub(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile);
|
||||||
|
|
||||||
#endif /*_META_H*/
|
#endif /*_META_H*/
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "meta.h"
|
||||||
|
#include "../util.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* OGL - Shin'en custom Vorbis [Jett Rocket (Wii), FAST Racing NEO (WiiU)] */
|
||||||
|
VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
off_t start_offset;
|
||||||
|
size_t partial_file_size;
|
||||||
|
int loop_flag, channel_count, sample_rate;
|
||||||
|
uint32_t num_samples, loop_start_sample, loop_end_sample;
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
if (!check_extensions(streamFile,"ogl"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* OGL headers are very basic with no ID but libvorbis should reject garbage data anyway */
|
||||||
|
loop_flag = read_32bitLE(0x00,streamFile) > 0; /* absolute loop offset */
|
||||||
|
loop_start_sample = read_32bitLE(0x04,streamFile);
|
||||||
|
//loop_start_block = read_32bitLE(0x08,streamFile);
|
||||||
|
num_samples = read_32bitLE(0x0c,streamFile);
|
||||||
|
partial_file_size = read_32bitLE(0x10,streamFile); /* header + data not counting end padding */
|
||||||
|
if (partial_file_size > get_streamfile_size(streamFile)) goto fail;
|
||||||
|
loop_end_sample = num_samples; /* there is no data after num_samples (ie.- it's really num_samples) */
|
||||||
|
|
||||||
|
/* this is actually peeking into the Vorbis id packet */
|
||||||
|
channel_count = read_8bit (0x21,streamFile);
|
||||||
|
sample_rate = read_32bitLE(0x22,streamFile);
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = num_samples;
|
||||||
|
vgmstream->loop_start_sample = loop_start_sample;
|
||||||
|
vgmstream->loop_end_sample = loop_end_sample;
|
||||||
|
vgmstream->meta_type = meta_OGL;
|
||||||
|
|
||||||
|
#ifdef VGM_USE_VORBIS
|
||||||
|
{
|
||||||
|
vgmstream->codec_data = init_ogl_vorbis_codec_data(streamFile, 0x14, &start_offset);
|
||||||
|
if (!vgmstream->codec_data) goto fail;
|
||||||
|
vgmstream->coding_type = coding_ogl_vorbis;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* non-looping files do this */
|
||||||
|
if (!num_samples) {
|
||||||
|
uint32_t avg_bitrate = read_32bitLE(0x2a,streamFile); /* inside id packet */
|
||||||
|
/* approximate as we don't know the sizes of all packet headers */ //todo this is wrong... but somehow works?
|
||||||
|
vgmstream->num_samples = (partial_file_size - start_offset) * ((sample_rate*10/avg_bitrate)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open the file for reading */
|
||||||
|
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -104,12 +104,12 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||||
case 0x6: { /* ATRAC3 high (132 kbps, frame size 192) */
|
case 0x6: { /* ATRAC3 high (132 kbps, frame size 192) */
|
||||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||||
uint8_t buf[100];
|
uint8_t buf[100];
|
||||||
int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo, max_samples;
|
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
|
||||||
|
|
||||||
block_size = (codec_id==4 ? 0x60 : (codec_id==5 ? 0x98 : 0xC0)) * vgmstream->channels;
|
block_size = (codec_id==4 ? 0x60 : (codec_id==5 ? 0x98 : 0xC0)) * vgmstream->channels;
|
||||||
encoder_delay = 0x0; //todo MSF encoder delay (around 440-450*2)
|
encoder_delay = 0x0; //todo MSF encoder delay (around 440-450*2)
|
||||||
max_samples = (data_size / block_size) * samples_size;
|
max_samples = atrac3_bytes_to_samples(data_size, block_size);
|
||||||
joint_stereo = codec_id==4; /* interleaved joint stereo (ch must be even) */
|
joint_stereo = codec_id==4; /* interleaved joint stereo (ch must be even) */
|
||||||
|
|
||||||
if (vgmstream->sample_rate==0xFFFFFFFF) /* some MSFv1 (Digi World SP) */
|
if (vgmstream->sample_rate==0xFFFFFFFF) /* some MSFv1 (Digi World SP) */
|
||||||
vgmstream->sample_rate = 44100;//voice tracks seems to use 44khz, not sure about other tracks
|
vgmstream->sample_rate = 44100;//voice tracks seems to use 44khz, not sure about other tracks
|
||||||
|
@ -126,8 +126,8 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
vgmstream->num_samples = max_samples;
|
vgmstream->num_samples = max_samples;
|
||||||
if (loop_flag) {
|
if (loop_flag) {
|
||||||
vgmstream->loop_start_sample = (loop_start / block_size) * samples_size;
|
vgmstream->loop_start_sample = atrac3_bytes_to_samples(loop_start, block_size);
|
||||||
vgmstream->loop_end_sample = (loop_end / block_size) * samples_size;
|
vgmstream->loop_end_sample = atrac3_bytes_to_samples(loop_end, block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -227,8 +227,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||||
uint32_t riff_size;
|
uint32_t riff_size;
|
||||||
uint32_t data_size = 0;
|
uint32_t data_size = 0;
|
||||||
|
|
||||||
int FormatChunkFound = 0;
|
int FormatChunkFound = 0, DataChunkFound = 0, JunkFound = 0;
|
||||||
int DataChunkFound = 0;
|
|
||||||
|
|
||||||
/* Level-5 mwv */
|
/* Level-5 mwv */
|
||||||
int mwv = 0;
|
int mwv = 0;
|
||||||
|
@ -361,6 +360,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||||
fact_sample_skip = read_32bitLE(current_chunk+0x10, streamFile);
|
fact_sample_skip = read_32bitLE(current_chunk+0x10, streamFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x4A554E4B: /* JUNK */
|
||||||
|
JunkFound = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* ignorance is bliss */
|
/* ignorance is bliss */
|
||||||
|
@ -373,6 +375,12 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
if (!FormatChunkFound || !DataChunkFound) goto fail;
|
if (!FormatChunkFound || !DataChunkFound) goto fail;
|
||||||
|
|
||||||
|
/* JUNK is an optional Wwise chunk, and Wwise hijacks the MSADPCM/MS_IMA/XBOX IMA ids (how nice).
|
||||||
|
* To ensure their stuff is parsed in wwise.c we reject their JUNK, which they put almost always.
|
||||||
|
* As JUNK is legal (if unusual) we only reject those codecs.
|
||||||
|
* (ex. Cave PC games have PCM16LE + JUNK + smpl created by "Samplitude software") */
|
||||||
|
if (JunkFound && (fmt.coding_type==coding_MSADPCM || fmt.coding_type==coding_MS_IMA)) goto fail;
|
||||||
|
|
||||||
switch (fmt.coding_type) {
|
switch (fmt.coding_type) {
|
||||||
case coding_PCM16LE:
|
case coding_PCM16LE:
|
||||||
sample_count = data_size/2/fmt.channel_count;
|
sample_count = data_size/2/fmt.channel_count;
|
||||||
|
@ -611,8 +619,7 @@ VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) {
|
||||||
uint32_t riff_size;
|
uint32_t riff_size;
|
||||||
uint32_t data_size = 0;
|
uint32_t data_size = 0;
|
||||||
|
|
||||||
int FormatChunkFound = 0;
|
int FormatChunkFound = 0, DataChunkFound = 0, JunkFound = 0;
|
||||||
int DataChunkFound = 0;
|
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
/* check extension, case insensitive */
|
||||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||||
|
@ -687,6 +694,8 @@ VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) {
|
||||||
if (chunk_size != 4) break;
|
if (chunk_size != 4) break;
|
||||||
//fact_sample_count = read_32bitBE(current_chunk+8, streamFile);
|
//fact_sample_count = read_32bitBE(current_chunk+8, streamFile);
|
||||||
break;
|
break;
|
||||||
|
case 0x4A554E4B: /* JUNK */
|
||||||
|
JunkFound = 1;
|
||||||
default:
|
default:
|
||||||
/* ignorance is bliss */
|
/* ignorance is bliss */
|
||||||
break;
|
break;
|
||||||
|
@ -698,6 +707,12 @@ VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
if (!FormatChunkFound || !DataChunkFound) goto fail;
|
if (!FormatChunkFound || !DataChunkFound) goto fail;
|
||||||
|
|
||||||
|
/* JUNK is an optional Wwise chunk, and Wwise hijacks the MSADPCM/MS_IMA/XBOX IMA ids (how nice).
|
||||||
|
* To ensure their stuff is parsed in wwise.c we reject their JUNK, which they put almost always.
|
||||||
|
* As JUNK is legal (if unusual) we only reject those codecs.
|
||||||
|
* (ex. Cave PC games have PCM16LE + JUNK + smpl created by "Samplitude software") */
|
||||||
|
if (JunkFound && (fmt.coding_type==coding_MSADPCM || fmt.coding_type==coding_MS_IMA)) goto fail;
|
||||||
|
|
||||||
switch (fmt.coding_type) {
|
switch (fmt.coding_type) {
|
||||||
case coding_PCM16BE:
|
case coding_PCM16BE:
|
||||||
sample_count = data_size/2/fmt.channel_count;
|
sample_count = data_size/2/fmt.channel_count;
|
||||||
|
|
|
@ -358,7 +358,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
/* post_meta_offset+0x00: fmt0x166 header (BE), post_meta_offset+0x34: seek table */
|
/* post_meta_offset+0x00: fmt0x166 header (BE), post_meta_offset+0x34: seek table */
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xma_from_fmt(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1);
|
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1);
|
||||||
if (bytes <= 0) goto fail;
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
#include "meta.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* SXD - Sony's SDK format? (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */
|
||||||
|
VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
STREAMFILE * streamHeader = NULL;
|
||||||
|
off_t start_offset, chunk_offset, first_offset = 0x60;
|
||||||
|
|
||||||
|
int is_separate;
|
||||||
|
int loop_flag, channels, type;
|
||||||
|
int sample_rate, num_samples, loop_start_sample, loop_end_sample;
|
||||||
|
int target_stream = 0, total_streams;
|
||||||
|
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
/* .sxd: header+data (SXDF), .sxd1: header (SXDF) + .sxd2 = data (SXDS) */
|
||||||
|
if (!check_extensions(streamFile,"sxd,sxd2")) goto fail;
|
||||||
|
is_separate = !check_extensions(streamFile,"sxd");
|
||||||
|
|
||||||
|
/* sxd1+sxd2: use sxd1 as header; otherwise use the current file as header */
|
||||||
|
if (is_separate) {
|
||||||
|
if (read_32bitBE(0x00,streamFile) != 0x53584453) /* "SXDS" */
|
||||||
|
goto fail;
|
||||||
|
streamHeader = open_stream_ext(streamFile, "sxd1");
|
||||||
|
if (!streamHeader) goto fail;
|
||||||
|
} else {
|
||||||
|
streamHeader = streamFile;
|
||||||
|
}
|
||||||
|
if (read_32bitBE(0x00,streamHeader) != 0x53584446) /* "SXDF" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
/* typical chunks: NAME, WAVE and many control chunks (SXDs don't need to contain any sound data) */
|
||||||
|
/* WAVE chunk (0 + streams + 4*streams table + streams * variable? + optional padding) */
|
||||||
|
if (!find_chunk_le(streamHeader, 0x57415645,first_offset,0, &chunk_offset,NULL)) goto fail; /* "WAVE" */
|
||||||
|
|
||||||
|
/* check multi-streams (usually only in SFX containers) */
|
||||||
|
total_streams = read_32bitLE(chunk_offset+0x04,streamHeader);
|
||||||
|
if (target_stream == 0) target_stream = 1;
|
||||||
|
if (target_stream < 0 || target_stream > total_streams || total_streams < 1) goto fail;
|
||||||
|
|
||||||
|
/* read stream header */
|
||||||
|
{
|
||||||
|
off_t table_offset, header_offset, stream_offset, data_offset;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* get target offset using table of relative offsets within WAVE */
|
||||||
|
table_offset = chunk_offset + 0x08 + 4*(target_stream-1);
|
||||||
|
header_offset = table_offset + read_32bitLE(table_offset,streamHeader);
|
||||||
|
|
||||||
|
type = read_32bitLE(header_offset+0x00,streamHeader);
|
||||||
|
/* 0x04 (1): unk (HEVAG: 21, ATRAC9: 42 */
|
||||||
|
channels = read_8bit (header_offset+0x05,streamHeader);
|
||||||
|
sample_rate = read_32bitLE(header_offset+0x08,streamHeader);
|
||||||
|
/* 0x0c (4): unk size? */
|
||||||
|
/* 0x10 (4): ? + volume? + pan? (can be 0 for music) */
|
||||||
|
num_samples = read_32bitLE(header_offset+0x14,streamHeader);
|
||||||
|
loop_start_sample = read_32bitLE(header_offset+0x18,streamHeader);
|
||||||
|
loop_end_sample = read_32bitLE(header_offset+0x1c,streamHeader);
|
||||||
|
/* 0x20 (4): data size */
|
||||||
|
/* 0x24 (-): extra data, variable size and format dependant
|
||||||
|
(ATRAC9 can contain truncated part of the data, for preloading I guess) */
|
||||||
|
loop_flag = loop_start_sample != -1 && loop_end_sample != -1;
|
||||||
|
|
||||||
|
/* calc stream offset by reading stream sizes */
|
||||||
|
stream_offset = 0;
|
||||||
|
for (i = 0; i < total_streams; i++) {
|
||||||
|
off_t subtable_offset, subheader_offset;
|
||||||
|
if (i == target_stream-1) break;
|
||||||
|
|
||||||
|
subtable_offset = chunk_offset + 0x08 + 4*(i);
|
||||||
|
subheader_offset = subtable_offset + read_32bitLE(subtable_offset,streamHeader);
|
||||||
|
stream_offset += read_32bitLE(subheader_offset+0x20,streamHeader); /* data size */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_separate) {
|
||||||
|
data_offset = first_offset;
|
||||||
|
} else {
|
||||||
|
if (!find_chunk_le(streamHeader, 0x44415441,first_offset,0, &data_offset,NULL)) goto fail; /* "DATA" */
|
||||||
|
data_offset += 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_offset = data_offset + stream_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channels,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = num_samples;
|
||||||
|
vgmstream->loop_start_sample = loop_start_sample;
|
||||||
|
vgmstream->loop_end_sample = loop_end_sample;
|
||||||
|
vgmstream->num_streams = total_streams;
|
||||||
|
vgmstream->meta_type = meta_SXD;
|
||||||
|
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 0x01: /* HEVAG */
|
||||||
|
vgmstream->coding_type = coding_HEVAG;
|
||||||
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = 0x10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03: /* ATRAC9 */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
default:
|
||||||
|
VGM_LOG("SXD: unknown codec %i", type);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* open the file for reading */
|
||||||
|
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (is_separate && streamHeader) close_streamfile(streamHeader);
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (is_separate && streamHeader) close_streamfile(streamHeader);
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -1,20 +1,17 @@
|
||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
#include "../coding/coding.h"
|
#include "../coding/coding.h"
|
||||||
#include "../layout/layout.h"
|
|
||||||
#include "../util.h"
|
|
||||||
|
|
||||||
/* Ubisoft CKD (Rayman Origins - Wii) */
|
|
||||||
|
/* CKD RIFF - Ubisoft audio [Rayman Origins (Wii)] */
|
||||||
VGMSTREAM * init_vgmstream_ubi_ckd(STREAMFILE *streamFile) {
|
VGMSTREAM * init_vgmstream_ubi_ckd(STREAMFILE *streamFile) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM * vgmstream = NULL;
|
||||||
char filename[PATH_LIMIT];
|
off_t start_offset, first_offset = 0xc, chunk_offset;
|
||||||
off_t start_offset;
|
size_t chunk_size, data_size;
|
||||||
|
int loop_flag, channel_count, interleave;
|
||||||
|
|
||||||
int loop_flag;
|
|
||||||
int channel_count;
|
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
/* check extension, case insensitive */
|
||||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
if (!check_extensions(streamFile,"ckd")) goto fail;
|
||||||
if (strcasecmp("ckd",filename_extension(filename))) goto fail;
|
|
||||||
|
|
||||||
/* check header */
|
/* check header */
|
||||||
if (read_32bitBE(0x0,streamFile) != 0x52494646) /* RIFF */
|
if (read_32bitBE(0x0,streamFile) != 0x52494646) /* RIFF */
|
||||||
|
@ -25,61 +22,43 @@ VGMSTREAM * init_vgmstream_ubi_ckd(STREAMFILE *streamFile) {
|
||||||
loop_flag = 0;
|
loop_flag = 0;
|
||||||
channel_count = read_16bitBE(0x16,streamFile);
|
channel_count = read_16bitBE(0x16,streamFile);
|
||||||
|
|
||||||
/* build the VGMSTREAM */
|
/* find data chunk, in 3 variants */
|
||||||
|
if (find_chunk_be(streamFile, 0x64617453,first_offset,0, &chunk_offset,&chunk_size)) { /*"datS"*/
|
||||||
|
/* normal interleave */
|
||||||
|
start_offset = chunk_offset;
|
||||||
|
data_size = chunk_size;
|
||||||
|
interleave = 8;
|
||||||
|
} else if (find_chunk_be(streamFile, 0x6461744C,first_offset,0, &chunk_offset,&chunk_size)) { /*"datL"*/
|
||||||
|
/* mono or full interleave (with a "datR" after the "datL", no check as we can just pretend it exists) */
|
||||||
|
start_offset = chunk_offset;
|
||||||
|
data_size = chunk_size * channel_count;
|
||||||
|
interleave = (4+4) + chunk_size; /* don't forget to skip the "datR"+size chunk */
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
/* fill in the vital statistics */
|
|
||||||
if (read_16bitBE(0x16,streamFile) == 1) {
|
|
||||||
start_offset = 0x96;
|
|
||||||
vgmstream->num_samples = (read_32bitBE(0x92,streamFile))*28/16/channel_count;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
start_offset = 0xFE;
|
|
||||||
vgmstream->num_samples = (read_32bitBE(0xFA,streamFile))*28/16/channel_count;
|
|
||||||
}
|
|
||||||
vgmstream->channels = channel_count;
|
|
||||||
vgmstream->sample_rate = read_32bitBE(0x18,streamFile);
|
vgmstream->sample_rate = read_32bitBE(0x18,streamFile);
|
||||||
vgmstream->coding_type = coding_NGC_DSP;
|
vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count);
|
||||||
vgmstream->num_samples = (read_32bitBE(0xFA,streamFile))*28/16/channel_count;
|
|
||||||
|
|
||||||
vgmstream->layout_type = layout_interleave;
|
vgmstream->coding_type = coding_NGC_DSP;
|
||||||
vgmstream->interleave_block_size = 8;
|
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = interleave;
|
||||||
vgmstream->meta_type = meta_UBI_CKD;
|
vgmstream->meta_type = meta_UBI_CKD;
|
||||||
|
|
||||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
dsp_read_coefs_be(vgmstream,streamFile, 0x4A, (4+4)+0x60);
|
||||||
int i;
|
|
||||||
for (i=0;i<16;i++) {
|
|
||||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x4A+i*2,streamFile);
|
|
||||||
}
|
|
||||||
if (vgmstream->channels) {
|
|
||||||
for (i=0;i<16;i++) {
|
|
||||||
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xB2+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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||||
|
goto fail;
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
/* clean up anything we may have opened */
|
close_vgmstream(vgmstream);
|
||||||
if (vgmstream) close_vgmstream(vgmstream);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* RAKI - Ubisoft audio format [Rayman Legends, Just Dance 2017 (multi)] */
|
||||||
|
VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
off_t start_offset, off, fmt_offset;
|
||||||
|
size_t header_size, data_size;
|
||||||
|
int little_endian;
|
||||||
|
int loop_flag, channel_count, block_align, bits_per_sample;
|
||||||
|
uint32_t platform, type;
|
||||||
|
|
||||||
|
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||||
|
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* basic checks */
|
||||||
|
/* .rak: Just Dance 2017; .ckd: Rayman Legends (technically .wav.ckd/rak) */
|
||||||
|
if (!check_extensions(streamFile,"rak,ckd")) goto fail;
|
||||||
|
|
||||||
|
/* some games (ex. Rayman Legends PS3) have a 32b file type before the RAKI data. However
|
||||||
|
* offsets are absolute and expect the type exists, so it's part of the file and not an extraction defect. */
|
||||||
|
if ((read_32bitBE(0x00,streamFile) == 0x52414B49)) /* "RAKI" */
|
||||||
|
off = 0x0;
|
||||||
|
else if ((read_32bitBE(0x04,streamFile) == 0x52414B49)) /* type varies between platforms (0x09, 0x0b) so ignore */
|
||||||
|
off = 0x4;
|
||||||
|
else
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* endianness is given with the platform field, but this is more versatile */
|
||||||
|
little_endian = read_32bitBE(off+0x10,streamFile) > 0x00ffffff;
|
||||||
|
if (little_endian) {
|
||||||
|
read_32bit = read_32bitLE;
|
||||||
|
read_16bit = read_16bitLE;
|
||||||
|
} else {
|
||||||
|
read_32bit = read_32bitBE;
|
||||||
|
read_16bit = read_16bitBE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 0x04: version? (0x00, 0x07, 0x0a, etc); */
|
||||||
|
platform = read_32bitBE(off+0x08,streamFile); /* string */
|
||||||
|
type = read_32bitBE(off+0x0c,streamFile); /* string */
|
||||||
|
header_size = read_32bit(off+0x10,streamFile);
|
||||||
|
start_offset = read_32bit(off+0x14,streamFile);
|
||||||
|
/* 0x18: number of chunks */
|
||||||
|
/* 0x1c: unk */
|
||||||
|
|
||||||
|
/* The first chunk is always "fmt" and points to a RIFF "fmt" chunk (even for WiiU or PS3) */
|
||||||
|
if (read_32bitBE(off+0x20,streamFile) != 0x666D7420) goto fail; /*"fmt "*/
|
||||||
|
fmt_offset = read_32bit(off+0x24,streamFile);
|
||||||
|
//fmt_size = read_32bit(off+0x28,streamFile);
|
||||||
|
|
||||||
|
loop_flag = 0; /* not seen */
|
||||||
|
channel_count = read_16bit(fmt_offset+0x2,streamFile);
|
||||||
|
block_align = read_16bit(fmt_offset+0xc,streamFile);
|
||||||
|
bits_per_sample = read_16bit(fmt_offset+0xe,streamFile);
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = read_32bit(fmt_offset+0x4,streamFile);
|
||||||
|
vgmstream->meta_type = meta_UBI_RAKI;
|
||||||
|
|
||||||
|
/* codecs have a "data" or equivalent chunk with the size/start_offset, but always agree with this */
|
||||||
|
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||||
|
|
||||||
|
/* parse compound codec to simplify */
|
||||||
|
switch(((uint64_t)platform << 32) | type) {
|
||||||
|
|
||||||
|
case 0x57696E2070636D20: /* "Win pcm " */
|
||||||
|
/* chunks: "data" */
|
||||||
|
vgmstream->coding_type = little_endian ? coding_PCM16LE : coding_PCM16BE;
|
||||||
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = block_align;
|
||||||
|
|
||||||
|
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, bits_per_sample);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x57696E2061647063: /* "Win adpc" */
|
||||||
|
/* chunks: "data" */
|
||||||
|
vgmstream->coding_type = coding_MSADPCM;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->interleave_block_size = block_align;
|
||||||
|
|
||||||
|
vgmstream->num_samples = msadpcm_bytes_to_samples(data_size, vgmstream->interleave_block_size, channel_count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x5769692061647063: /* "Wii adpc" */
|
||||||
|
case 0x4361666561647063: /* "Cafeadpc" (WiiU) */
|
||||||
|
/* chunks: "datS" (stereo), "datL" (mono or full interleave), "datR" (full interleave), "data" equivalents */
|
||||||
|
vgmstream->coding_type = coding_NGC_DSP;
|
||||||
|
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = 8;
|
||||||
|
|
||||||
|
/* we need to know if the file uses "datL" and is full-interleave */
|
||||||
|
if (channel_count > 1) {
|
||||||
|
off_t chunk_off = off+ 0x20 + 0xc; /* after "fmt" */
|
||||||
|
while (chunk_off < header_size) {
|
||||||
|
if (read_32bitBE(chunk_off,streamFile) == 0x6461744C) { /*"datL" found */
|
||||||
|
size_t chunk_size = read_32bit(chunk_off+0x8,streamFile);
|
||||||
|
data_size = chunk_size * channel_count; /* to avoid counting the "datR" chunk */
|
||||||
|
vgmstream->interleave_block_size = (4+4) + chunk_size; /* don't forget to skip the "datR"+size chunk */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chunk_off += 0xc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found? probably "datS" (regular stereo interleave) */
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* get coef offsets; could check "dspL" and "dspR" chunks after "fmt " better but whatevs (only "dspL" if mono) */
|
||||||
|
off_t dsp_coefs = read_32bitBE(off+0x30,streamFile); /* after "dspL"; spacing is consistent but could vary */
|
||||||
|
dsp_read_coefs(vgmstream,streamFile, dsp_coefs+0x1c, 0x60, !little_endian);
|
||||||
|
/* dsp_coefs + 0x00-0x1c: ? (special coefs or adpcm history?) */
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef VGM_USE_MPEG
|
||||||
|
case 0x505333206D703320: { /* "PS3 mp3 " */
|
||||||
|
/* chunks: "MARK" optional seek table), "STRG" (optional description), "Msf " ("data" equivalent) */
|
||||||
|
vgmstream->codec_data = init_mpeg_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels);
|
||||||
|
if (!vgmstream->codec_data) goto fail;
|
||||||
|
vgmstream->layout_type = layout_mpeg;
|
||||||
|
|
||||||
|
vgmstream->num_samples = mpeg_bytes_to_samples(data_size, vgmstream->codec_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
case 0x58333630786D6132: { /* "X360xma2" */
|
||||||
|
/* chunks: "seek" (XMA2 seek table), "data" */
|
||||||
|
uint8_t buf[100];
|
||||||
|
int bytes, block_count;
|
||||||
|
|
||||||
|
block_count = data_size / block_align + (data_size % block_align ? 1 : 0);
|
||||||
|
bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_align);
|
||||||
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
||||||
|
if ( !vgmstream->codec_data ) goto fail;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
vgmstream->num_samples = read_32bit(fmt_offset+0x18,streamFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 0x5649544161743920: /*"VITAat9 "*/
|
||||||
|
/* chunks: "fact" (equivalent to a RIFF "fact", num_samples + skip_samples), "data" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
default:
|
||||||
|
VGM_LOG("RAKI: unknown platform %x and type %x\n", platform, type);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -75,33 +75,30 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case 7: { /* ATRAC3 */
|
case 7: { /* ATRAC3 */
|
||||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
|
||||||
uint8_t buf[FAKE_RIFF_BUFFER_SIZE];
|
uint8_t buf[FAKE_RIFF_BUFFER_SIZE];
|
||||||
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
|
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
|
||||||
|
|
||||||
datasize = read_32bitBE(0x54,streamFile);
|
datasize = read_32bitBE(0x54,streamFile);
|
||||||
block_size = 0x98 * vgmstream->channels;
|
block_size = 0x98 * vgmstream->channels;
|
||||||
joint_stereo = 0;
|
joint_stereo = 0;
|
||||||
max_samples = (datasize / block_size) * 1024;
|
max_samples = atrac3_bytes_to_samples(datasize, block_size);
|
||||||
encoder_delay = 0x0; /* not used by FFmpeg */
|
encoder_delay = 0x0; //max_samples - vgmstream->num_samples; /* todo not correct */
|
||||||
if (vgmstream->num_samples > max_samples) {
|
vgmstream->num_samples = max_samples; /* use calc samples since loop points are too, breaks looping in some files otherwise */
|
||||||
vgmstream->num_samples = max_samples;
|
|
||||||
/*encoder_delay = ?; */ /* todo some tracks need it to skip garbage but not sure how to calculate it */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make a fake riff so FFmpeg can parse the ATRAC3 */
|
/* make a fake riff so FFmpeg can parse the ATRAC3 */
|
||||||
bytes = ffmpeg_make_riff_atrac3(buf, FAKE_RIFF_BUFFER_SIZE, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
bytes = ffmpeg_make_riff_atrac3(buf, FAKE_RIFF_BUFFER_SIZE, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
|
||||||
if (bytes <= 0)
|
if (bytes <= 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
|
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
|
||||||
if ( !ffmpeg_data ) goto fail;
|
if (!vgmstream->codec_data) goto fail;
|
||||||
vgmstream->codec_data = ffmpeg_data;
|
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
vgmstream->loop_start_sample = (read_32bitBE(0x44,streamFile) / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize;
|
vgmstream->loop_start_sample = atrac3_bytes_to_samples(read_32bitBE(0x44,streamFile), block_size);
|
||||||
vgmstream->loop_end_sample = (read_32bitBE(0x48,streamFile) / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize;
|
vgmstream->loop_end_sample = atrac3_bytes_to_samples(read_32bitBE(0x48,streamFile), block_size);
|
||||||
|
//vgmstream->loop_start_sample -= encoder_delay;
|
||||||
|
//vgmstream->loop_end_sample -= encoder_delay;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
|
@ -12,6 +12,7 @@ typedef enum { PCM, IMA, VORBIS, DSP, XMA2, XWMA, AAC, HEVAG, ATRAC9 } wwise_cod
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int big_endian;
|
int big_endian;
|
||||||
size_t file_size;
|
size_t file_size;
|
||||||
|
int truncated;
|
||||||
|
|
||||||
/* chunks references */
|
/* chunks references */
|
||||||
off_t fmt_offset;
|
off_t fmt_offset;
|
||||||
|
@ -25,13 +26,14 @@ typedef struct {
|
||||||
int channels;
|
int channels;
|
||||||
int sample_rate;
|
int sample_rate;
|
||||||
int block_align;
|
int block_align;
|
||||||
int bit_per_sample;
|
int average_bps;
|
||||||
|
int bits_per_sample;
|
||||||
size_t extra_size;
|
size_t extra_size;
|
||||||
|
|
||||||
|
int32_t num_samples;
|
||||||
int loop_flag;
|
int loop_flag;
|
||||||
uint32_t num_samples;
|
int32_t loop_start_sample;
|
||||||
uint32_t loop_start_sample;
|
int32_t loop_end_sample;
|
||||||
uint32_t loop_end_sample;
|
|
||||||
} wwise_header;
|
} wwise_header;
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,13 +47,14 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
/* basic checks */
|
/* basic checks */
|
||||||
/* .wem (Wwise Encoded Media) is "newer Wwise", used after the 2011.2 SDK (~july)
|
/* .wem (Wwise Encoded Media) is "newer Wwise", used after the 2011.2 SDK (~july)
|
||||||
* .wav (ex. Shadowrun X360) and .ogg (ex. KOF XII X360) are used only in older Wwise */
|
* .wav (ex. Shadowrun X360) and .ogg (ex. KOF XII X360), .xma (ex. Tron Evolution X360) are used in older Wwise */
|
||||||
if (!check_extensions(streamFile,"wem,wav,lwav,ogg,logg")) goto fail; /* .xma may be possible? */
|
if (!check_extensions(streamFile,"wem,wav,lwav,ogg,logg,xma")) goto fail;
|
||||||
|
|
||||||
if ((read_32bitBE(0x00,streamFile) != 0x52494646) && /* "RIFF" (LE) */
|
if ((read_32bitBE(0x00,streamFile) != 0x52494646) && /* "RIFF" (LE) */
|
||||||
(read_32bitBE(0x00,streamFile) != 0x52494658)) /* "RIFX" (BE) */
|
(read_32bitBE(0x00,streamFile) != 0x52494658)) /* "RIFX" (BE) */
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((read_32bitBE(0x08,streamFile) != 0x57415645)) /* "WAVE" */
|
if ((read_32bitBE(0x08,streamFile) != 0x57415645) && /* "WAVE" */
|
||||||
|
(read_32bitBE(0x08,streamFile) != 0x58574D41)) /* "XWMA" */
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
memset(&ww,0,sizeof(wwise_header));
|
memset(&ww,0,sizeof(wwise_header));
|
||||||
|
@ -68,7 +71,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
ww.file_size = streamFile->get_size(streamFile);
|
ww.file_size = streamFile->get_size(streamFile);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* sometimes uses a RIFF size that doesn't count chunk/sizes, or just wrong...? */
|
/* sometimes uses a RIFF size that doesn't count chunks/sizes, has LE size in RIFX, or is just wrong...? */
|
||||||
if (4+4+read_32bit(0x04,streamFile) != ww.file_size) {
|
if (4+4+read_32bit(0x04,streamFile) != ww.file_size) {
|
||||||
VGM_LOG("WWISE: bad riff size (real=0x%x vs riff=0x%x)\n", 4+4+read_32bit(0x04,streamFile), ww.file_size);
|
VGM_LOG("WWISE: bad riff size (real=0x%x vs riff=0x%x)\n", 4+4+read_32bit(0x04,streamFile), ww.file_size);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -76,7 +79,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* parse WAVEFORMATEX (roughly spec-compliant but some massaging is needed) */
|
/* parse format (roughly spec-compliant but some massaging is needed) */
|
||||||
{
|
{
|
||||||
off_t loop_offset;
|
off_t loop_offset;
|
||||||
size_t loop_size;
|
size_t loop_size;
|
||||||
|
@ -85,29 +88,32 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
if (!find_chunk(streamFile, 0x666d7420,first_offset,0, &ww.fmt_offset,&ww.fmt_size, ww.big_endian, 0)) goto fail; /*"fmt "*/
|
if (!find_chunk(streamFile, 0x666d7420,first_offset,0, &ww.fmt_offset,&ww.fmt_size, ww.big_endian, 0)) goto fail; /*"fmt "*/
|
||||||
if (!find_chunk(streamFile, 0x64617461,first_offset,0, &ww.data_offset,&ww.data_size, ww.big_endian, 0)) goto fail; /*"data"*/
|
if (!find_chunk(streamFile, 0x64617461,first_offset,0, &ww.data_offset,&ww.data_size, ww.big_endian, 0)) goto fail; /*"data"*/
|
||||||
|
|
||||||
if (ww.data_size > ww.file_size) {
|
|
||||||
VGM_LOG("WWISE: bad data size (real=0x%x > riff=0x%x)\n", ww.data_size, ww.file_size);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* base fmt */
|
/* base fmt */
|
||||||
if (ww.fmt_size < 0x12) goto fail;
|
if (ww.fmt_size < 0x12) goto fail;
|
||||||
ww.format = (uint16_t)read_16bit(ww.fmt_offset+0x00,streamFile);
|
ww.format = (uint16_t)read_16bit(ww.fmt_offset+0x00,streamFile);
|
||||||
ww.channels = read_16bit(ww.fmt_offset+0x02,streamFile);
|
|
||||||
ww.sample_rate = read_32bit(ww.fmt_offset+0x04,streamFile);
|
|
||||||
/* 0x08: average samples per second */
|
|
||||||
ww.block_align = (uint16_t)read_16bit(ww.fmt_offset+0x0c,streamFile);
|
|
||||||
ww.bit_per_sample = (uint16_t)read_16bit(ww.fmt_offset+0x0e,streamFile);
|
|
||||||
if (ww.fmt_size > 0x10 && ww.format != 0x0165 && ww.format != 0x0166) /* ignore XMAWAVEFORMAT */
|
|
||||||
ww.extra_size = (uint16_t)read_16bit(ww.fmt_offset+0x10,streamFile);
|
|
||||||
#if 0
|
|
||||||
/* channel bitmask, see AkSpeakerConfig.h (ex. 1ch uses FRONT_CENTER 0x4, 2ch FRONT_LEFT 0x1 | FRONT_RIGHT 0x2) */
|
|
||||||
if (ww.extra_size >= 6)
|
|
||||||
ww.channel_config = read_32bit(ww.fmt_offset+0x14,streamFile);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* find loop info (both used in early and late Wwise and seem to follow the spec) */
|
if (ww.format == 0x0165) { /* XMA2WAVEFORMAT (always "fmt"+"XMA2", unlike .xma that may only have "XMA2") */
|
||||||
if (find_chunk(streamFile, 0x736D706C,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"smpl"*/
|
off_t xma2_offset;
|
||||||
|
if (!find_chunk(streamFile, 0x584D4132,first_offset,0, &xma2_offset,NULL, ww.big_endian, 0)) goto fail;
|
||||||
|
xma2_parse_xma2_chunk(streamFile, xma2_offset,&ww.channels,&ww.sample_rate, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample);
|
||||||
|
} else { /* WAVEFORMATEX */
|
||||||
|
ww.channels = read_16bit(ww.fmt_offset+0x02,streamFile);
|
||||||
|
ww.sample_rate = read_32bit(ww.fmt_offset+0x04,streamFile);
|
||||||
|
ww.average_bps = read_32bit(ww.fmt_offset+0x08,streamFile);/* bytes per sec */
|
||||||
|
ww.block_align = (uint16_t)read_16bit(ww.fmt_offset+0x0c,streamFile);
|
||||||
|
ww.bits_per_sample = (uint16_t)read_16bit(ww.fmt_offset+0x0e,streamFile);
|
||||||
|
if (ww.fmt_size > 0x10 && ww.format != 0x0165 && ww.format != 0x0166) /* ignore XMAWAVEFORMAT */
|
||||||
|
ww.extra_size = (uint16_t)read_16bit(ww.fmt_offset+0x10,streamFile);
|
||||||
|
/* channel bitmask, see AkSpeakerConfig.h (ex. 1ch uses FRONT_CENTER 0x4, 2ch FRONT_LEFT 0x1 | FRONT_RIGHT 0x2, etc) */
|
||||||
|
//if (ww.extra_size >= 6)
|
||||||
|
// ww.channel_config = read_32bit(ww.fmt_offset+0x14,streamFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find loop info */
|
||||||
|
if (ww.format == 0x0166) { /* XMA2WAVEFORMATEX */
|
||||||
|
xma2_parse_fmt_chunk_extra(streamFile, ww.fmt_offset, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample, ww.big_endian);
|
||||||
|
}
|
||||||
|
else if (find_chunk(streamFile, 0x736D706C,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"smpl". common */
|
||||||
if (loop_size >= 0x34
|
if (loop_size >= 0x34
|
||||||
&& read_32bit(loop_offset+0x1c, streamFile)==1 /*loop count*/
|
&& read_32bit(loop_offset+0x1c, streamFile)==1 /*loop count*/
|
||||||
&& read_32bit(loop_offset+0x24+4, streamFile)==0) {
|
&& read_32bit(loop_offset+0x24+4, streamFile)==0) {
|
||||||
|
@ -116,28 +122,31 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
ww.loop_end_sample = read_32bit(loop_offset+0x24+0xc,streamFile);
|
ww.loop_end_sample = read_32bit(loop_offset+0x24+0xc,streamFile);
|
||||||
//todo fix repeat looping
|
//todo fix repeat looping
|
||||||
}
|
}
|
||||||
} else if (find_chunk(streamFile, 0x4C495354,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"LIST"*/
|
}
|
||||||
|
else if (find_chunk(streamFile, 0x4C495354,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"LIST", common */
|
||||||
//todo parse "adtl" (does it ever contain loop info in Wwise?)
|
//todo parse "adtl" (does it ever contain loop info in Wwise?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* other Wwise specific: */
|
/* other Wwise specific: */
|
||||||
//"JUNK": optional padding so that raw data starts in an offset multiple of 0x10 (0-size JUNK exists)
|
//"JUNK": optional padding so that raw data starts in an offset multiple of 0x10 (0-size JUNK exists too)
|
||||||
//"akd ": unknown (IMA/PCM; "audiokinetic data"?)
|
//"akd ": unknown (IMA/PCM; "audiokinetic data"?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* format to codec */
|
/* format to codec */
|
||||||
switch(ww.format) {
|
switch(ww.format) {
|
||||||
case 0x0001: ww.codec = PCM; break; /* older Wwise */
|
case 0x0001: ww.codec = PCM; break; /* older Wwise */
|
||||||
case 0x0002: ww.codec = IMA; break; /* newer Wwise (conflicts with MSADPCM) */
|
case 0x0002: ww.codec = IMA; break; /* newer Wwise (conflicts with MSADPCM, probably means "platform's ADPCM") */
|
||||||
case 0x0011: ww.codec = IMA; break; /* older Wwise */
|
//case 0x0011: ww.codec = IMA; break; /* older Wwise (used?) */
|
||||||
case 0x0069: ww.codec = IMA; break; /* older Wwise */
|
case 0x0069: ww.codec = IMA; break; /* older Wwise (Spiderman Web of Shadows X360, LotR Conquest PC) */
|
||||||
case 0x0165: ww.codec = XMA2; break;
|
case 0x0161: ww.codec = XWMA; break;
|
||||||
|
case 0x0162: ww.codec = XWMA; break;
|
||||||
|
case 0x0165: ww.codec = XMA2; break; /* always with the "XMA2" chunk, Wwise doesn't use XMA1 */
|
||||||
case 0x0166: ww.codec = XMA2; break;
|
case 0x0166: ww.codec = XMA2; break;
|
||||||
case 0xAAC0: ww.codec = AAC; break;
|
case 0xAAC0: ww.codec = AAC; break;
|
||||||
case 0xFFF0: ww.codec = DSP; break;
|
case 0xFFF0: ww.codec = DSP; break;
|
||||||
case 0xFFFB: ww.codec = HEVAG; break;
|
case 0xFFFB: ww.codec = HEVAG; break;
|
||||||
case 0xFFFC: ww.codec = ATRAC9; break;
|
case 0xFFFC: ww.codec = ATRAC9; break;
|
||||||
case 0xFFFE: ww.codec = PCM; break; /* newer Wwise ("PCM for Wwise Authoring") (conflicts with WAVEFORMATEXTENSIBLE) */
|
case 0xFFFE: ww.codec = PCM; break; /* "PCM for Wwise Authoring" */
|
||||||
case 0xFFFF: ww.codec = VORBIS; break;
|
case 0xFFFF: ww.codec = VORBIS; break;
|
||||||
default:
|
default:
|
||||||
VGM_LOG("WWISE: unknown codec 0x%x \n", ww.format);
|
VGM_LOG("WWISE: unknown codec 0x%x \n", ww.format);
|
||||||
|
@ -148,13 +157,23 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
ww.codec = DSP;
|
ww.codec = DSP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Some Wwise files (ex. Oddworld PSV, Bayonetta 2 WiiU sfx) are truncated mirrors of another file.
|
||||||
|
* They come in RAM banks, probably to play the beginning while the rest of the real stream loads.
|
||||||
|
* We'll add basic support to avoid complaints of this or that .wem not playing */
|
||||||
|
if (ww.data_size > ww.file_size) {
|
||||||
|
//VGM_LOG("WWISE: truncated data size (prefetch): (real=0x%x > riff=0x%x)\n", ww.data_size, ww.file_size);
|
||||||
|
if (ww.codec == IMA || ww.codec == VORBIS) /* only seen those, probably others exist */
|
||||||
|
ww.truncated = 1;
|
||||||
|
else
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* build the VGMSTREAM */
|
/* build the VGMSTREAM */
|
||||||
vgmstream = allocate_vgmstream(ww.channels,ww.loop_flag);
|
vgmstream = allocate_vgmstream(ww.channels,ww.loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
vgmstream->sample_rate = ww.sample_rate;
|
vgmstream->sample_rate = ww.sample_rate;
|
||||||
vgmstream->num_samples = ww.num_samples;
|
|
||||||
vgmstream->loop_start_sample = ww.loop_start_sample;
|
vgmstream->loop_start_sample = ww.loop_start_sample;
|
||||||
vgmstream->loop_end_sample = ww.loop_end_sample;
|
vgmstream->loop_end_sample = ww.loop_end_sample;
|
||||||
vgmstream->meta_type = meta_WWISE_RIFF;
|
vgmstream->meta_type = meta_WWISE_RIFF;
|
||||||
|
@ -164,93 +183,172 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
switch(ww.codec) {
|
switch(ww.codec) {
|
||||||
case PCM: /* common */
|
case PCM: /* common */
|
||||||
/* normally riff.c has priority but it's needed when .wem is used */
|
/* normally riff.c has priority but it's needed when .wem is used */
|
||||||
if (ww.bit_per_sample != 16) goto fail;
|
if (ww.bits_per_sample != 16) goto fail;
|
||||||
|
|
||||||
vgmstream->coding_type = (ww.big_endian ? coding_PCM16BE : coding_PCM16LE);
|
vgmstream->coding_type = (ww.big_endian ? coding_PCM16BE : coding_PCM16LE);
|
||||||
vgmstream->layout_type = ww.channels > 1 ? layout_interleave : layout_none;
|
vgmstream->layout_type = ww.channels > 1 ? layout_interleave : layout_none;
|
||||||
vgmstream->interleave_block_size = 0x02;
|
vgmstream->interleave_block_size = 0x02;
|
||||||
|
|
||||||
vgmstream->num_samples = ww.data_size / ww.channels / (ww.bit_per_sample/8);
|
vgmstream->num_samples = pcm_bytes_to_samples(ww.data_size, ww.channels, ww.bits_per_sample);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IMA: /* common */
|
case IMA: /* common */
|
||||||
/* slightly modified MS-IMA.
|
/* slightly modified MS IMA with interleaved sub-blocks and LE/BE header */
|
||||||
* Original research by hcs in ima_rejigger (https://github.com/hcs64/vgm_ripping/tree/master/demux/ima_rejigger5) */
|
|
||||||
#if 0
|
/* Wwise uses common codecs (ex. 0x0002 MSADPCM) so this parser should go AFTER riff.c avoid misdetection */
|
||||||
if (ww.bit_per_sample != 4) goto fail;
|
|
||||||
|
if (ww.bits_per_sample != 4) goto fail;
|
||||||
vgmstream->coding_type = coding_WWISE_IMA;
|
vgmstream->coding_type = coding_WWISE_IMA;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
vgmstream->interleave_block_size = ww.block_align;
|
vgmstream->interleave_block_size = ww.block_align;
|
||||||
|
vgmstream->codec_endian = ww.big_endian;
|
||||||
|
|
||||||
vgmstream->num_samples = (ww.data_size / ww.block_align) * (ww.block_align - 4 * vgmstream->channels) * 2 /vgmstream->channels;
|
if (ww.truncated) /* enough to get real samples */
|
||||||
|
ww.data_size = ww.file_size - ww.data_offset;
|
||||||
|
|
||||||
|
vgmstream->num_samples = ms_ima_bytes_to_samples(ww.data_size, ww.block_align, ww.channels);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
VGM_LOG("WWISE: IMA found (unsupported)\n");
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
case VORBIS: { /* common */
|
case VORBIS: { /* common */
|
||||||
/* Wwise uses custom Vorbis, which changed over time (config must be detected to pass to the decoder).
|
/* Wwise uses custom Vorbis, which changed over time (config must be detected to pass to the decoder). */
|
||||||
* Original research by hcs in ww2ogg (https://github.com/hcs64/ww2ogg) */
|
off_t vorb_offset, data_offsets, block_offsets;
|
||||||
#if 0
|
size_t vorb_size, setup_offset, audio_offset;
|
||||||
off_t vorb_offset;
|
|
||||||
size_t vorb_size;
|
|
||||||
|
|
||||||
int packet_header_type = 0; /* 1 = size 8 (4-granule + 4-size), 2 = size 6 (4-granule + 2-size) or 3 = size 2 (2-size) */
|
wwise_setup_type setup_type;
|
||||||
int packet_type = 0; /* 1 = standard, 2 = modified vorbis packets */
|
wwise_header_type header_type;
|
||||||
int setup_type = 0; /* 1: triad, 2 = inline codebooks, 3 = external codebooks, 4 = external aoTuV codebooks */
|
wwise_packet_type packet_type;
|
||||||
int blocksize_0_pow = 0, blocksize_1_pow = 0;
|
int blocksize_0_exp = 0, blocksize_1_exp = 0;
|
||||||
|
|
||||||
if (ww.block_align != 0 || ww.bit_per_sample != 0) goto fail;
|
if (ww.block_align != 0 || ww.bits_per_sample != 0) goto fail; /* always 0 for Worbis */
|
||||||
|
|
||||||
/* autodetect format */
|
/* autodetect format (field are mostly common, see the end of the file) */
|
||||||
if (find_chunk(streamFile, 0x766F7262,first_offset,0, &vorb_offset,&vorb_size, ww.big_endian, 0)) { /*"vorb"*/
|
if (find_chunk(streamFile, 0x766F7262,first_offset,0, &vorb_offset,&vorb_size, ww.big_endian, 0)) { /*"vorb"*/
|
||||||
/* older Wwise (~2011) */
|
/* older Wwise (~<2012) */
|
||||||
switch (vorb_size) {
|
|
||||||
case 0x28:
|
switch(vorb_size) {
|
||||||
case 0x2A:
|
//case 0x2C: /* early (~2009), some EVE Online Apocrypha files? */
|
||||||
case 0x2C:
|
case 0x28: /* early (~2009), ex. The Lord of the Rings: Conquest PC */
|
||||||
case 0x32:
|
data_offsets = 0x18;
|
||||||
case 0x34:
|
block_offsets = 0; /* no need, full headers are present */
|
||||||
default: goto fail;
|
header_type = TYPE_8;
|
||||||
|
packet_type = STANDARD;
|
||||||
|
setup_type = HEADER_TRIAD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
//case 0x32: /* ? */
|
||||||
|
case 0x34: /* common (2010~2011) */
|
||||||
|
data_offsets = 0x18;
|
||||||
|
block_offsets = 0x30;
|
||||||
|
header_type = TYPE_6;
|
||||||
|
packet_type = STANDARD;
|
||||||
|
setup_type = EXTERNAL_CODEBOOKS; /* setup_type will be corrected later */
|
||||||
|
break;
|
||||||
|
case 0x2a: /* uncommon (mid 2011), ex. infamous 2 PS3 */
|
||||||
|
data_offsets = 0x10;
|
||||||
|
block_offsets = 0x28;
|
||||||
|
header_type = TYPE_2;
|
||||||
|
packet_type = MODIFIED;
|
||||||
|
setup_type = EXTERNAL_CODEBOOKS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VGM_LOG("WWISE: unknown vorb size 0x%x\n", vorb_size);
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vgmstream->num_samples = read_32bit(vorb_offset + 0x00, streamFile);
|
||||||
|
setup_offset = read_32bit(vorb_offset + data_offsets + 0x00, streamFile); /* within data (0 = no seek table) */
|
||||||
|
audio_offset = read_32bit(vorb_offset + data_offsets + 0x04, streamFile); /* within data */
|
||||||
|
if (block_offsets) {
|
||||||
|
blocksize_1_exp = read_8bit(vorb_offset + block_offsets + 0x00, streamFile); /* small */
|
||||||
|
blocksize_0_exp = read_8bit(vorb_offset + block_offsets + 0x01, streamFile); /* big */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* detect setup type:
|
||||||
|
* - full inline: ~2009, ex. The King of Fighters XII X360, The Saboteur PC
|
||||||
|
* - trimmed inline: ~2010, ex. Army of Two: 40 days X360 (some multiplayer files)
|
||||||
|
* - external: ~2010, ex. Assassin's Creed Brotherhood X360, Dead Nation X360 */
|
||||||
|
if (vorb_size == 0x34) {
|
||||||
|
size_t setup_size = (uint16_t)read_16bit(start_offset + setup_offset, streamFile);
|
||||||
|
uint32_t id = (uint32_t)read_32bitBE(start_offset + setup_offset + 0x06, streamFile);
|
||||||
|
|
||||||
|
/* if the setup after header starts with "(data)BCV" it's an inline codebook) */
|
||||||
|
if ((id & 0x00FFFFFF) == 0x00424356) { /* 0"BCV" */
|
||||||
|
setup_type = FULL_SETUP;
|
||||||
|
}
|
||||||
|
/* if the setup is suspiciously big it's probably trimmed inline codebooks */
|
||||||
|
else if (setup_size > 0x200) { /* an external setup it's ~0x100 max + some threshold */
|
||||||
|
setup_type = INLINE_CODEBOOKS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_wwise_vorbis_codec_data(streamFile, start_offset + setup_offset, ww.channels, ww.sample_rate, blocksize_0_exp,blocksize_1_exp,
|
||||||
|
setup_type,header_type,packet_type, ww.big_endian);
|
||||||
|
if (!vgmstream->codec_data) goto fail;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* newer Wwise (~2012+) */
|
/* newer Wwise (>2012) */
|
||||||
if (ww.extra_size != 0x30) goto fail; //todo some 0x2a exist
|
off_t extra_offset = ww.fmt_offset + 0x18; /* after flag + channels */
|
||||||
|
int is_wem = check_extensions(streamFile,"wem");
|
||||||
|
|
||||||
packet_header_type = 3; /* size 2 */
|
switch(ww.extra_size) {
|
||||||
packet_type = 1; //todo mod packets false on certain configs
|
case 0x30:
|
||||||
setup_type = 4; /* aoTuV */
|
data_offsets = 0x10;
|
||||||
|
block_offsets = 0x28;
|
||||||
|
header_type = TYPE_2;
|
||||||
|
packet_type = MODIFIED;
|
||||||
|
|
||||||
/* 0x12 (2): unk (00,10,18) not related to seek table*/
|
/* setup not detectable by header, so we'll try both; hopefully libvorbis will reject wrong codebooks
|
||||||
/* 0x14 (4): channel config */
|
* - standard: early (<2012), ex. The King of Fighters XIII X360 (2011/11), .ogg (cbs are from aoTuV, too)
|
||||||
vgmstream->num_samples = read_32bit(ww.fmt_offset + 0x18, streamFile);
|
* - aoTuV603: later (>2012), ex. Sonic & All-Stars Racing Transformed PC (2012/11), .wem */
|
||||||
/* 0x20 (4): config, 0xcb/0xd9/etc */
|
setup_type = is_wem ? AOTUV603_CODEBOOKS : EXTERNAL_CODEBOOKS; /* aoTuV came along .wem */
|
||||||
/* 0x24 (4): ? samples? */
|
break;
|
||||||
/* 0x28 (4): seek table size (setup packet offset within data) */
|
|
||||||
/* 0x2c (4): setup size (first audio packet offset within data) */
|
|
||||||
/* 0x30 (2): ? */
|
|
||||||
/* 0x32 (2): ? */
|
|
||||||
/* 0x34 (4): ? */
|
|
||||||
/* 0x38 (4): ? */
|
|
||||||
/* 0x3c (4): uid */ //todo same as external crc32?
|
|
||||||
blocksize_0_pow = read_8bit(ww.fmt_offset + 0x40, streamFile);
|
|
||||||
blocksize_1_pow = read_8bit(ww.fmt_offset + 0x41, streamFile);
|
|
||||||
|
|
||||||
goto fail;
|
//case 0x2a: /* Rocksmith 2011 X360? */
|
||||||
|
//non mod packets? TYPE_06? (possibly detectable by checking setup's granule, should be 0)
|
||||||
|
default:
|
||||||
|
VGM_LOG("WWISE: unknown extra size 0x%x\n", vorb_size);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->num_samples = read_32bit(extra_offset + 0x00, streamFile);
|
||||||
|
setup_offset = read_32bit(extra_offset + data_offsets + 0x00, streamFile); /* within data*/
|
||||||
|
audio_offset = read_32bit(extra_offset + data_offsets + 0x04, streamFile); /* within data */
|
||||||
|
blocksize_1_exp = read_8bit(extra_offset + block_offsets + 0x00, streamFile); /* small */
|
||||||
|
blocksize_0_exp = read_8bit(extra_offset + block_offsets + 0x01, streamFile); /* big */
|
||||||
|
|
||||||
|
/* Normal packets are used rarely (ex. Oddworld New 'n' Tasty! PSV). They are hard to detect (decoding
|
||||||
|
* will mostly work with garbage results) but we'll try. Setup size and "fmt" bitrate fields may matter too. */
|
||||||
|
if (ww.extra_size == 0x30) {
|
||||||
|
/* all blocksizes I've seen are 0x08+0x0B except Oddworld PSV, that uses 0x09+0x09
|
||||||
|
* (maybe lower spec machines = needs simpler packets) */
|
||||||
|
if (blocksize_0_exp == blocksize_1_exp)
|
||||||
|
packet_type = STANDARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* try with the selected codebooks */
|
||||||
|
vgmstream->codec_data = init_wwise_vorbis_codec_data(streamFile, start_offset + setup_offset, ww.channels, ww.sample_rate, blocksize_0_exp,blocksize_1_exp,
|
||||||
|
setup_type,header_type,packet_type, ww.big_endian);
|
||||||
|
if (!vgmstream->codec_data) {
|
||||||
|
/* codebooks failed: try again with the other type */
|
||||||
|
setup_type = is_wem ? EXTERNAL_CODEBOOKS : AOTUV603_CODEBOOKS;
|
||||||
|
vgmstream->codec_data = init_wwise_vorbis_codec_data(streamFile, start_offset + setup_offset, ww.channels, ww.sample_rate, blocksize_0_exp,blocksize_1_exp,
|
||||||
|
setup_type,header_type,packet_type, ww.big_endian);
|
||||||
|
if (!vgmstream->codec_data) goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vgmstream->codec_data = init_wwise_vorbis_codec_data(streamFile, start_offset, vgmstream->channels, vgmstream->sample_rate);//pass endianness too
|
|
||||||
if (!vgmstream->codec_data) goto fail;
|
|
||||||
vgmstream->coding_type = coding_wwise_vorbis;
|
vgmstream->coding_type = coding_wwise_vorbis;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->codec_endian = ww.big_endian;
|
||||||
|
|
||||||
|
start_offset = start_offset + audio_offset;
|
||||||
|
|
||||||
|
/* Vorbis is VBR so this is very approximate, meh */
|
||||||
|
if (ww.truncated)
|
||||||
|
vgmstream->num_samples = vgmstream->num_samples * (ww.file_size - start_offset) / ww.data_size;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
VGM_LOG("WWISE: VORBIS found (unsupported)\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -259,7 +357,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
size_t wiih_size;
|
size_t wiih_size;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (ww.bit_per_sample != 4) goto fail;
|
if (ww.bits_per_sample != 4) goto fail;
|
||||||
|
|
||||||
vgmstream->coding_type = coding_NGC_DSP;
|
vgmstream->coding_type = coding_NGC_DSP;
|
||||||
vgmstream->layout_type = layout_interleave;
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
@ -267,7 +365,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
/* find coef position */
|
/* find coef position */
|
||||||
if (find_chunk(streamFile, 0x57696948,first_offset,0, &wiih_offset,&wiih_size, ww.big_endian, 0)) { /*"WiiH"*/ /* older Wwise */
|
if (find_chunk(streamFile, 0x57696948,first_offset,0, &wiih_offset,&wiih_size, ww.big_endian, 0)) { /*"WiiH"*/ /* older Wwise */
|
||||||
vgmstream->num_samples = ww.data_size / ww.channels / 8 * 14;
|
vgmstream->num_samples = dsp_bytes_to_samples(ww.data_size, ww.channels);
|
||||||
if (wiih_size != 0x2e * ww.channels) goto fail;
|
if (wiih_size != 0x2e * ww.channels) goto fail;
|
||||||
}
|
}
|
||||||
else if (ww.extra_size == 0x0c + ww.channels * 0x2e) { /* newer Wwise */
|
else if (ww.extra_size == 0x0c + ww.channels * 0x2e) { /* newer Wwise */
|
||||||
|
@ -291,21 +389,74 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case XMA2: { /* X360/XBone */
|
case XMA2: { /* X360/XBone */
|
||||||
//chunks:
|
uint8_t buf[0x100];
|
||||||
//"XMA2", "seek": same as the official ones
|
int bytes;
|
||||||
//"XMAc": Wwise extension, XMA2 physical loop regions (loop_start_b, loop_end_b, loop_subframe_data)
|
off_t xma2_offset;
|
||||||
|
size_t xma2_size;
|
||||||
|
|
||||||
VGM_LOG("WWISE: XMA2 found (unsupported)\n");
|
if (!ww.big_endian) goto fail; /* must be Wwise (real XMA are LE and parsed elsewhere) */
|
||||||
goto fail;
|
|
||||||
|
if (find_chunk(streamFile, 0x584D4132,first_offset,0, &xma2_offset,&xma2_size, ww.big_endian, 0)) { /*"XMA2"*/ /* older Wwise */
|
||||||
|
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf,0x100, xma2_offset, xma2_size, ww.data_size, streamFile);
|
||||||
|
} else { /* newer Wwise */
|
||||||
|
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, ww.fmt_offset, ww.fmt_size, ww.data_size, streamFile, ww.big_endian);
|
||||||
|
}
|
||||||
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, ww.data_offset,ww.data_size);
|
||||||
|
if ( !vgmstream->codec_data ) goto fail;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
vgmstream->num_samples = ww.num_samples; /* set while parsing XMAWAVEFORMATs */
|
||||||
|
|
||||||
|
/* "XMAc": rare Wwise extension, XMA2 physical loop regions (loop_start_b, loop_end_b, loop_subframe_data)
|
||||||
|
* Can appear even in the file doesn't loop, maybe it's meant to be the playable physical region */
|
||||||
|
//VGM_ASSERT(find_chunk(streamFile, 0x584D4163,first_offset,0, NULL,NULL, ww.big_endian, 0), "WWISE: XMAc chunk found\n");
|
||||||
|
/* other chunks: "seek", regular XMA2 seek table */
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case XWMA: /* X360 */
|
case XWMA: { /* X360 */
|
||||||
VGM_LOG("WWISE: XWMA found (unsupported)\n");
|
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||||
goto fail;
|
uint8_t buf[0x100];
|
||||||
|
int bytes;
|
||||||
|
|
||||||
|
if (!ww.big_endian) goto fail; /* must be from Wwise X360 (PC LE XWMA is parsed elsewhere) */
|
||||||
|
|
||||||
|
bytes = ffmpeg_make_riff_xwma(buf,0x100, ww.format, ww.data_size, vgmstream->channels, vgmstream->sample_rate, ww.average_bps, ww.block_align);
|
||||||
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, ww.data_offset,ww.data_size);
|
||||||
|
if ( !ffmpeg_data ) goto fail;
|
||||||
|
vgmstream->codec_data = ffmpeg_data;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
/* manually find total samples, why don't they put this in the header is beyond me */
|
||||||
|
{
|
||||||
|
ms_sample_data msd;
|
||||||
|
memset(&msd,0,sizeof(ms_sample_data));
|
||||||
|
|
||||||
|
msd.channels = ww.channels;
|
||||||
|
msd.data_offset = ww.data_offset;
|
||||||
|
msd.data_size = ww.data_size;
|
||||||
|
|
||||||
|
if (ww.format == 0x0162)
|
||||||
|
wmapro_get_samples(&msd, streamFile, ww.block_align, ww.sample_rate,0x0000);
|
||||||
|
else
|
||||||
|
wma_get_samples(&msd, streamFile, ww.block_align, ww.sample_rate,0x0000);
|
||||||
|
|
||||||
|
vgmstream->num_samples = ffmpeg_data->totalSamples; /* ffmpeg_data->totalSamples is approximate from avg-br */
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AAC: { /* iOS/Mac */
|
case AAC: { /* iOS/Mac */
|
||||||
ffmpeg_codec_data * ffmpeg_data = NULL;
|
ffmpeg_codec_data * ffmpeg_data = NULL;
|
||||||
if (ww.block_align != 0 || ww.bit_per_sample != 0) goto fail;
|
if (ww.block_align != 0 || ww.bits_per_sample != 0) goto fail;
|
||||||
|
|
||||||
/* extra: size 0x12, unknown values */
|
/* extra: size 0x12, unknown values */
|
||||||
|
|
||||||
|
@ -322,18 +473,18 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
case HEVAG: /* PSV */
|
case HEVAG: /* PSV */
|
||||||
/* changed values, another bizarre Wwise quirk */
|
/* changed values, another bizarre Wwise quirk */
|
||||||
//ww.block_align /* unknown (1ch=2, 2ch=4) */
|
//ww.block_align /* unknown (1ch=2, 2ch=4) */
|
||||||
//ww.bit_per_sample; /* probably interleave (0x10) */
|
//ww.bits_per_sample; /* probably interleave (0x10) */
|
||||||
//if (ww.bit_per_sample != 4) goto fail;
|
//if (ww.bits_per_sample != 4) goto fail;
|
||||||
|
|
||||||
if (ww.big_endian) goto fail;
|
if (ww.big_endian) goto fail;
|
||||||
|
|
||||||
/* extra_data: size 0x06, @0x00: samples per block (28), @0x04: channel config */
|
/* extra_data: size 0x06, @0x00: samples per block (0x1c), @0x04: channel config */
|
||||||
|
|
||||||
vgmstream->coding_type = coding_HEVAG;
|
vgmstream->coding_type = coding_HEVAG;
|
||||||
vgmstream->layout_type = layout_interleave;
|
vgmstream->layout_type = layout_interleave;
|
||||||
vgmstream->interleave_block_size = 0x10;
|
vgmstream->interleave_block_size = 0x10;
|
||||||
|
|
||||||
vgmstream->num_samples = ww.data_size * 28 / 16 / ww.channels;
|
vgmstream->num_samples = ps_bytes_to_samples(ww.data_size, ww.channels);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ATRAC9: /* PSV/PS4 */
|
case ATRAC9: /* PSV/PS4 */
|
||||||
|
@ -353,3 +504,68 @@ fail:
|
||||||
close_vgmstream(vgmstream);
|
close_vgmstream(vgmstream);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* VORBIS FORMAT RESEARCH */
|
||||||
|
/*
|
||||||
|
- old format
|
||||||
|
"fmt" size 0x28, extra size 0x16 / size 0x18, extra size 0x06
|
||||||
|
0x12 (2): flag? (00,10,18): not related to seek table, codebook type, chunk count, looping
|
||||||
|
0x14 (4): channel config
|
||||||
|
0x18-24 (16): ? (fixed: 0x01000000 00001000 800000AA 00389B71) [removed when extra size is 0x06]
|
||||||
|
|
||||||
|
"vorb" size 0x34
|
||||||
|
0x00 (4): num_samples
|
||||||
|
0x04 (4): skip samples?
|
||||||
|
0x08 (4): ? (small if loop, 0 otherwise)
|
||||||
|
0x0c (4): loop offset after seek table+setup (offset after setup if file doesn't loop)
|
||||||
|
0x10 (4): ? (small, 0..~0x400)
|
||||||
|
0x14 (4): approximate data size without seek table? (almost setup+packets)
|
||||||
|
0x18 (4): setup_offset within data (0 = no seek table)
|
||||||
|
0x1c (4): audio_offset within data
|
||||||
|
0x20 (4): biggest packet size (not including header)?
|
||||||
|
0x24 (4): ? (mid, 0~0x5000)
|
||||||
|
0x28 (4): ? (mid, 0~0x5000)
|
||||||
|
0x2c (4): parent bank/event id? (shared by several .wem a game, but not all need to share it)
|
||||||
|
0x30 (1): blocksize_1_exp (small)
|
||||||
|
0x31 (1): blocksize_0_exp (large)
|
||||||
|
0x32 (2): empty
|
||||||
|
|
||||||
|
"vorb" size 0x28 / 0x2a
|
||||||
|
0x00 (4): num_samples
|
||||||
|
0x04 (4): loop offset after seek table+setup (offset after setup if file doesn't loop)
|
||||||
|
0x08 (4): data size without seek table (setup+packets)
|
||||||
|
0x0c (2): ? (small, 0..~0x400)
|
||||||
|
0x10 (4): setup_offset within data (0 = no seek table)
|
||||||
|
0x14 (4): audio_offset within data
|
||||||
|
0x18 (2): ? (small, 0..~0x400)
|
||||||
|
0x1a (2): ? (small, N..~0x100)
|
||||||
|
0x1c (4): ? (mid, 0~0x5000)
|
||||||
|
0x20 (4): ? (mid, 0~0x5000)
|
||||||
|
0x24 (4): parent bank/event id? (shared by several .wem a game, but not all need to share it)
|
||||||
|
0x28 (1): blocksize_1_exp (small) [removed when size is 0x28]
|
||||||
|
0x29 (1): blocksize_0_exp (large) [removed when size is 0x28]
|
||||||
|
|
||||||
|
|
||||||
|
- new format:
|
||||||
|
"fmt" size 0x42, extra size 0x30
|
||||||
|
0x12 (2): flag? (00,10,18): not related to seek table, codebook type, chunk count, looping, etc
|
||||||
|
0x14 (4): channel config
|
||||||
|
0x18 (4): num_samples
|
||||||
|
0x1c (4): loop offset after seek table+setup (offset after setup if file doesn't loop)
|
||||||
|
0x20 (4): data size without seek table (setup+packets)
|
||||||
|
0x24 (2): ?1 (small, 0..~0x400)
|
||||||
|
0x26 (2): ?2 (small, N..~0x100): not related to seek table, codebook type, chunk count, looping, packet size, samples, etc
|
||||||
|
0x28 (4): setup offset within data (0 = no seek table)
|
||||||
|
0x2c (4): audio offset within data
|
||||||
|
0x30 (2): biggest packet size (not including header)
|
||||||
|
0x32 (2): ?4 (small, 0..~0x100): may be same than ?2 (something related to the avg bitrate?)
|
||||||
|
0x34 (4): bitrate config? (mid, 0~0x5000)
|
||||||
|
0x38 (4): bitrate config? (mid, 0~0x5000) (2 byte with max/min?)
|
||||||
|
0x40 (1): blocksize_1_exp (small)
|
||||||
|
0x41 (1): blocksize_0_exp (large)
|
||||||
|
|
||||||
|
Wwise encoder options, unknown fields above may be reflect these:
|
||||||
|
https://www.audiokinetic.com/library/edge/?source=Help&id=vorbis_encoder_parameters
|
||||||
|
*/
|
||||||
|
|
|
@ -37,29 +37,29 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
|
||||||
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
|
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
|
||||||
vgmstream->meta_type = meta_X360_AST;
|
vgmstream->meta_type = meta_X360_AST;
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
|
||||||
{
|
{
|
||||||
/* manually find sample offsets (XMA1 nonsense again) */
|
/* manually find sample offsets (XMA1 nonsense again) */
|
||||||
xma_sample_data xma_sd;
|
ms_sample_data msd;
|
||||||
memset(&xma_sd,0,sizeof(xma_sample_data));
|
memset(&msd,0,sizeof(ms_sample_data));
|
||||||
|
|
||||||
xma_sd.xma_version = 1;
|
msd.xma_version = 1;
|
||||||
xma_sd.channels = channel_count;
|
msd.channels = channel_count;
|
||||||
xma_sd.data_offset = start_offset;
|
msd.data_offset = start_offset;
|
||||||
xma_sd.data_size = data_size;
|
msd.data_size = data_size;
|
||||||
xma_sd.loop_flag = loop_flag;
|
msd.loop_flag = loop_flag;
|
||||||
xma_sd.loop_start_b = read_32bitBE(0x44,streamFile);
|
msd.loop_start_b = read_32bitBE(0x44,streamFile);
|
||||||
xma_sd.loop_end_b = read_32bitBE(0x48,streamFile);
|
msd.loop_end_b = read_32bitBE(0x48,streamFile);
|
||||||
xma_sd.loop_start_subframe = read_8bit(0x4c,streamFile) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
msd.loop_start_subframe = read_8bit(0x4c,streamFile) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
||||||
xma_sd.loop_end_subframe = read_8bit(0x4c,streamFile) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
msd.loop_end_subframe = read_8bit(0x4c,streamFile) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
||||||
|
|
||||||
xma_get_samples(&xma_sd, streamFile);
|
xma_get_samples(&msd, streamFile);
|
||||||
vgmstream->num_samples = xma_sd.num_samples;
|
vgmstream->num_samples = msd.num_samples;
|
||||||
vgmstream->loop_start_sample = xma_sd.loop_start_sample;
|
vgmstream->loop_start_sample = msd.loop_start_sample;
|
||||||
vgmstream->loop_end_sample = xma_sd.loop_end_sample;
|
vgmstream->loop_end_sample = msd.loop_end_sample;
|
||||||
//skip_samples = xma_sd.skip_samples; //todo add skip samples
|
//skip_samples = msd.skip_samples; //todo add skip samples
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
{
|
{
|
||||||
uint8_t buf[100];
|
uint8_t buf[100];
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
|
@ -68,7 +68,7 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
|
||||||
size_t fmt_size = 0x0c + xma_streams * 0x14;
|
size_t fmt_size = 0x0c + xma_streams * 0x14;
|
||||||
|
|
||||||
/* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */
|
/* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */
|
||||||
bytes = ffmpeg_make_riff_xma_from_fmt(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1);
|
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1);
|
||||||
if (bytes <= 0) goto fail;
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
/* Namco NUB xma - from Tekken 6, Galaga Legions DX */
|
||||||
|
VGMSTREAM * init_vgmstream_x360_nub(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
off_t start_offset, chunk_offset;
|
||||||
|
size_t data_size, chunk_size;
|
||||||
|
int loop_flag, channel_count, sample_rate, chunk_type;
|
||||||
|
int num_samples, loop_start_sample, loop_end_sample;
|
||||||
|
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
if ( !check_extensions(streamFile,"xma")) /* (probably meant to be .nub) */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (read_32bitBE(0x00,streamFile) != 0x786D6100) /* "xma\0" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
/* custom header with a "XMA2" or "fmt " chunk inside; most other values are unknown */
|
||||||
|
chunk_type = read_32bitBE(0xC,streamFile);
|
||||||
|
start_offset = 0x100;
|
||||||
|
data_size = read_32bitBE(0x14,streamFile);
|
||||||
|
chunk_offset = 0xBC;
|
||||||
|
chunk_size = read_32bitBE(0x24,streamFile);
|
||||||
|
if (chunk_type == 0x4) { /* "XMA2" */
|
||||||
|
xma2_parse_xma2_chunk(streamFile, chunk_offset, &channel_count,&sample_rate, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample);
|
||||||
|
} else if (chunk_type == 0x8) { /* "fmt " */
|
||||||
|
channel_count = read_16bitBE(chunk_offset+0x02,streamFile);
|
||||||
|
sample_rate = read_32bitBE(chunk_offset+0x04,streamFile);
|
||||||
|
xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = num_samples;
|
||||||
|
vgmstream->loop_start_sample = loop_start_sample;
|
||||||
|
vgmstream->loop_end_sample = loop_end_sample;
|
||||||
|
vgmstream->meta_type = meta_NUB_XMA;
|
||||||
|
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
{
|
||||||
|
uint8_t buf[0x100];
|
||||||
|
size_t bytes;
|
||||||
|
|
||||||
|
if (chunk_type == 0x4) { /* "XMA2" */
|
||||||
|
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile);
|
||||||
|
} else { /* "fmt " */
|
||||||
|
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1);
|
||||||
|
}
|
||||||
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);;
|
||||||
|
if ( !vgmstream->codec_data ) goto fail;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* open the file for reading */
|
||||||
|
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
/* PASX - from SoulCalibur II HD (X360) */
|
||||||
|
VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
off_t start_offset, chunk_offset;
|
||||||
|
size_t data_size, chunk_size;
|
||||||
|
int loop_flag, channel_count, sample_rate;
|
||||||
|
int num_samples, loop_start_sample, loop_end_sample;
|
||||||
|
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
if ( !check_extensions(streamFile,"past"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
/* custom header with a "fmt " data chunk inside */
|
||||||
|
chunk_size = read_32bitBE(0x08,streamFile);
|
||||||
|
data_size = read_32bitBE(0x0c,streamFile);
|
||||||
|
chunk_offset = read_32bitBE(0x10,streamFile); /* 0x14: fmt offset end */
|
||||||
|
start_offset = read_32bitBE(0x18,streamFile);
|
||||||
|
|
||||||
|
channel_count = read_16bitBE(chunk_offset+0x02,streamFile);
|
||||||
|
sample_rate = read_32bitBE(chunk_offset+0x04,streamFile);
|
||||||
|
xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = num_samples;
|
||||||
|
vgmstream->loop_start_sample = loop_start_sample;
|
||||||
|
vgmstream->loop_end_sample = loop_end_sample;
|
||||||
|
vgmstream->meta_type = meta_X360_PASX;
|
||||||
|
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
{
|
||||||
|
uint8_t buf[0x100];
|
||||||
|
size_t bytes;
|
||||||
|
|
||||||
|
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1);
|
||||||
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
||||||
|
if ( !vgmstream->codec_data ) goto fail;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* open the file for reading */
|
||||||
|
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -1,103 +1,117 @@
|
||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
#include "../util.h"
|
|
||||||
#include "../coding/coding.h"
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
/* XMA - Microsoft format derived from WMAPRO, found in X360/XBone games */
|
||||||
|
|
||||||
#define FAKE_RIFF_BUFFER_SIZE 100
|
|
||||||
|
|
||||||
|
|
||||||
/* parsing helper */
|
|
||||||
typedef struct {
|
|
||||||
size_t file_size;
|
|
||||||
/* file traversing */
|
|
||||||
int big_endian;
|
|
||||||
off_t chunk_offset; /* main header chunk offset, after "(id)" and size */
|
|
||||||
size_t chunk_size;
|
|
||||||
off_t data_offset;
|
|
||||||
size_t data_size;
|
|
||||||
|
|
||||||
int32_t fmt_codec;
|
|
||||||
uint8_t xma2_version;
|
|
||||||
int needs_header;
|
|
||||||
int force_little_endian; /* FFmpeg can't parse big endian "fmt" chunks */
|
|
||||||
int skip_samples;
|
|
||||||
|
|
||||||
/* info */
|
|
||||||
int channels;
|
|
||||||
int loop_flag;
|
|
||||||
int32_t num_samples;
|
|
||||||
int32_t loop_start_sample;
|
|
||||||
int32_t loop_end_sample;
|
|
||||||
|
|
||||||
int32_t loop_start_b;
|
|
||||||
int32_t loop_end_b;
|
|
||||||
int32_t loop_subframe;
|
|
||||||
|
|
||||||
meta_t meta;
|
|
||||||
} xma_header_data;
|
|
||||||
|
|
||||||
static int parse_header(xma_header_data * xma, STREAMFILE *streamFile);
|
|
||||||
static void fix_samples(xma_header_data * xma, STREAMFILE *streamFile);
|
|
||||||
static int create_riff_header(uint8_t * buf, size_t buf_size, xma_header_data * xma, STREAMFILE *streamFile);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XMA 1/2 (Microsoft)
|
|
||||||
*
|
|
||||||
* Usually in RIFF headers and minor variations.
|
|
||||||
*/
|
|
||||||
VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
|
VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM * vgmstream = NULL;
|
||||||
ffmpeg_codec_data *data = NULL;
|
off_t start_offset, chunk_offset, first_offset = 0xc;
|
||||||
|
size_t data_size, chunk_size;
|
||||||
xma_header_data xma;
|
int loop_flag, channel_count, sample_rate, is_xma2_old = 0, is_xma1 = 0;
|
||||||
uint8_t fake_riff[FAKE_RIFF_BUFFER_SIZE];
|
int num_samples, loop_start_sample, loop_end_sample, loop_start_b = 0, loop_end_b = 0, loop_subframe = 0;
|
||||||
int fake_riff_size = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
/* check extension, case insensitive */
|
||||||
/* .xma2: Skullgirls, .nps: Beautiful Katamari, .past: SoulCalibur II HD */
|
/* .xma2: Skullgirls, .nps: Beautiful Katamari (renamed .xma) */
|
||||||
if ( !check_extensions(streamFile, "xma,xma2,nps,past") )
|
if ( !check_extensions(streamFile, "xma,xma2,nps") )
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* check header */
|
{
|
||||||
if ( !parse_header(&xma, streamFile) )
|
size_t file_size = streamFile->get_size(streamFile);
|
||||||
goto fail;
|
size_t riff_size = read_32bitLE(0x04,streamFile);
|
||||||
|
/* +8 for some Beautiful Katamari files, unsure if bad rip */
|
||||||
|
if (riff_size != file_size && riff_size+8 > file_size)
|
||||||
/* init ffmpeg (create a fake RIFF that FFmpeg can read if needed) */
|
goto fail;
|
||||||
if (xma.needs_header) { /* fake header + partial size */
|
|
||||||
fake_riff_size = create_riff_header(fake_riff, FAKE_RIFF_BUFFER_SIZE, &xma, streamFile);
|
|
||||||
if (fake_riff_size <= 0) goto fail;
|
|
||||||
|
|
||||||
data = init_ffmpeg_header_offset(streamFile, fake_riff, (uint64_t)fake_riff_size, xma.data_offset, xma.data_size);
|
|
||||||
if (!data) goto fail;
|
|
||||||
}
|
|
||||||
else { /* no change */
|
|
||||||
data = init_ffmpeg_offset(streamFile, 0, xma.file_size);
|
|
||||||
if (!data) goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* build VGMSTREAM */
|
/* parse LE RIFF header, with "XMA2" (XMA2WAVEFORMAT) or "fmt " (XMAWAVEFORMAT/XMA2WAVEFORMAT) main chunks
|
||||||
vgmstream = allocate_vgmstream(data->channels, xma.loop_flag);
|
* Often comes with an optional "seek" chunk too */
|
||||||
|
|
||||||
|
/* parse sample data */
|
||||||
|
if ( find_chunk_le(streamFile, 0x584D4132,first_offset,0, &chunk_offset,&chunk_size) ) { /* old XMA2 */
|
||||||
|
is_xma2_old = 1;
|
||||||
|
xma2_parse_xma2_chunk(streamFile, chunk_offset, &channel_count,&sample_rate, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample);
|
||||||
|
}
|
||||||
|
else if ( find_chunk_le(streamFile, 0x666d7420,first_offset,0, &chunk_offset,&chunk_size)) {
|
||||||
|
int format = read_16bitLE(chunk_offset,streamFile);
|
||||||
|
if (format == 0x165) { /* XMA1 */
|
||||||
|
is_xma1 = 1;
|
||||||
|
xma1_parse_fmt_chunk(streamFile, chunk_offset, &channel_count,&sample_rate, &loop_flag, &loop_start_b, &loop_end_b, &loop_subframe, 0);
|
||||||
|
} else if (format == 0x166) { /* new XMA2 */
|
||||||
|
channel_count = read_16bitLE(chunk_offset+0x02,streamFile);
|
||||||
|
sample_rate = read_32bitLE(chunk_offset+0x04,streamFile);
|
||||||
|
xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 0);
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "data" chunk */
|
||||||
|
if (!find_chunk_le(streamFile, 0x64617461,first_offset,0, &start_offset,&data_size)) /*"data"*/
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
|
||||||
|
/* fix samples; for now only XMA1 is fixed, but xmaencode.exe doesn't seem to use XMA2
|
||||||
|
* num_samples in the headers, and the values don't look exact */
|
||||||
|
if (is_xma1) {
|
||||||
|
ms_sample_data msd;
|
||||||
|
memset(&msd,0,sizeof(ms_sample_data));
|
||||||
|
|
||||||
|
msd.xma_version = 1;
|
||||||
|
msd.channels = channel_count;
|
||||||
|
msd.data_offset = start_offset;
|
||||||
|
msd.data_size = data_size;
|
||||||
|
msd.loop_flag = loop_flag;
|
||||||
|
msd.loop_start_b= loop_start_b;
|
||||||
|
msd.loop_end_b = loop_end_b;
|
||||||
|
msd.loop_start_subframe = loop_subframe & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
||||||
|
msd.loop_end_subframe = loop_subframe >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
||||||
|
|
||||||
|
xma_get_samples(&msd, streamFile);
|
||||||
|
|
||||||
|
num_samples = msd.num_samples;
|
||||||
|
//skip_samples = msd.skip_samples;
|
||||||
|
loop_start_sample = msd.loop_start_sample;
|
||||||
|
loop_end_sample = msd.loop_end_sample;
|
||||||
|
/* XMA2 loop/num_samples don't seem to skip_samples */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
vgmstream->codec_data = data;
|
|
||||||
vgmstream->coding_type = coding_FFmpeg;
|
|
||||||
vgmstream->layout_type = layout_none;
|
|
||||||
vgmstream->meta_type = xma.meta;
|
|
||||||
|
|
||||||
vgmstream->sample_rate = data->sampleRate;
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = num_samples;
|
||||||
|
vgmstream->loop_start_sample = loop_start_sample;
|
||||||
|
vgmstream->loop_end_sample = loop_end_sample;
|
||||||
|
vgmstream->meta_type = meta_XMA_RIFF;
|
||||||
|
|
||||||
/* fix samples for some formats (data->totalSamples: XMA1 = not set; XMA2 = not reliable) */
|
|
||||||
xma.channels = data->channels;
|
|
||||||
fix_samples(&xma, streamFile);
|
|
||||||
|
|
||||||
vgmstream->num_samples = xma.num_samples;
|
#ifdef VGM_USE_FFMPEG
|
||||||
if (vgmstream->loop_flag) {
|
{
|
||||||
vgmstream->loop_start_sample = xma.loop_start_sample;
|
uint8_t buf[0x100];
|
||||||
vgmstream->loop_end_sample = xma.loop_end_sample;
|
size_t bytes;
|
||||||
|
|
||||||
|
if (is_xma2_old) {
|
||||||
|
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile);
|
||||||
|
} else {
|
||||||
|
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 0);
|
||||||
|
}
|
||||||
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
||||||
|
if ( !vgmstream->codec_data ) goto fail;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
//not active due to a FFmpeg bug that misses some of the last packet samples and decodes
|
//not active due to a FFmpeg bug that misses some of the last packet samples and decodes
|
||||||
// garbage if asked for more samples (always happens but more apparent with skip_samples active)
|
// garbage if asked for more samples (always happens but more apparent with skip_samples active)
|
||||||
|
@ -106,313 +120,17 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
|
||||||
ffmpeg_set_skip_samples(data, xma.skip_samples);
|
ffmpeg_set_skip_samples(data, xma.skip_samples);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* open the file for reading */
|
||||||
|
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||||
|
goto fail;
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
/* clean up */
|
close_vgmstream(vgmstream);
|
||||||
if (data) {
|
|
||||||
free_ffmpeg(data);
|
|
||||||
}
|
|
||||||
if (vgmstream) {
|
|
||||||
vgmstream->codec_data = NULL;
|
|
||||||
close_vgmstream(vgmstream);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds stuff needed for XMA with FFmpeg
|
|
||||||
*
|
|
||||||
* returns 1 if ok, 0 on error
|
|
||||||
*/
|
|
||||||
static int parse_header(xma_header_data * xma, STREAMFILE *streamFile) {
|
|
||||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
|
||||||
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
|
||||||
uint32_t id;
|
|
||||||
int big_endian = 0;
|
|
||||||
enum {
|
|
||||||
id_RIFF = UINT32_C(0x52494646), /* "RIFF" */
|
|
||||||
id_RIFX = UINT32_C(0x52494658), /* "RIFX" */
|
|
||||||
id_NXMA = UINT32_C(0x786D6100), /* "xma\0" */
|
|
||||||
id_PASX = UINT32_C(0x50415358), /* "PASX" */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* check header */
|
|
||||||
id = read_32bitBE(0x00,streamFile);
|
|
||||||
switch (id) {
|
|
||||||
case id_RIFF:
|
|
||||||
break;
|
|
||||||
case id_RIFX:
|
|
||||||
case id_NXMA:
|
|
||||||
case id_PASX:
|
|
||||||
big_endian = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(xma,0,sizeof(xma_header_data));
|
|
||||||
xma->big_endian = big_endian;
|
|
||||||
|
|
||||||
if (xma->big_endian) {
|
|
||||||
read_32bit = read_32bitBE;
|
|
||||||
read_16bit = read_16bitBE;
|
|
||||||
} else {
|
|
||||||
read_32bit = read_32bitLE;
|
|
||||||
read_16bit = read_16bitLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
xma->file_size = streamFile->get_size(streamFile);
|
|
||||||
|
|
||||||
/* find offsets */
|
|
||||||
if (id == id_RIFF || id == id_RIFX) { /* regular RIFF header / RIFX (BE, wwsize?) */
|
|
||||||
off_t current_chunk = 0xc;
|
|
||||||
off_t fmt_offset = 0, xma2_offset = 0;
|
|
||||||
size_t riff_size = 0, fmt_size = 0, xma2_size = 0;
|
|
||||||
|
|
||||||
xma->meta = meta_XMA_RIFF;
|
|
||||||
riff_size = read_32bit(4,streamFile);
|
|
||||||
if (riff_size != xma->file_size && /* some Beautiful Katamari, unsure if bad rip */
|
|
||||||
riff_size+8 > xma->file_size) goto fail;
|
|
||||||
|
|
||||||
while (current_chunk < xma->file_size && current_chunk < riff_size+8) {
|
|
||||||
uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
|
|
||||||
off_t chunk_size = read_32bit(current_chunk+4,streamFile);
|
|
||||||
|
|
||||||
if (current_chunk+4+4+chunk_size > xma->file_size)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
switch(chunk_type) {
|
|
||||||
case 0x666d7420: /* "fmt " */
|
|
||||||
if (fmt_offset) goto fail;
|
|
||||||
|
|
||||||
fmt_offset = current_chunk + 4 + 4;
|
|
||||||
fmt_size = chunk_size;
|
|
||||||
break;
|
|
||||||
case 0x64617461: /* "data" */
|
|
||||||
if (xma->data_offset) goto fail;
|
|
||||||
|
|
||||||
xma->data_offset = current_chunk + 4 + 4;
|
|
||||||
xma->data_size = chunk_size;
|
|
||||||
break;
|
|
||||||
case 0x584D4132: /* "XMA2" */
|
|
||||||
if (xma2_offset) goto fail;
|
|
||||||
|
|
||||||
xma2_offset = current_chunk + 4 + 4;
|
|
||||||
xma2_size = chunk_size;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_chunk += 8+chunk_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* give priority to "XMA2" since it can go together with "fmt " */
|
|
||||||
if (xma2_offset) {
|
|
||||||
xma->chunk_offset = xma2_offset;
|
|
||||||
xma->chunk_size = xma2_size;
|
|
||||||
xma->xma2_version = read_8bit(xma->chunk_offset,streamFile);
|
|
||||||
xma->needs_header = 1; /* FFmpeg can only parse pure XMA1 or pure XMA2 */
|
|
||||||
} else if (fmt_offset) {
|
|
||||||
xma->chunk_offset = fmt_offset;
|
|
||||||
xma->chunk_size = fmt_size;
|
|
||||||
xma->fmt_codec = read_16bit(xma->chunk_offset,streamFile);
|
|
||||||
xma->force_little_endian = xma->big_endian;
|
|
||||||
} else {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (id == id_NXMA) { /* Namco NUB xma (Tekken 6, Galaga Legions DX) */
|
|
||||||
/* Custom header with a "XMA2" or "fmt " data chunk inside; most other values are unknown
|
|
||||||
* It's here rather than its own meta to reuse the chunk parsing (probably intended to be .nub) */
|
|
||||||
uint32_t chunk_type = read_32bit(0xC,streamFile);
|
|
||||||
|
|
||||||
xma->meta = meta_NUB_XMA;
|
|
||||||
xma->data_offset = 0x100;
|
|
||||||
xma->data_size = read_32bit(0x14,streamFile);
|
|
||||||
xma->chunk_offset = 0xBC;
|
|
||||||
xma->chunk_size = read_32bit(0x24,streamFile);
|
|
||||||
if (chunk_type == 0x4) { /* "XMA2" */
|
|
||||||
xma->xma2_version = read_8bit(xma->chunk_offset,streamFile);
|
|
||||||
} else if (chunk_type == 0x8) { /* "fmt " */
|
|
||||||
xma->fmt_codec = read_16bit(xma->chunk_offset,streamFile);
|
|
||||||
xma->force_little_endian = 1;
|
|
||||||
} else {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
xma->needs_header = 1;
|
|
||||||
|
|
||||||
if (xma->data_size + xma->data_offset > xma->file_size) goto fail;
|
|
||||||
}
|
|
||||||
else if (id == id_PASX) { /* SoulCalibur II HD */
|
|
||||||
/* Custom header with a "fmt " data chunk inside
|
|
||||||
* It's here rather than its own meta to reuse the chunk parsing */
|
|
||||||
|
|
||||||
xma->meta = meta_X360_PASX;
|
|
||||||
xma->chunk_size = read_32bit(0x08,streamFile);
|
|
||||||
xma->data_size = read_32bit(0x0c,streamFile);
|
|
||||||
xma->chunk_offset = read_32bit(0x10,streamFile);
|
|
||||||
/* 0x14: chunk offset end */
|
|
||||||
xma->data_offset = read_32bit(0x18,streamFile);
|
|
||||||
xma->fmt_codec = read_16bit(xma->chunk_offset,streamFile);
|
|
||||||
xma->needs_header = 1;
|
|
||||||
xma->force_little_endian = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find sample data */
|
|
||||||
if (xma->xma2_version) { /* old XMA2 (internally always BE) */
|
|
||||||
xma->loop_start_sample = read_32bitBE(xma->chunk_offset+0x4,streamFile);
|
|
||||||
xma->loop_end_sample = read_32bitBE(xma->chunk_offset+0x8,streamFile);
|
|
||||||
xma->loop_flag = (uint8_t)read_8bit(xma->chunk_offset+0x3,streamFile) > 0 /* rarely not set, encoder default */
|
|
||||||
|| xma->loop_end_sample;
|
|
||||||
if (xma->xma2_version == 3) {
|
|
||||||
xma->num_samples = read_32bitBE(xma->chunk_offset+0x14,streamFile);
|
|
||||||
/*xma->pcm_samples = read_32bitBE(xma->chunk_offset+0x18,streamFile)*/
|
|
||||||
} else {
|
|
||||||
xma->num_samples = read_32bitBE(xma->chunk_offset+0x1C,streamFile);
|
|
||||||
/*xma->pcm_samples = read_32bitBE(xma->chunk_offset+0x20,streamFile)*/
|
|
||||||
}
|
|
||||||
/* num_samples is the max samples in the file (apparently not including encoder delay) */
|
|
||||||
/* pcm_samples are original WAV's; not current since samples and sample rate may be adjusted for looping purposes */
|
|
||||||
}
|
|
||||||
else if (xma->fmt_codec == 0x166) { /* pure XMA2 */
|
|
||||||
xma->num_samples = read_32bit(xma->chunk_offset+0x18,streamFile);
|
|
||||||
xma->loop_start_sample = read_32bit(xma->chunk_offset+0x28,streamFile);
|
|
||||||
xma->loop_end_sample = xma->loop_start_sample + read_32bit(xma->chunk_offset+0x2C,streamFile);
|
|
||||||
xma->loop_flag = (uint8_t)read_8bit(xma->chunk_offset+0x30,streamFile) > 0 /* never set in practice */
|
|
||||||
|| xma->loop_end_sample;
|
|
||||||
/* play_begin+end = probably pcm_samples (for original sample rate), don't seem to affect anything */
|
|
||||||
/* int32_t play_begin_sample = read_32bit(xma->chunk_offset+0x20,streamFile); */
|
|
||||||
/* int32_t play_end_sample = play_begin_sample + read_32bit(xma->chunk_offset+0x24,streamFile); */
|
|
||||||
}
|
|
||||||
else if (xma->fmt_codec == 0x165) { /* pure XMA1 */
|
|
||||||
xma->loop_flag = (uint8_t)read_8bit(xma->chunk_offset+0xA,streamFile) > 0;
|
|
||||||
xma->loop_start_b = read_32bit(xma->chunk_offset+0x14,streamFile);
|
|
||||||
xma->loop_end_b = read_32bit(xma->chunk_offset+0x18,streamFile);
|
|
||||||
xma->loop_subframe = (uint8_t)read_8bit(xma->chunk_offset+0x1C,streamFile);
|
|
||||||
/* num_samples are parsed later */
|
|
||||||
}
|
|
||||||
else { /* unknown chunk */
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void fix_samples(xma_header_data * xma, STREAMFILE *streamFile) {
|
|
||||||
xma_sample_data xma_sd;
|
|
||||||
|
|
||||||
/* for now only XMA1 is fixed, but xmaencode.exe doesn't seem to use
|
|
||||||
* XMA2 sample values in the headers, and the exact number of samples may not be exact.
|
|
||||||
* Also loop values don't seem to need skip_samples. */
|
|
||||||
|
|
||||||
if (xma->fmt_codec != 0x165) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&xma_sd,0,sizeof(xma_sample_data));
|
|
||||||
|
|
||||||
/* call xma parser (copy to its own struct, a bit clunky but oh well...) */
|
|
||||||
xma_sd.xma_version = xma->fmt_codec==0x165 ? 1 : 2;
|
|
||||||
xma_sd.channels = xma->channels;
|
|
||||||
xma_sd.data_offset = xma->data_offset;
|
|
||||||
xma_sd.data_size = xma->data_size;
|
|
||||||
xma_sd.loop_flag = xma->loop_flag;
|
|
||||||
xma_sd.loop_start_b = xma->loop_start_b;
|
|
||||||
xma_sd.loop_end_b = xma->loop_end_b;
|
|
||||||
xma_sd.loop_start_subframe = xma->loop_subframe & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
|
|
||||||
xma_sd.loop_end_subframe = xma->loop_subframe >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
|
|
||||||
|
|
||||||
xma_get_samples(&xma_sd, streamFile);
|
|
||||||
|
|
||||||
/* and recieve results */
|
|
||||||
xma->num_samples = xma_sd.num_samples;
|
|
||||||
xma->skip_samples = xma_sd.skip_samples;
|
|
||||||
xma->loop_start_sample = xma_sd.loop_start_sample;
|
|
||||||
xma->loop_end_sample = xma_sd.loop_end_sample;
|
|
||||||
/* XMA2 loop/num_samples don't seem to skip_samples */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recreates a RIFF header that FFmpeg can read since it lacks support for some variations.
|
|
||||||
*
|
|
||||||
* returns bytes written (up until "data" chunk + size), -1 on failure
|
|
||||||
*/
|
|
||||||
static int create_riff_header(uint8_t * buf, size_t buf_size, xma_header_data * xma, STREAMFILE *streamFile) {
|
|
||||||
void (*put_32bit)(uint8_t *, int32_t) = NULL;
|
|
||||||
uint8_t chunk[FAKE_RIFF_BUFFER_SIZE];
|
|
||||||
uint8_t internal[FAKE_RIFF_BUFFER_SIZE];
|
|
||||||
size_t head_size, file_size, internal_size;
|
|
||||||
|
|
||||||
int use_be = xma->big_endian && !xma->force_little_endian;
|
|
||||||
|
|
||||||
if (use_be) {
|
|
||||||
put_32bit = put_32bitBE;
|
|
||||||
} else {
|
|
||||||
put_32bit = put_32bitLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(buf,0, sizeof(uint8_t) * buf_size);
|
|
||||||
if (read_streamfile(chunk,xma->chunk_offset,xma->chunk_size, streamFile) != xma->chunk_size)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* create internal chunks */
|
|
||||||
if (xma->xma2_version == 3) { /* old XMA2 v3: change to v4 (extra 8 bytes in the middle) */
|
|
||||||
internal_size = 4+4+xma->chunk_size + 8;
|
|
||||||
|
|
||||||
memcpy(internal + 0x0, "XMA2", 4); /* "XMA2" chunk (internal data is BE) */
|
|
||||||
put_32bit(internal + 0x4, xma->chunk_size + 8); /* v3 > v4 size*/
|
|
||||||
put_8bit(internal + 0x8, 4); /* v4 */
|
|
||||||
memcpy(internal + 0x9, chunk+1, 15); /* first v3 part (fixed) */
|
|
||||||
put_32bitBE(internal + 0x18, 0); /* extra v4 BE: "EncodeOptions" (not used by FFmpeg) */
|
|
||||||
put_32bitBE(internal + 0x1c, 0); /* extra v4 BE: "PsuedoBytesPerSec" (not used by FFmpeg) */
|
|
||||||
memcpy(internal + 0x20, chunk+16, xma->chunk_size - 16); /* second v3 part (variable) */
|
|
||||||
}
|
|
||||||
else { /* direct copy (old XMA2 v4 ignoring "fmt", pure XMA1/2) */
|
|
||||||
internal_size = 4+4+xma->chunk_size;
|
|
||||||
|
|
||||||
if (xma->force_little_endian ) {
|
|
||||||
if ( !ffmpeg_fmt_chunk_swap_endian(chunk, xma->chunk_size, xma->fmt_codec) )
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(internal + 0x0, xma->xma2_version ? "XMA2" : "fmt ", 4);
|
|
||||||
put_32bit(internal + 0x4, xma->chunk_size);
|
|
||||||
memcpy(internal + 0x8, chunk, xma->chunk_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create main RIFF */
|
|
||||||
head_size = 4+4 + 4 + internal_size + 4+4;
|
|
||||||
file_size = head_size-4-4 + xma->data_size;
|
|
||||||
if (head_size > buf_size) goto fail;
|
|
||||||
|
|
||||||
memcpy(buf + 0x0, use_be ? "RIFX" : "RIFF", 4);
|
|
||||||
put_32bit(buf + 0x4, file_size);
|
|
||||||
memcpy(buf + 0x8, "WAVE", 4);
|
|
||||||
memcpy(buf + 0xc, internal, internal_size);
|
|
||||||
memcpy(buf + head_size-4-4, "data", 4);
|
|
||||||
put_32bit(buf + head_size-4, xma->data_size);
|
|
||||||
|
|
||||||
return head_size;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/**
|
/**
|
||||||
* Get real XMA sample rate (from Microsoft docs).
|
* Get real XMA sample rate (from Microsoft docs).
|
||||||
|
@ -428,5 +146,3 @@ static int32_t get_xma_sample_rate(int32_t general_rate) {
|
||||||
return xma_rate;
|
return xma_rate;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,12 +5,21 @@
|
||||||
/* most info from XWBtool, xactwb.h, xact2wb.h and xact3wb.h */
|
/* most info from XWBtool, xactwb.h, xact2wb.h and xact3wb.h */
|
||||||
|
|
||||||
#define WAVEBANK_FLAGS_COMPACT 0x00020000 // Bank uses compact format
|
#define WAVEBANK_FLAGS_COMPACT 0x00020000 // Bank uses compact format
|
||||||
#define WAVEBANKENTRY_FLAGS_IGNORELOOP 0x00000008 // Used internally when the loop region can't be used
|
#define WAVEBANKENTRY_FLAGS_IGNORELOOP 0x00000008 // Used internally when the loop region can't be used (no idea...)
|
||||||
|
|
||||||
static const int32_t wma_avg_bps_index[] = { /*7*/
|
/* the x.x version is just to make it clearer, MS only classifies XACT as 1/2/3 */
|
||||||
|
#define XACT1_0_MAX 1 /* Project Gotham Racing 2 (v1), Silent Hill 4 (v1) */
|
||||||
|
#define XACT1_1_MAX 3 /* The King of Fighters 2003 (v3) */
|
||||||
|
#define XACT2_0_MAX 34 /* Dead or Alive 4 (v17), Kameo (v23), Table Tennis (v34) */ // v35/36/37 too?
|
||||||
|
#define XACT2_1_MAX 38 /* Prey (v38) */ // v39 too?
|
||||||
|
#define XACT2_2_MAX 41 /* Blue Dragon (v40) */
|
||||||
|
#define XACT3_0_MAX 46 /* Ninja Blade (t43 v42), Persona 4 Ultimax NESSICA (t45 v43) */
|
||||||
|
#define XACT_TECHLAND 0x10000 /* Sniper Ghost Warrior, Nail'd (PS3/X360) */
|
||||||
|
|
||||||
|
static const int wma_avg_bps_index[7] = {
|
||||||
12000, 24000, 4000, 6000, 8000, 20000, 2500
|
12000, 24000, 4000, 6000, 8000, 20000, 2500
|
||||||
};
|
};
|
||||||
static const int32_t wma_block_align_index[] = { /*17*/
|
static const int wma_block_align_index[17] = {
|
||||||
929, 1487, 1280, 2230, 8917, 8192, 4459, 5945, 2304, 1536, 1485, 1008, 2731, 4096, 6827, 5462, 1280
|
929, 1487, 1280, 2230, 8917, 8192, 4459, 5945, 2304, 1536, 1485, 1008, 2731, 4096, 6827, 5462, 1280
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,8 +27,6 @@ static const int32_t wma_block_align_index[] = { /*17*/
|
||||||
typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3 } xact_codec;
|
typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3 } xact_codec;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int little_endian;
|
int little_endian;
|
||||||
int xact; /* rough XACT version (1/2/3) */
|
|
||||||
|
|
||||||
int version;
|
int version;
|
||||||
|
|
||||||
/* segments */
|
/* segments */
|
||||||
|
@ -83,43 +90,47 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
|
|
||||||
/* read main header (WAVEBANKHEADER) */
|
/* read main header (WAVEBANKHEADER) */
|
||||||
xwb.version = read_32bit(0x04, streamFile);
|
xwb.version = read_32bit(0x04, streamFile); /* XACT3: 0x04=tool version, 0x08=header version */
|
||||||
if (xwb.version <= 3) {
|
|
||||||
xwb.xact = 1; /* XACT1: XBOX [The King of Fighters 2003] */
|
|
||||||
} else if (xwb.version < 42) {
|
|
||||||
xwb.xact = 2; /* XACT2: early XBOX360 [Kameo, Table Tennis, Blue Dragon], Windows */
|
|
||||||
} else { /* highest seen: tool=v46, header=v44 */
|
|
||||||
xwb.xact = 3; /* XACT3: late XBOX360, Windows */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read segment offsets (SEGIDX) */
|
/* read segment offsets (SEGIDX) */
|
||||||
off = xwb.xact <= 2 ? 0x08 : 0x0c; /* XACT3: 0x04=tool version, 0x08=header version */
|
if (xwb.version <= XACT1_0_MAX) {
|
||||||
xwb.base_offset = read_32bit(off+0x00, streamFile);//BANKDATA
|
xwb.streams = read_32bit(0x0c, streamFile);
|
||||||
xwb.base_size = read_32bit(off+0x04, streamFile);
|
/* 0x10: bank name */
|
||||||
xwb.entry_offset= read_32bit(off+0x08, streamFile);//ENTRYMETADATA
|
xwb.entry_elem_size = 0x14;
|
||||||
xwb.entry_size = read_32bit(off+0x0c, streamFile);
|
xwb.entry_offset= 0x50;
|
||||||
/* go to last segment (XACT2/3 have 5 segments, XACT1 4) */
|
xwb.entry_size = xwb.entry_elem_size * xwb.streams;
|
||||||
//0x10: XACT1/2: ENTRYNAMES, XACT3: SEEKTABLES
|
xwb.data_offset = xwb.entry_offset + xwb.entry_size;
|
||||||
//0x14: XACT1: none (ENTRYWAVEDATA), XACT2: EXTRA, XACT3: ENTRYNAMES
|
xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset;
|
||||||
suboff = xwb.xact >= 2 ? 0x08+0x08 : 0x08;
|
}
|
||||||
xwb.data_offset = read_32bit(off+0x10+suboff, streamFile);//ENTRYWAVEDATA
|
else {
|
||||||
xwb.data_size = read_32bit(off+0x14+suboff, streamFile);
|
off = xwb.version <= XACT2_2_MAX ? 0x08 : 0x0c;
|
||||||
|
xwb.base_offset = read_32bit(off+0x00, streamFile);//BANKDATA
|
||||||
|
xwb.base_size = read_32bit(off+0x04, streamFile);
|
||||||
|
xwb.entry_offset= read_32bit(off+0x08, streamFile);//ENTRYMETADATA
|
||||||
|
xwb.entry_size = read_32bit(off+0x0c, streamFile);
|
||||||
|
/* go to last segment (XACT2/3 have 5 segments, XACT1 4) */
|
||||||
|
//0x10: XACT1/2: ENTRYNAMES, XACT3: SEEKTABLES
|
||||||
|
//0x14: XACT1: none (ENTRYWAVEDATA), XACT2: EXTRA, XACT3: ENTRYNAMES
|
||||||
|
suboff = xwb.version <= XACT1_1_MAX ? 0x08 : 0x08+0x08;
|
||||||
|
xwb.data_offset = read_32bit(off+0x10+suboff, streamFile);//ENTRYWAVEDATA
|
||||||
|
xwb.data_size = read_32bit(off+0x14+suboff, streamFile);
|
||||||
|
|
||||||
/* for Silent Hill 4 Xbox fake XWB and Techland's XWB with no data */
|
/* for Techland's XWB with no data */
|
||||||
if (xwb.base_offset == 0) goto fail;
|
if (xwb.base_offset == 0) goto fail;
|
||||||
if (xwb.data_offset + xwb.data_size != get_streamfile_size(streamFile)) goto fail;
|
if (xwb.data_offset + xwb.data_size != get_streamfile_size(streamFile)) goto fail;
|
||||||
|
|
||||||
/* read base entry (WAVEBANKDATA) */
|
/* read base entry (WAVEBANKDATA) */
|
||||||
off = xwb.base_offset;
|
off = xwb.base_offset;
|
||||||
xwb.base_flags = (uint32_t)read_32bit(off+0x00, streamFile);
|
xwb.base_flags = (uint32_t)read_32bit(off+0x00, streamFile);
|
||||||
xwb.streams = read_32bit(off+0x04, streamFile);
|
xwb.streams = read_32bit(off+0x04, streamFile);
|
||||||
/* 0x08 bank_name */
|
/* 0x08 bank_name */
|
||||||
suboff = 0x08 + (xwb.xact == 1 ? 0x10 : 0x40);
|
suboff = 0x08 + (xwb.version <= XACT1_1_MAX ? 0x10 : 0x40);
|
||||||
xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile);
|
xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile);
|
||||||
/* suboff+0x04: meta name entry size */
|
/* suboff+0x04: meta name entry size */
|
||||||
xwb.entry_alignment = read_32bit(off+suboff+0x08, streamFile); /* usually 1 dvd sector */
|
xwb.entry_alignment = read_32bit(off+suboff+0x08, streamFile); /* usually 1 dvd sector */
|
||||||
xwb.format = read_32bit(off+suboff+0x0c, streamFile); /* compact mode only */
|
xwb.format = read_32bit(off+suboff+0x0c, streamFile); /* compact mode only */
|
||||||
/* suboff+0x10: build time 64b (XACT2/3) */
|
/* suboff+0x10: build time 64b (XACT2/3) */
|
||||||
|
}
|
||||||
|
|
||||||
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
|
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
|
||||||
if (target_stream < 0 || target_stream > xwb.streams || xwb.streams < 1) goto fail;
|
if (target_stream < 0 || target_stream > xwb.streams || xwb.streams < 1) goto fail;
|
||||||
|
@ -142,27 +153,34 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
xwb.stream_size = xwb.data_size;
|
xwb.stream_size = xwb.data_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (xwb.version <= XACT1_0_MAX) {
|
||||||
|
xwb.format = (uint32_t)read_32bit(off+0x00, streamFile);
|
||||||
|
xwb.stream_offset = xwb.data_offset + (uint32_t)read_32bit(off+0x04, streamFile);
|
||||||
|
xwb.stream_size = (uint32_t)read_32bit(off+0x08, streamFile);
|
||||||
|
|
||||||
|
xwb.loop_start = (uint32_t)read_32bit(off+0x0c, streamFile);
|
||||||
|
xwb.loop_end = (uint32_t)read_32bit(off+0x10, streamFile);//length
|
||||||
|
|
||||||
|
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
uint32_t entry_info = (uint32_t)read_32bit(off+0x00, streamFile);
|
uint32_t entry_info = (uint32_t)read_32bit(off+0x00, streamFile);
|
||||||
if (xwb.xact == 1) {
|
if (xwb.version <= XACT1_1_MAX) {
|
||||||
xwb.entry_flags = entry_info;
|
xwb.entry_flags = entry_info;
|
||||||
} else {
|
} else {
|
||||||
xwb.entry_flags = (entry_info) & 0xF; /*4*/
|
xwb.entry_flags = (entry_info) & 0xF; /*4b*/
|
||||||
xwb.num_samples = (entry_info >> 4) & 0x0FFFFFFF; /*28*/
|
xwb.num_samples = (entry_info >> 4) & 0x0FFFFFFF; /*28b*/
|
||||||
}
|
}
|
||||||
xwb.format = (uint32_t)read_32bit(off+0x04, streamFile);
|
xwb.format = (uint32_t)read_32bit(off+0x04, streamFile);
|
||||||
xwb.stream_offset = xwb.data_offset + (uint32_t)read_32bit(off+0x08, streamFile);
|
xwb.stream_offset = xwb.data_offset + (uint32_t)read_32bit(off+0x08, streamFile);
|
||||||
xwb.stream_size = (uint32_t)read_32bit(off+0x0c, streamFile);
|
xwb.stream_size = (uint32_t)read_32bit(off+0x0c, streamFile);
|
||||||
|
|
||||||
if (xwb.xact == 1) { //LoopRegion (bytes within data)
|
if (xwb.version <= XACT2_1_MAX) { /* LoopRegion (bytes) */
|
||||||
xwb.loop_start = (uint32_t)read_32bit(off+0x10, streamFile);
|
xwb.loop_start = (uint32_t)read_32bit(off+0x10, streamFile);
|
||||||
xwb.loop_end = (uint32_t)read_32bit(off+0x14, streamFile);//length
|
xwb.loop_end = (uint32_t)read_32bit(off+0x14, streamFile);//length (LoopRegion) or offset (XMALoopRegion in late XACT2)
|
||||||
} else if (xwb.xact == 2 && xwb.version <= 38) {//LoopRegion (bytes within data) or XMALoopRegion (bits within data)
|
} else { /* LoopRegion (samples) */
|
||||||
xwb.loop_start = (uint32_t)read_32bit(off+0x10, streamFile);
|
|
||||||
xwb.loop_end = (uint32_t)read_32bit(off+0x14, streamFile);//length (LoopRegion) or offset (XMALoopRegion)
|
|
||||||
} else {//LoopRegion (samples)
|
|
||||||
xwb.loop_start_sample = (uint32_t)read_32bit(off+0x10, streamFile);
|
xwb.loop_start_sample = (uint32_t)read_32bit(off+0x10, streamFile);
|
||||||
xwb.loop_end_sample = xwb.loop_start_sample + (uint32_t)read_32bit(off+0x14, streamFile);
|
xwb.loop_end_sample = (uint32_t)read_32bit(off+0x14, streamFile) + xwb.loop_start_sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start)
|
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start)
|
||||||
|
@ -171,40 +189,52 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
|
|
||||||
/* parse format */
|
/* parse format */
|
||||||
if (xwb.xact == 1) {
|
if (xwb.version <= XACT1_0_MAX) {
|
||||||
xwb.bits_per_sample = (xwb.format >> 31) & 0x1; /*1*/
|
xwb.bits_per_sample = (xwb.format >> 31) & 0x1; /*1b*/
|
||||||
xwb.sample_rate = (xwb.format >> 5) & 0x3FFFFFF; /*26*/
|
xwb.sample_rate = (xwb.format >> 4) & 0x7FFFFFF; /*27b*/
|
||||||
xwb.channels = (xwb.format >> 2) & 0x7; /*3*/
|
xwb.channels = (xwb.format >> 1) & 0x7; /*3b*/
|
||||||
xwb.tag = (xwb.format) & 0x3; /*2*/
|
xwb.tag = (xwb.format) & 0x1; /*1b*/
|
||||||
}
|
}
|
||||||
else if (xwb.version <= 34) { /* early XACT2, not sure if includes v35/36 */
|
else if (xwb.version <= XACT1_1_MAX) {
|
||||||
xwb.bits_per_sample = (xwb.format >> 31) & 0x1; /*1*/
|
xwb.bits_per_sample = (xwb.format >> 31) & 0x1; /*1b*/
|
||||||
xwb.block_align = (xwb.format >> 24) & 0xFF; /*8*/
|
xwb.sample_rate = (xwb.format >> 5) & 0x3FFFFFF; /*26b*/
|
||||||
xwb.sample_rate = (xwb.format >> 4) & 0x7FFFF; /*19*/
|
xwb.channels = (xwb.format >> 2) & 0x7; /*3b*/
|
||||||
xwb.channels = (xwb.format >> 1) & 0x7; /*3*/
|
xwb.tag = (xwb.format) & 0x3; /*2b*/
|
||||||
xwb.tag = (xwb.format) & 0x1; /*1*/
|
}
|
||||||
|
else if (xwb.version <= XACT2_0_MAX) {
|
||||||
|
xwb.bits_per_sample = (xwb.format >> 31) & 0x1; /*1b*/
|
||||||
|
xwb.block_align = (xwb.format >> 24) & 0xFF; /*8b*/
|
||||||
|
xwb.sample_rate = (xwb.format >> 4) & 0x7FFFF; /*19b*/
|
||||||
|
xwb.channels = (xwb.format >> 1) & 0x7; /*3b*/
|
||||||
|
xwb.tag = (xwb.format) & 0x1; /*1b*/
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
xwb.bits_per_sample = (xwb.format >> 31) & 0x1; /*1*/
|
xwb.bits_per_sample = (xwb.format >> 31) & 0x1; /*1b*/
|
||||||
xwb.block_align = (xwb.format >> 23) & 0xFF; /*8*/
|
xwb.block_align = (xwb.format >> 23) & 0xFF; /*8b*/
|
||||||
xwb.sample_rate = (xwb.format >> 5) & 0x3FFFF; /*18*/
|
xwb.sample_rate = (xwb.format >> 5) & 0x3FFFF; /*18b*/
|
||||||
xwb.channels = (xwb.format >> 2) & 0x7; /*3*/
|
xwb.channels = (xwb.format >> 2) & 0x7; /*3b*/
|
||||||
xwb.tag = (xwb.format) & 0x3; /*2*/
|
xwb.tag = (xwb.format) & 0x3; /*2b*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* standardize tag to codec */
|
/* standardize tag to codec */
|
||||||
if (xwb.xact == 1) {
|
if (xwb.version <= XACT1_0_MAX) {
|
||||||
|
switch(xwb.tag){
|
||||||
|
case 0: xwb.codec = PCM; break;
|
||||||
|
case 1: xwb.codec = XBOX_ADPCM; break;
|
||||||
|
default: goto fail;
|
||||||
|
}
|
||||||
|
} else if (xwb.version <= XACT1_1_MAX) {
|
||||||
switch(xwb.tag){
|
switch(xwb.tag){
|
||||||
case 0: xwb.codec = PCM; break;
|
case 0: xwb.codec = PCM; break;
|
||||||
case 1: xwb.codec = XBOX_ADPCM; break;
|
case 1: xwb.codec = XBOX_ADPCM; break;
|
||||||
case 2: xwb.codec = WMA; break;
|
case 2: xwb.codec = WMA; break;
|
||||||
default: goto fail;
|
default: goto fail;
|
||||||
}
|
}
|
||||||
} else if (xwb.xact == 2) {
|
} else if (xwb.version <= XACT2_2_MAX) {
|
||||||
switch(xwb.tag) {
|
switch(xwb.tag) {
|
||||||
case 0: xwb.codec = PCM; break;
|
case 0: xwb.codec = PCM; break;
|
||||||
/* Table Tennis (v34): XMA1, Prey (v38): XMA2, v35/36/37: ? */
|
/* Table Tennis (v34): XMA1, Prey (v38): XMA2, v35/36/37: ? */
|
||||||
case 1: xwb.codec = xwb.version <= 34 ? XMA1 : XMA2; break;
|
case 1: xwb.codec = xwb.version <= XACT2_0_MAX ? XMA1 : XMA2; break;
|
||||||
case 2: xwb.codec = MS_ADPCM; break;
|
case 2: xwb.codec = MS_ADPCM; break;
|
||||||
default: goto fail;
|
default: goto fail;
|
||||||
}
|
}
|
||||||
|
@ -220,60 +250,59 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
|
|
||||||
/* Techland's bizarre format hijack (Nail'd, Sniper: Ghost Warrior PS3).
|
/* Techland's bizarre format hijack (Nail'd, Sniper: Ghost Warrior PS3).
|
||||||
* Somehow they used XWB + ATRAC3 in their PS3 games, very creative */
|
* Somehow they used XWB + ATRAC3 in their PS3 games, very creative */
|
||||||
if (xwb.version == 0x10000 && xwb.codec == XMA2 /* v 0x10000 is used in their X360 games too */
|
if (xwb.version == XACT_TECHLAND && xwb.codec == XMA2 /* XACT_TECHLAND used in their X360 games too */
|
||||||
&& (xwb.block_align == 0x60 || xwb.block_align == 0x98 || xwb.block_align == 0xc0) ) {
|
&& (xwb.block_align == 0x60 || xwb.block_align == 0x98 || xwb.block_align == 0xc0) ) {
|
||||||
xwb.codec = ATRAC3; /* standard ATRAC3 blocks sizes; no other way to identify (other than reading data) */
|
xwb.codec = ATRAC3; /* standard ATRAC3 blocks sizes; no other way to identify (other than reading data) */
|
||||||
|
|
||||||
/* num samples uses a modified entry_info format (maybe skip samples + samples? sfx use the standard format)
|
/* num samples uses a modified entry_info format (maybe skip samples + samples? sfx use the standard format)
|
||||||
* ignore for now and just calc max samples */ //todo
|
* ignore for now and just calc max samples */
|
||||||
xwb.num_samples = xwb.stream_size / (xwb.block_align * xwb.channels) * 1024;
|
xwb.num_samples = atrac3_bytes_to_samples(xwb.stream_size, xwb.block_align * xwb.channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* fix samples */
|
/* fix samples */
|
||||||
if ((xwb.xact == 1 || xwb.xact == 2) && xwb.codec == PCM) {
|
if (xwb.version <= XACT2_2_MAX && xwb.codec == PCM) {
|
||||||
xwb.num_samples = xwb.stream_size / 2 / xwb.channels;
|
int bits_per_sample = xwb.bits_per_sample == 0 ? 8 : 16;
|
||||||
|
xwb.num_samples = pcm_bytes_to_samples(xwb.stream_size, xwb.channels, bits_per_sample);
|
||||||
if (xwb.loop_flag) {
|
if (xwb.loop_flag) {
|
||||||
xwb.loop_start_sample = (xwb.loop_start) / 2 / xwb.channels;
|
xwb.loop_start_sample = pcm_bytes_to_samples(xwb.loop_start, xwb.channels, bits_per_sample);
|
||||||
xwb.loop_end_sample = (xwb.loop_start + xwb.loop_end) / 2 / xwb.channels;
|
xwb.loop_end_sample = pcm_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.channels, bits_per_sample);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xwb.xact == 1 && xwb.codec == XBOX_ADPCM) {
|
else if (xwb.version <= XACT1_1_MAX && xwb.codec == XBOX_ADPCM) {
|
||||||
xwb.num_samples = xwb.stream_size / 36 / xwb.channels*64;
|
xwb.block_align = 0x24 * xwb.channels;
|
||||||
|
xwb.num_samples = ms_ima_bytes_to_samples(xwb.stream_size, xwb.block_align, xwb.channels);
|
||||||
if (xwb.loop_flag) {
|
if (xwb.loop_flag) {
|
||||||
xwb.loop_start_sample = xwb.loop_start / 36 / xwb.channels*64;
|
xwb.loop_start_sample = ms_ima_bytes_to_samples(xwb.loop_start, xwb.block_align, xwb.channels);
|
||||||
xwb.loop_end_sample = (xwb.loop_start + xwb.loop_end) / 36 / xwb.channels*64;
|
xwb.loop_end_sample = ms_ima_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.block_align, xwb.channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xwb.xact == 2 && xwb.codec == MS_ADPCM && xwb.loop_flag) {
|
else if (xwb.version <= XACT2_2_MAX && xwb.codec == MS_ADPCM && xwb.loop_flag) {
|
||||||
int block_size, samples_per_frame;
|
int block_size = (xwb.block_align + 22) * xwb.channels; /*22=CONVERSION_OFFSET (?)*/
|
||||||
block_size = (xwb.block_align + 22) * xwb.channels; /*22=CONVERSION_OFFSET (?)*/
|
|
||||||
samples_per_frame = (block_size-(7-1) * xwb.channels) * 2 / xwb.channels;
|
|
||||||
|
|
||||||
xwb.loop_start_sample = (xwb.loop_start) / block_size / samples_per_frame;
|
xwb.loop_start_sample = msadpcm_bytes_to_samples(xwb.loop_start, block_size, xwb.channels);
|
||||||
xwb.loop_end_sample = (xwb.loop_start + xwb.loop_end) / block_size / samples_per_frame;
|
xwb.loop_end_sample = msadpcm_bytes_to_samples(xwb.loop_start + xwb.loop_end, block_size, xwb.channels);
|
||||||
}
|
}
|
||||||
else if (xwb.xact == 2 && xwb.version <= 38 /* v38: byte offset, v40+: sample offset, v39: ? */
|
else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
|
||||||
&& (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
|
/* v38: byte offset, v40+: sample offset, v39: ? */
|
||||||
#ifdef VGM_USE_FFMPEG
|
|
||||||
/* need to manually find sample offsets, thanks to Microsoft dumb headers */
|
/* need to manually find sample offsets, thanks to Microsoft dumb headers */
|
||||||
xma_sample_data xma_sd;
|
ms_sample_data msd;
|
||||||
memset(&xma_sd,0,sizeof(xma_sample_data));
|
memset(&msd,0,sizeof(ms_sample_data));
|
||||||
|
|
||||||
xma_sd.xma_version = xwb.codec == XMA1 ? 1 : 2;
|
msd.xma_version = xwb.codec == XMA1 ? 1 : 2;
|
||||||
xma_sd.channels = xwb.channels;
|
msd.channels = xwb.channels;
|
||||||
xma_sd.data_offset = xwb.stream_offset;
|
msd.data_offset = xwb.stream_offset;
|
||||||
xma_sd.data_size = xwb.stream_size;
|
msd.data_size = xwb.stream_size;
|
||||||
xma_sd.loop_flag = xwb.loop_flag;
|
msd.loop_flag = xwb.loop_flag;
|
||||||
xma_sd.loop_start_b = xwb.loop_start; /* bit offset in the stream */
|
msd.loop_start_b = xwb.loop_start; /* bit offset in the stream */
|
||||||
xma_sd.loop_end_b = (xwb.loop_end >> 4); /*28b */
|
msd.loop_end_b = (xwb.loop_end >> 4); /*28b */
|
||||||
/* XACT adds +1 to the subframe, but this means 0 can't be used? */
|
/* XACT adds +1 to the subframe, but this means 0 can't be used? */
|
||||||
xma_sd.loop_end_subframe = ((xwb.loop_end >> 2) & 0x3) + 1; /* 2b */
|
msd.loop_end_subframe = ((xwb.loop_end >> 2) & 0x3) + 1; /* 2b */
|
||||||
xma_sd.loop_start_subframe = ((xwb.loop_end >> 0) & 0x3) + 1; /* 2b */
|
msd.loop_start_subframe = ((xwb.loop_end >> 0) & 0x3) + 1; /* 2b */
|
||||||
|
|
||||||
xma_get_samples(&xma_sd, streamFile);
|
xma_get_samples(&msd, streamFile);
|
||||||
xwb.loop_start_sample = xma_sd.loop_start_sample;
|
xwb.loop_start_sample = msd.loop_start_sample;
|
||||||
xwb.loop_end_sample = xma_sd.loop_end_sample;
|
xwb.loop_end_sample = msd.loop_end_sample;
|
||||||
|
|
||||||
// todo fix properly (XWB loop_start/end seem to count padding samples while XMA1 RIFF doesn't)
|
// todo fix properly (XWB loop_start/end seem to count padding samples while XMA1 RIFF doesn't)
|
||||||
//this doesn't seem ok because can fall within 0 to 512 (ie.- first frame)
|
//this doesn't seem ok because can fall within 0 to 512 (ie.- first frame)
|
||||||
|
@ -283,9 +312,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
//add padding back until it's fixed (affects looping)
|
//add padding back until it's fixed (affects looping)
|
||||||
// (in rare cases this causes a glitch in FFmpeg since it has a bug where it's missing some samples)
|
// (in rare cases this causes a glitch in FFmpeg since it has a bug where it's missing some samples)
|
||||||
xwb.num_samples += 64 + 512;
|
xwb.num_samples += 64 + 512;
|
||||||
#else
|
|
||||||
goto fail;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -296,7 +322,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
vgmstream->sample_rate = xwb.sample_rate;
|
vgmstream->sample_rate = xwb.sample_rate;
|
||||||
vgmstream->num_samples = xwb.num_samples;
|
vgmstream->num_samples = xwb.num_samples;
|
||||||
vgmstream->loop_start_sample = xwb.loop_start_sample;
|
vgmstream->loop_start_sample = xwb.loop_start_sample;
|
||||||
vgmstream->loop_end_sample = xwb.loop_end_sample;
|
vgmstream->loop_end_sample = xwb.loop_end_sample;
|
||||||
vgmstream->num_streams = xwb.streams;
|
vgmstream->num_streams = xwb.streams;
|
||||||
vgmstream->meta_type = meta_XWB;
|
vgmstream->meta_type = meta_XWB;
|
||||||
|
|
||||||
|
@ -380,7 +406,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
block_align = wma_block_align_index[block_index];
|
block_align = wma_block_align_index[block_index];
|
||||||
wma_codec = xwb.bits_per_sample ? 0x162 : 0x161; /* 0=WMAudio2, 1=WMAudio3 */
|
wma_codec = xwb.bits_per_sample ? 0x162 : 0x161; /* 0=WMAudio2, 1=WMAudio3 */
|
||||||
|
|
||||||
bytes = ffmpeg_make_riff_xwma(buf, 100, wma_codec, vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align);
|
bytes = ffmpeg_make_riff_xwma(buf, 100, wma_codec, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align);
|
||||||
if (bytes <= 0) goto fail;
|
if (bytes <= 0) goto fail;
|
||||||
|
|
||||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, xwb.stream_offset,xwb.stream_size);
|
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, xwb.stream_offset,xwb.stream_size);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "streamtypes.h"
|
#include "streamtypes.h"
|
||||||
|
|
||||||
int check_sample_rate(int32_t sr) {
|
int check_sample_rate(int32_t sr) {
|
||||||
return !(sr<1000 || sr>96000);
|
return !(sr<300 || sr>96000);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * filename_extension(const char * filename) {
|
const char * filename_extension(const char * filename) {
|
||||||
|
|
|
@ -11,6 +11,12 @@
|
||||||
#include "layout/layout.h"
|
#include "layout/layout.h"
|
||||||
#include "coding/coding.h"
|
#include "coding/coding.h"
|
||||||
|
|
||||||
|
/* See if there is a second file which may be the second channel, given
|
||||||
|
* already opened mono opened_stream which was opened from filename.
|
||||||
|
* If a suitable file is found, open it and change opened_stream to a stereo stream. */
|
||||||
|
static void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of functions that will recognize files. These should correspond pretty
|
* List of functions that will recognize files. These should correspond pretty
|
||||||
* directly to the metadata types
|
* directly to the metadata types
|
||||||
|
@ -342,9 +348,14 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
||||||
init_vgmstream_akb2_multi,
|
init_vgmstream_akb2_multi,
|
||||||
init_vgmstream_x360_ast,
|
init_vgmstream_x360_ast,
|
||||||
init_vgmstream_wwise,
|
init_vgmstream_wwise,
|
||||||
|
init_vgmstream_ubi_raki,
|
||||||
|
init_vgmstream_x360_pasx,
|
||||||
|
init_vgmstream_x360_nub,
|
||||||
|
init_vgmstream_xma,
|
||||||
|
init_vgmstream_sxd,
|
||||||
|
init_vgmstream_ogl,
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
init_vgmstream_xma,
|
|
||||||
init_vgmstream_mp4_aac_ffmpeg,
|
init_vgmstream_mp4_aac_ffmpeg,
|
||||||
init_vgmstream_bik,
|
init_vgmstream_bik,
|
||||||
|
|
||||||
|
@ -371,6 +382,7 @@ VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) {
|
||||||
/* fail if there is nothing to play
|
/* fail if there is nothing to play
|
||||||
* (without this check vgmstream can generate empty files) */
|
* (without this check vgmstream can generate empty files) */
|
||||||
if (vgmstream->num_samples <= 0) {
|
if (vgmstream->num_samples <= 0) {
|
||||||
|
VGM_LOG("VGMSTREAM: wrong num_samples (ns=%i)\n", vgmstream->num_samples);
|
||||||
close_vgmstream(vgmstream);
|
close_vgmstream(vgmstream);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -378,6 +390,7 @@ VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) {
|
||||||
/* everything should have a reasonable sample rate
|
/* everything should have a reasonable sample rate
|
||||||
* (a verification of the metadata) */
|
* (a verification of the metadata) */
|
||||||
if (!check_sample_rate(vgmstream->sample_rate)) {
|
if (!check_sample_rate(vgmstream->sample_rate)) {
|
||||||
|
VGM_LOG("VGMSTREAM: wrong sample rate (sr=%i)\n", vgmstream->sample_rate);
|
||||||
close_vgmstream(vgmstream);
|
close_vgmstream(vgmstream);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -388,7 +401,7 @@ VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) {
|
||||||
|| (vgmstream->loop_end_sample > vgmstream->num_samples)
|
|| (vgmstream->loop_end_sample > vgmstream->num_samples)
|
||||||
|| (vgmstream->loop_start_sample < 0) ) {
|
|| (vgmstream->loop_start_sample < 0) ) {
|
||||||
vgmstream->loop_flag = 0;
|
vgmstream->loop_flag = 0;
|
||||||
VGM_LOG("VGMSTREAM: wrong loops ignored (lss==%i, lse=%i, ns=%i)\n", vgmstream->loop_start_sample, vgmstream->loop_end_sample, vgmstream->num_samples);
|
VGM_LOG("VGMSTREAM: wrong loops ignored (lss=%i, lse=%i, ns=%i)\n", vgmstream->loop_start_sample, vgmstream->loop_end_sample, vgmstream->num_samples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,6 +489,14 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
|
||||||
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
||||||
reset_fsb_vorbis(vgmstream);
|
reset_fsb_vorbis(vgmstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type==coding_wwise_vorbis) {
|
||||||
|
reset_wwise_vorbis(vgmstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type==coding_ogl_vorbis) {
|
||||||
|
reset_ogl_vorbis(vgmstream);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (vgmstream->coding_type==coding_CRI_HCA) {
|
if (vgmstream->coding_type==coding_CRI_HCA) {
|
||||||
hca_codec_data *data = vgmstream->codec_data;
|
hca_codec_data *data = vgmstream->codec_data;
|
||||||
|
@ -679,6 +700,16 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
||||||
free_fsb_vorbis(vgmstream->codec_data);
|
free_fsb_vorbis(vgmstream->codec_data);
|
||||||
vgmstream->codec_data = NULL;
|
vgmstream->codec_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type==coding_wwise_vorbis) {
|
||||||
|
free_wwise_vorbis(vgmstream->codec_data);
|
||||||
|
vgmstream->codec_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type==coding_ogl_vorbis) {
|
||||||
|
free_ogl_vorbis(vgmstream->codec_data);
|
||||||
|
vgmstream->codec_data = NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (vgmstream->coding_type==coding_CRI_HCA) {
|
if (vgmstream->coding_type==coding_CRI_HCA) {
|
||||||
|
@ -1000,6 +1031,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
case coding_ogg_vorbis:
|
case coding_ogg_vorbis:
|
||||||
case coding_fsb_vorbis:
|
case coding_fsb_vorbis:
|
||||||
|
case coding_wwise_vorbis:
|
||||||
|
case coding_ogl_vorbis:
|
||||||
#endif
|
#endif
|
||||||
#ifdef VGM_USE_MPEG
|
#ifdef VGM_USE_MPEG
|
||||||
case coding_fake_MPEG2_L2:
|
case coding_fake_MPEG2_L2:
|
||||||
|
@ -1070,6 +1103,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||||
return 64;
|
return 64;
|
||||||
case coding_MS_IMA:
|
case coding_MS_IMA:
|
||||||
case coding_RAD_IMA:
|
case coding_RAD_IMA:
|
||||||
|
case coding_WWISE_IMA:
|
||||||
return (vgmstream->interleave_block_size-4*vgmstream->channels)*2/vgmstream->channels;
|
return (vgmstream->interleave_block_size-4*vgmstream->channels)*2/vgmstream->channels;
|
||||||
case coding_RAD_IMA_mono:
|
case coding_RAD_IMA_mono:
|
||||||
return 32;
|
return 32;
|
||||||
|
@ -1159,6 +1193,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||||
case coding_RAD_IMA:
|
case coding_RAD_IMA:
|
||||||
case coding_NDS_IMA:
|
case coding_NDS_IMA:
|
||||||
case coding_DAT4_IMA:
|
case coding_DAT4_IMA:
|
||||||
|
case coding_WWISE_IMA:
|
||||||
return vgmstream->interleave_block_size;
|
return vgmstream->interleave_block_size;
|
||||||
case coding_RAD_IMA_mono:
|
case coding_RAD_IMA_mono:
|
||||||
return 0x14;
|
return 0x14;
|
||||||
|
@ -1484,6 +1519,18 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||||
buffer+samples_written*vgmstream->channels,samples_to_do,
|
buffer+samples_written*vgmstream->channels,samples_to_do,
|
||||||
vgmstream->channels);
|
vgmstream->channels);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case coding_wwise_vorbis:
|
||||||
|
decode_wwise_vorbis(vgmstream,
|
||||||
|
buffer+samples_written*vgmstream->channels,samples_to_do,
|
||||||
|
vgmstream->channels);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case coding_ogl_vorbis:
|
||||||
|
decode_ogl_vorbis(vgmstream,
|
||||||
|
buffer+samples_written*vgmstream->channels,samples_to_do,
|
||||||
|
vgmstream->channels);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case coding_CRI_HCA:
|
case coding_CRI_HCA:
|
||||||
decode_hca(vgmstream->codec_data,
|
decode_hca(vgmstream->codec_data,
|
||||||
|
@ -1584,6 +1631,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||||
samples_to_do,chan);
|
samples_to_do,chan);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case coding_WWISE_IMA:
|
||||||
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
|
decode_wwise_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||||
|
vgmstream->channels,vgmstream->samples_into_block,
|
||||||
|
samples_to_do,chan);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case coding_WS:
|
case coding_WS:
|
||||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
|
@ -1798,6 +1852,14 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) {
|
||||||
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
if (vgmstream->coding_type==coding_fsb_vorbis) {
|
||||||
seek_fsb_vorbis(vgmstream, vgmstream->loop_start_sample);
|
seek_fsb_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type==coding_wwise_vorbis) {
|
||||||
|
seek_wwise_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vgmstream->coding_type==coding_ogl_vorbis) {
|
||||||
|
seek_ogl_vorbis(vgmstream, vgmstream->loop_start_sample);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
@ -1994,7 +2056,7 @@ const char * const dfs_pairs[][2] = {
|
||||||
};
|
};
|
||||||
#define DFS_PAIR_COUNT (sizeof(dfs_pairs)/sizeof(dfs_pairs[0]))
|
#define DFS_PAIR_COUNT (sizeof(dfs_pairs)/sizeof(dfs_pairs[0]))
|
||||||
|
|
||||||
void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile) {
|
static void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile) {
|
||||||
char filename[PATH_LIMIT];
|
char filename[PATH_LIMIT];
|
||||||
char filename2[PATH_LIMIT];
|
char filename2[PATH_LIMIT];
|
||||||
char * ext;
|
char * ext;
|
||||||
|
|
|
@ -130,9 +130,10 @@ typedef enum {
|
||||||
coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */
|
coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */
|
||||||
coding_OTNS_IMA, /* Omikron The Nomad Soul IMA ADPCM */
|
coding_OTNS_IMA, /* Omikron The Nomad Soul IMA ADPCM */
|
||||||
coding_FSB_IMA, /* FMOD's FSB multichannel IMA ADPCM */
|
coding_FSB_IMA, /* FMOD's FSB multichannel IMA ADPCM */
|
||||||
|
coding_WWISE_IMA, /* Audiokinetic Wwise IMA ADPCM */
|
||||||
|
|
||||||
coding_WS, /* Westwood Studios VBR ADPCM */
|
|
||||||
coding_MSADPCM, /* Microsoft ADPCM */
|
coding_MSADPCM, /* Microsoft ADPCM */
|
||||||
|
coding_WS, /* Westwood Studios VBR ADPCM */
|
||||||
coding_AICA, /* Yamaha AICA ADPCM */
|
coding_AICA, /* Yamaha AICA ADPCM */
|
||||||
coding_L5_555, /* Level-5 0x555 ADPCM */
|
coding_L5_555, /* Level-5 0x555 ADPCM */
|
||||||
coding_SASSC, /* Activision EXAKT SASSC DPCM */
|
coding_SASSC, /* Activision EXAKT SASSC DPCM */
|
||||||
|
@ -158,7 +159,9 @@ typedef enum {
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
coding_ogg_vorbis, /* Xiph Vorbis (MDCT-based) */
|
coding_ogg_vorbis, /* Xiph Vorbis (MDCT-based) */
|
||||||
coding_fsb_vorbis, /* FMOD's Vorbis without Ogg layer */
|
coding_fsb_vorbis, /* FMOD Vorbis without Ogg layer */
|
||||||
|
coding_wwise_vorbis, /* Audiokinetic Vorbis without Ogg layer */
|
||||||
|
coding_ogl_vorbis, /* Shin'en Vorbis without Ogg layer */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VGM_USE_MPEG
|
#ifdef VGM_USE_MPEG
|
||||||
|
@ -441,7 +444,7 @@ typedef enum {
|
||||||
meta_PS2_XA2_RRP, /* RC Revenge Pro */
|
meta_PS2_XA2_RRP, /* RC Revenge Pro */
|
||||||
meta_PS2_STM, /* Red Dead Revolver .stm, renamed .ps2stm */
|
meta_PS2_STM, /* Red Dead Revolver .stm, renamed .ps2stm */
|
||||||
meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */
|
meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */
|
||||||
meta_UBI_CKD, /* Ubisoft CKD RIFF header from Rayman Origins */
|
meta_UBI_CKD, /* Ubisoft CKD RIFF header (Rayman Origins Wii) */
|
||||||
|
|
||||||
meta_XBOX_WAVM, /* XBOX WAVM File */
|
meta_XBOX_WAVM, /* XBOX WAVM File */
|
||||||
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
|
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
|
||||||
|
@ -608,6 +611,9 @@ typedef enum {
|
||||||
meta_XMA_RIFF, /* Microsoft RIFF XMA */
|
meta_XMA_RIFF, /* Microsoft RIFF XMA */
|
||||||
meta_X360_AST, /* Dead Rising (X360) */
|
meta_X360_AST, /* Dead Rising (X360) */
|
||||||
meta_WWISE_RIFF, /* Audiokinetic Wwise RIFF/RIFX */
|
meta_WWISE_RIFF, /* Audiokinetic Wwise RIFF/RIFX */
|
||||||
|
meta_UBI_RAKI, /* Ubisoft RAKI header (Rayman Legends, Just Dance 2017) */
|
||||||
|
meta_SXD, /* Sony SXD (Gravity Rush, Freedom Wars PSV) */
|
||||||
|
meta_OGL, /* Shin'en Wii/WiiU (Jett Rocket (Wii), FAST Racing NEO (WiiU)) */
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
meta_OGG_VORBIS, /* Ogg Vorbis */
|
meta_OGG_VORBIS, /* Ogg Vorbis */
|
||||||
|
@ -729,6 +735,8 @@ typedef struct {
|
||||||
off_t loop_next_block_offset; /* saved from next_block_offset */
|
off_t loop_next_block_offset; /* saved from next_block_offset */
|
||||||
|
|
||||||
/* decoder specific */
|
/* decoder specific */
|
||||||
|
int codec_endian; /* little/big endian marker; name is left vague but usually means big endian */
|
||||||
|
|
||||||
uint8_t xa_channel; /* XA ADPCM: selected channel */
|
uint8_t xa_channel; /* XA ADPCM: selected channel */
|
||||||
int32_t xa_sector_length; /* XA ADPCM: XA block */
|
int32_t xa_sector_length; /* XA ADPCM: XA block */
|
||||||
uint8_t xa_headerless; /* XA ADPCM: headerless XA block */
|
uint8_t xa_headerless; /* XA ADPCM: headerless XA block */
|
||||||
|
@ -776,8 +784,13 @@ typedef struct {
|
||||||
ogg_vorbis_streamfile ov_streamfile;
|
ogg_vorbis_streamfile ov_streamfile;
|
||||||
} ogg_vorbis_codec_data;
|
} ogg_vorbis_codec_data;
|
||||||
|
|
||||||
|
/* config for Wwise Vorbis */
|
||||||
|
typedef enum { HEADER_TRIAD, FULL_SETUP, INLINE_CODEBOOKS, EXTERNAL_CODEBOOKS, AOTUV603_CODEBOOKS } wwise_setup_type;
|
||||||
|
typedef enum { TYPE_8, TYPE_6, TYPE_2 } wwise_header_type;
|
||||||
|
typedef enum { STANDARD, MODIFIED } wwise_packet_type;
|
||||||
|
|
||||||
/* any raw Vorbis without Ogg layer */
|
/* any raw Vorbis without Ogg layer */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vorbis_info vi; /* stream settings */
|
vorbis_info vi; /* stream settings */
|
||||||
vorbis_comment vc; /* stream comments */
|
vorbis_comment vc; /* stream comments */
|
||||||
vorbis_dsp_state vd; /* decoder global state */
|
vorbis_dsp_state vd; /* decoder global state */
|
||||||
|
@ -788,6 +801,16 @@ typedef struct {
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
size_t samples_to_discard; /* for looping purposes */
|
size_t samples_to_discard; /* for looping purposes */
|
||||||
int samples_full; /* flag, samples available in vorbis buffers */
|
int samples_full; /* flag, samples available in vorbis buffers */
|
||||||
|
|
||||||
|
/* Wwise Vorbis config */
|
||||||
|
wwise_setup_type setup_type;
|
||||||
|
wwise_header_type header_type;
|
||||||
|
wwise_packet_type packet_type;
|
||||||
|
/* saved data to reconstruct modified packets */
|
||||||
|
uint8_t mode_blockflag[64+1]; /* max 6b+1; flags 'n stuff */
|
||||||
|
int mode_bits; /* bits to store mode_number */
|
||||||
|
uint8_t prev_blockflag; /* blockflag in the last decoded packet */
|
||||||
|
|
||||||
} vorbis_codec_data;
|
} vorbis_codec_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1053,12 +1076,6 @@ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMST
|
||||||
* Returns 1 if loop was done. */
|
* Returns 1 if loop was done. */
|
||||||
int vgmstream_do_loop(VGMSTREAM * vgmstream);
|
int vgmstream_do_loop(VGMSTREAM * vgmstream);
|
||||||
|
|
||||||
/* See if there is a second file which may be the second channel, given
|
|
||||||
* already opened mono opened_stream which was opened from filename.
|
|
||||||
* If a suitable file is found, open it and change opened_stream to a stereo stream. */
|
|
||||||
void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile);
|
|
||||||
|
|
||||||
|
|
||||||
/* Open the stream for reading at offset (standarized taking into account layouts, channels and so on).
|
/* Open the stream for reading at offset (standarized taking into account layouts, channels and so on).
|
||||||
* returns 0 on failure */
|
* returns 0 on failure */
|
||||||
int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset);
|
int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset);
|
||||||
|
|
Loading…
Reference in New Issue