Updated VGMStream to r1050-707-gfcc79e8f.

CQTexperiment
Christopher Snowhill 2017-10-08 16:25:44 -07:00
parent 614d57d37f
commit 34357351c8
28 changed files with 614 additions and 313 deletions

View File

@ -22,7 +22,6 @@
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 */; };
8323894A1D22419B00482226 /* clHCA.c in Sources */ = {isa = PBXBuildFile; fileRef = 832389481D22419B00482226 /* clHCA.c */; };
@ -32,6 +31,11 @@
83299FD01E7660C7003A3242 /* bik.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCE1E7660C7003A3242 /* bik.c */; };
83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */ = {isa = PBXBuildFile; fileRef = 83299FCF1E7660C7003A3242 /* dsp_adx.c */; };
832C70BF1E9335E400BD7B4E /* Vorbis.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83F4128F1E932F9A002E37D0 /* Vorbis.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
83345A4A1F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A491F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c */; };
83345A4F1F8AEB2800B2EAA4 /* nub_xma.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */; };
83345A501F8AEB2800B2EAA4 /* pc_al2.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */; };
83345A511F8AEB2800B2EAA4 /* nsw_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */; };
83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83345A4E1F8AEB2800B2EAA4 /* xvag.c */; };
833A7A2E1ED11961003EC53E /* xau.c in Sources */ = {isa = PBXBuildFile; fileRef = 833A7A2D1ED11961003EC53E /* xau.c */; };
834D3A6E19F47C98001C54F6 /* g1l.c in Sources */ = {isa = PBXBuildFile; fileRef = 834D3A6D19F47C98001C54F6 /* g1l.c */; };
8350270D1ED119D200C25929 /* ps3_mta2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8350270C1ED119D200C25929 /* ps3_mta2.c */; };
@ -270,7 +274,6 @@
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 */; };
836F701518BDC2190095E648 /* ps3_past.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED918BDC2190095E648 /* ps3_past.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 */; };
836F701A18BDC2190095E648 /* psx_fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDE18BDC2190095E648 /* psx_fag.c */; };
836F701B18BDC2190095E648 /* psx_gms.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDF18BDC2190095E648 /* psx_gms.c */; };
@ -344,7 +347,6 @@
83709E0D1ECBC1C3005C03D3 /* mc3_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */; };
83709E0E1ECBC1C3005C03D3 /* psv_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */; };
8374EE3E1F787AB600033E90 /* ffmpeg_decoder_utils_ea_xma.c in Sources */ = {isa = PBXBuildFile; fileRef = 8374EE361F787AB500033E90 /* ffmpeg_decoder_utils_ea_xma.c */; };
8374EE3F1F787AB600033E90 /* ffmpeg_decoder_utils_wwise_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 8374EE3B1F787AB600033E90 /* ffmpeg_decoder_utils_wwise_opus.c */; };
8374EE401F787AB600033E90 /* ffmpeg_decoder_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 8374EE3C1F787AB600033E90 /* ffmpeg_decoder_utils.h */; };
8374EE411F787AB600033E90 /* ffmpeg_decoder_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 8374EE3D1F787AB600033E90 /* ffmpeg_decoder_utils.c */; };
838BDB641D3AF08C0022CA6F /* libavcodec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB611D3AF08C0022CA6F /* libavcodec.a */; };
@ -525,7 +527,6 @@
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>"; };
831BD11F1EEE1CF200198540 /* ngc_ulw.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ngc_ulw.c; sourceTree = "<group>"; };
@ -536,6 +537,11 @@
832389511D224C0800482226 /* hca_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hca_decoder.c; sourceTree = "<group>"; };
83299FCE1E7660C7003A3242 /* bik.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bik.c; sourceTree = "<group>"; };
83299FCF1E7660C7003A3242 /* dsp_adx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_adx.c; sourceTree = "<group>"; };
83345A491F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils_switch_opus.c; sourceTree = "<group>"; };
83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_xma.c; sourceTree = "<group>"; };
83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_al2.c; sourceTree = "<group>"; };
83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nsw_opus.c; sourceTree = "<group>"; };
83345A4E1F8AEB2800B2EAA4 /* xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xvag.c; sourceTree = "<group>"; };
833A7A2D1ED11961003EC53E /* xau.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xau.c; sourceTree = "<group>"; };
834D3A6D19F47C98001C54F6 /* g1l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g1l.c; sourceTree = "<group>"; };
8350270C1ED119D200C25929 /* ps3_mta2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_mta2.c; sourceTree = "<group>"; };
@ -776,7 +782,6 @@
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>"; };
836F6ED918BDC2190095E648 /* ps3_past.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_past.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>"; };
836F6EDE18BDC2190095E648 /* psx_fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_fag.c; sourceTree = "<group>"; };
836F6EDF18BDC2190095E648 /* psx_gms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_gms.c; sourceTree = "<group>"; };
@ -850,7 +855,6 @@
83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3_decoder.c; sourceTree = "<group>"; };
83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psv_decoder.c; sourceTree = "<group>"; };
8374EE361F787AB500033E90 /* ffmpeg_decoder_utils_ea_xma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils_ea_xma.c; sourceTree = "<group>"; };
8374EE3B1F787AB600033E90 /* ffmpeg_decoder_utils_wwise_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils_wwise_opus.c; sourceTree = "<group>"; };
8374EE3C1F787AB600033E90 /* ffmpeg_decoder_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffmpeg_decoder_utils.h; sourceTree = "<group>"; };
8374EE3D1F787AB600033E90 /* ffmpeg_decoder_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_utils.c; sourceTree = "<group>"; };
838BDB611D3AF08C0022CA6F /* libavcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavcodec.a; path = ../../ThirdParty/ffmpeg/lib/libavcodec.a; sourceTree = "<group>"; };
@ -1050,8 +1054,8 @@
836F6DDF18BDC2180095E648 /* coding */ = {
isa = PBXGroup;
children = (
83345A491F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c */,
8374EE361F787AB500033E90 /* ffmpeg_decoder_utils_ea_xma.c */,
8374EE3B1F787AB600033E90 /* ffmpeg_decoder_utils_wwise_opus.c */,
8374EE3D1F787AB600033E90 /* ffmpeg_decoder_utils.c */,
8374EE3C1F787AB600033E90 /* ffmpeg_decoder_utils.h */,
83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */,
@ -1157,6 +1161,10 @@
836F6E2718BDC2180095E648 /* meta */ = {
isa = PBXGroup;
children = (
83345A4D1F8AEB2800B2EAA4 /* nsw_opus.c */,
83345A4B1F8AEB2700B2EAA4 /* nub_xma.c */,
83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */,
83345A4E1F8AEB2800B2EAA4 /* xvag.c */,
83AA5D201F6E2F9B0020821C /* awc.c */,
83AA5D221F6E2F9C0020821C /* ea_snu.c */,
83AA5D211F6E2F9C0020821C /* hca_keys.h */,
@ -1184,7 +1192,6 @@
831BA6131EAC61A500CF89B0 /* ubi_raki.c */,
831BA6141EAC61A500CF89B0 /* vawx.c */,
831BA6151EAC61A500CF89B0 /* x360_cxs.c */,
831BA6161EAC61A500CF89B0 /* x360_nub.c */,
831BA6171EAC61A500CF89B0 /* x360_pasx.c */,
83FF0EBB1E93282100C58054 /* wwise.c */,
83AB8C731E8072A100086084 /* nub_vag.c */,
@ -1370,7 +1377,6 @@
836F6ED718BDC2190095E648 /* ps3_klbs.c */,
836F6ED818BDC2190095E648 /* ps3_msf.c */,
836F6ED918BDC2190095E648 /* ps3_past.c */,
836F6EDC18BDC2190095E648 /* ps3_xvag.c */,
836F6EDD18BDC2190095E648 /* psx_cdxa.c */,
836F6EDE18BDC2190095E648 /* psx_fag.c */,
836F6EDF18BDC2190095E648 /* psx_gms.c */,
@ -1672,7 +1678,6 @@
836F6F9B18BDC2190095E648 /* mn_str.c in Sources */,
836F6F5918BDC2190095E648 /* tra_blocked.c in Sources */,
836F6F9F18BDC2190095E648 /* musc.c in Sources */,
836F701818BDC2190095E648 /* ps3_xvag.c in Sources */,
836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */,
836F6FA118BDC2190095E648 /* myspd.c in Sources */,
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */,
@ -1681,7 +1686,6 @@
836F6F7018BDC2190095E648 /* apple_caff.c in Sources */,
836F700018BDC2190095E648 /* ps2_svag.c in Sources */,
836F6FB618BDC2190095E648 /* ngc_sck_dsp.c in Sources */,
8374EE3F1F787AB600033E90 /* ffmpeg_decoder_utils_wwise_opus.c in Sources */,
836F6F2818BDC2190095E648 /* ima_decoder.c in Sources */,
836F702318BDC2190095E648 /* rsf.c in Sources */,
83299FD01E7660C7003A3242 /* bik.c in Sources */,
@ -1760,6 +1764,7 @@
836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */,
83AA5D261F6E2F9C0020821C /* ea_snu.c in Sources */,
83AA5D171F6E2F600020821C /* mpeg_custom_utils_ealayer3.c in Sources */,
83345A521F8AEB2800B2EAA4 /* xvag.c in Sources */,
836F704C18BDC2190095E648 /* xbox_xvas.c in Sources */,
836F6F3918BDC2190095E648 /* SASSC_decoder.c in Sources */,
836F703A18BDC2190095E648 /* vs.c in Sources */,
@ -1818,6 +1823,7 @@
836F6F6D18BDC2190095E648 /* aifc.c in Sources */,
836F702218BDC2190095E648 /* rsd.c in Sources */,
836F6FC618BDC2190095E648 /* pcm.c in Sources */,
83345A501F8AEB2800B2EAA4 /* pc_al2.c in Sources */,
836F702518BDC2190095E648 /* rwx.c in Sources */,
836F6F3A18BDC2190095E648 /* sdx2_decoder.c in Sources */,
836F6FAF18BDC2190095E648 /* ngc_dsp_std.c in Sources */,
@ -1840,7 +1846,6 @@
836F6F4618BDC2190095E648 /* filp_blocked.c in Sources */,
836F6FE518BDC2190095E648 /* ps2_lpcm.c in Sources */,
836F6FB318BDC2190095E648 /* ngc_lps.c in Sources */,
831BA6201EAC61A500CF89B0 /* x360_nub.c in Sources */,
836F6FC018BDC2190095E648 /* p3d.c in Sources */,
836F6FC718BDC2190095E648 /* pona.c in Sources */,
836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */,
@ -1884,6 +1889,7 @@
836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */,
836F6F9618BDC2190095E648 /* lsf.c in Sources */,
8374EE3E1F787AB600033E90 /* ffmpeg_decoder_utils_ea_xma.c in Sources */,
83345A511F8AEB2800B2EAA4 /* nsw_opus.c in Sources */,
836F6FC818BDC2190095E648 /* pos.c in Sources */,
8350C05A1E071990009E0A93 /* ps2_svag_snk.c in Sources */,
836F6F8918BDC2190095E648 /* gca.c in Sources */,
@ -1948,6 +1954,7 @@
836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */,
836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */,
836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */,
83345A4F1F8AEB2800B2EAA4 /* nub_xma.c in Sources */,
836F6F7618BDC2190095E648 /* brstm.c in Sources */,
836F700718BDC2190095E648 /* ps2_vgv.c in Sources */,
836F704F18BDC2190095E648 /* xwb.c in Sources */,
@ -1982,6 +1989,7 @@
836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */,
836F705018BDC2190095E648 /* ydsp.c in Sources */,
836F702718BDC2190095E648 /* sat_baka.c in Sources */,
83345A4A1F8AEAF900B2EAA4 /* ffmpeg_decoder_utils_switch_opus.c in Sources */,
836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */,
836F704B18BDC2190095E648 /* xbox_xmu.c in Sources */,
832389501D2246C300482226 /* hca.c in Sources */,

View File

@ -64,6 +64,7 @@ void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
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_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_alaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian);
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
@ -214,7 +215,10 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data * data, int skip_samples);
size_t ffmpeg_make_opus_header(uint8_t * buf, int buf_size, int channels, int skip, int sample_rate);
size_t ffmpeg_get_eaxma_virtual_size(off_t real_offset, size_t real_size, STREAMFILE *streamFile);
size_t ffmpeg_get_eaxma_virtual_size(int channels, off_t real_offset, size_t real_size, STREAMFILE *streamFile);
size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile);
#endif
/* coding_utils */
@ -229,12 +233,14 @@ int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data
/* MS audio format's sample info (struct to avoid passing so much stuff, separate for reusing) */
typedef struct {
/* input */
int xma_version;
int channels;
int stream_mode;
off_t data_offset;
size_t data_size;
int channels; /* for skips */
off_t chunk_offset; /* for multistream config */
/* frame offsets */
int loop_flag;
uint32_t loop_start_b;
@ -253,7 +259,7 @@ void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_
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_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_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);

View File

@ -235,7 +235,7 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s
put_16bitLE(buf+0x14, codec_XMA2);
put_16bitLE(buf+0x16, channels);
put_32bitLE(buf+0x18, sample_rate);
put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong unneeded) */
put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */
put_16bitLE(buf+0x20, (int16_t)(channels*sizeof(sample))); /* block align */
put_16bitLE(buf+0x22, 16); /* bits per sample */
@ -243,7 +243,7 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s
put_16bitLE(buf+0x26, streams); /* number of streams */
put_32bitLE(buf+0x28, speakers); /* speaker position */
put_32bitLE(buf+0x2c, bytecount); /* PCM samples */
put_32bitLE(buf+0x30, block_size); /* XMA block size */
put_32bitLE(buf+0x30, block_size); /* XMA block size (can be zero, it's for seeking only) */
/* (looping values not set, expected to be handled externally) */
put_32bitLE(buf+0x34, 0); /* play begin */
put_32bitLE(buf+0x38, 0); /* play length */
@ -251,7 +251,7 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s
put_32bitLE(buf+0x40, 0); /* loop length */
put_8bit(buf+0x44, 0); /* loop count */
put_8bit(buf+0x45, 4); /* encoder version */
put_16bitLE(buf+0x46, block_count); /* blocks count = entries in seek table */
put_16bitLE(buf+0x46, block_count); /* blocks count (entries in seek table, can be zero) */
memcpy(buf+0x48, "data", 4);
put_32bitLE(buf+0x4c, data_size); /* data size */
@ -424,19 +424,18 @@ fail:
/* ******************************************** */
/* XMA PARSING */
/* ******************************************** */
#define XMA_CHECK_SKIPS 0
/**
* Find total and loop samples of Microsoft audio formats (WMAPRO/XMA1/XMA2) by reading frame headers.
*
* The stream is made of packets, each containing N small frames of X samples. Frames are further divided into subframes.
* XMA1/XMA2/WMAPRO only differ in the packet headers.
* XMA1/XMA2 can divided into streams for multichannel (1/2ch ... 1/2ch). From the file start, packet 1..N is owned by
* stream 1..N. Then must follow "packet_skip" value to find the stream next packet, as they are arbitrarily interleaved.
* XMA1/XMA2/WMAPRO data only differs in the packet headers.
*/
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;
#if XMA_CHECK_SKIPS
int start_skip = 0, end_skip = 0, first_start_skip = 0, last_end_skip = 0;
#endif
static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int start_packet, int channels_per_packet, 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, start_skip = 0, end_skip = 0;
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;
size_t size;
@ -445,25 +444,15 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i
off_t offset = msd->data_offset;
uint32_t stream_offset_b = msd->data_offset * 8;
offset += start_packet * packet_size;
size = offset + msd->data_size;
packet_size_b = packet_size * 8;
/* 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 */
//streams = (msd->stream_mode==0 ? (msd->channels + 1) / 2 : msd->channels)
skip_packets = 0;
/* read packets */
while (offset < size) {
offset_b = offset * 8; /* global offset in bits */
offset += packet_size; /* global offset in bytes */
/* skip packets not owned by the first stream, since we only need samples from it */
if (skip_packets && packet_skip_count) {
packet_skip_count--;
continue;
}
/* packet header */
if (msd->xma_version == 1) { /* XMA1 */
//packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */
@ -480,149 +469,141 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i
} 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 */
first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */
packet_skip_count = 0; /* xwma has no need to skip packets since it uses real multichannel audio */
header_size_b = 4+2+bits_frame_size; /* variable-sized header */
}
/* full packet skip */
if (packet_skip_count == 0x7FF) {
/* XMA2 packets with XMA1 RIFF (transmogrified), remove the packet metadata flag */
if (msd->xma_version == 1 && (packet_skip_count & 0x700) == 0x100) {
//VGM_LOG("MS_SAMPLES: XMA1 transmogrified packet header at 0x%lx\n", (off_t)offset_b/8);
packet_skip_count &= ~0x100;
}
/* full packet skip, no new frames start in this packet (prev frames can end here) */
if (packet_skip_count == 0x7FF) { /* XMA1, 11b */
VGM_LOG("MS_SAMPLES: XMA1 full packet_skip %i at 0x%lx\n", packet_skip_count, (off_t)offset_b/8);
packet_skip_count = 0;
continue;
}
if (packet_skip_count > 255) { /* seen in some (converted?) XMA1 */
else if (packet_skip_count == 0xFF) { /* XMA2, 8b*/
VGM_LOG("MS_SAMPLES: XMA2 full packet_skip %i at 0x%lx\n", packet_skip_count, (off_t)offset_b/8);
packet_skip_count = 0;
continue;
}
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);
offset += packet_size * (packet_skip_count); /* skip packets not owned by the first stream, since we only need samples from it */
/* unusual but not impossible, as the encoder can interleave packets in any way */
VGM_ASSERT(packet_skip_count > 10, "MS_SAMPLES: found big packet skip %i at 0x%lx\n", packet_skip_count, (off_t)offset_b/8);
packet_offset_b = header_size_b + first_frame_b;
packet_offset_b = header_size_b + first_frame_b; /* packet offset in bits */
/* read packet frames */
while (packet_offset_b < packet_size_b) {
frame_offset_b = offset_b + packet_offset_b; /* in bits for aligment stuff */
//todo not sure if frames or frames+1 (considering skip_samples)
/* loops, later adjusted with subframe (seems correct vs tests) */
if (msd->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == msd->loop_start_b)
loop_start_frame = frames;
if (msd->loop_flag && (offset_b + packet_offset_b) - stream_offset_b == msd->loop_end_b)
loop_end_frame = frames;
/* frame header */
frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, streamFile);
frame_offset_b += bits_frame_size;
if (frame_size_b == 0) /* observed in some files with empty frames/packets */
//;VGM_LOG("MS_SAMPLES: frame_offset=0x%lx (0b%lx), frame_size=0x%x (0b%x)\n", (off_t)frame_offset_b/8,(off_t)frame_offset_b, frame_size_b/8, frame_size_b);
/* stop when packet padding starts (0x00 for XMA1 or 0xFF in XMA2) */
if (frame_size_b == 0 || frame_size_b == (0xffffffff >> (32 - bits_frame_size))) {
break;
}
packet_offset_b += frame_size_b; /* including header */
#if 0
{
uint32_t frame_config
frame_config = read_bitsBE_b(frame_offset_b, 15, streamFile);
//VGM_LOG(" frame %04i: off_b=%I64x (~0x%I64x), fs_b=%i (~0x%x), fs=%x\n",frames, frame_offset_b, frame_offset_b/8, frame_size_b,frame_size_b/8, frame_config);
//if (frame_config != 0x7f00) /* "contains all subframes"? */
// continue; // todo read packet end bit instead
}
#endif
frame_offset_b += 15; //todo bits_frame_size?
if (frame_size_b == 0x7FFF) { /* end packet frame marker */
break;
}
#if XMA_CHECK_SKIPS
// more header stuff (info from FFmpeg)
{
/* find skips (info from FFmpeg) */
if (channels_per_packet && (msd->xma_version == 1 || msd->xma_version == 2)) {
int flag;
int tilehdr_size = 15; //todo incorrect but usable for XMA, fix for WMAPro (complex calcs, see ffmpeg decode_tilehdr)
frame_offset_b += tilehdr_size;
/* ignore "postproc transform" */
if (msd->channels > 1) {
if (channels_per_packet > 1) {
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
frame_offset_b += 1;
if (flag) {
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
frame_offset_b += 1;
if (flag) {
frame_offset_b += 1 + 4 * msd->channels*msd->channels; /* 4-something per double channel? */
frame_offset_b += 1 + 4 * channels_per_packet*channels_per_packet; /* 4-something per double channel? */
}
}
}
/* get start/end skips to get the proper number of samples */ //todo check if first bit =1 means full 512 skip
/* get start/end skips to get the proper number of samples */
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
frame_offset_b += 1;
if (flag) {
int new_skip;
/* get start skip */
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
frame_offset_b += 1;
if (flag) {
VGM_LOG("start_skip at 0x%I64x\n", frame_offset_b);
new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile);
int new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile);
VGM_LOG("MS_SAMPLES: start_skip %i at 0x%lx (bit 0x%lx)\n", new_skip, (off_t)frame_offset_b/8, (off_t)frame_offset_b);
VGM_ASSERT(start_skip, "MS_SAMPLES: more than one start_skip (%i)\n", new_skip); //ignore, happens due to incorrect tilehdr_size
frame_offset_b += 10;
VGM_ASSERT(start_skip, "XMA: more than one start_skip (%i)\n", new_skip);
if (new_skip > samples_per_frame) { /* from xmaencode */
VGM_LOG("XMA: bad start_skip (%i)\n", new_skip);
if (new_skip > samples_per_frame) /* from xmaencode */
new_skip = samples_per_frame;
}
if (frames==0) first_start_skip = new_skip; /* sometimes in the middle */
start_skip += new_skip;
if (start_skip==0)
start_skip = new_skip;
}
/* get end skip */
flag = read_bitsBE_b(frame_offset_b, 1, streamFile);
frame_offset_b += 1;
if (flag) {
VGM_LOG("end_skip at 0x%I64x\n", frame_offset_b);
new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile);
int new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile);
VGM_LOG("MS_SAMPLES: end_skip %i at 0x%lx (bit 0x%lx)\n", new_skip, (off_t)frame_offset_b/8, (off_t)frame_offset_b);
VGM_ASSERT(end_skip, "MS_SAMPLES: more than one end_skip (%i)\n", new_skip);//ignore, happens due to incorrect tilehdr_size
frame_offset_b += 10;
VGM_ASSERT(end_skip, "XMA: more than one end_skip (%i)\n", new_skip);
if (new_skip > samples_per_frame) { /* from xmaencode */
VGM_LOG("XMA: bad end_skip (%i)\n", new_skip);
if (new_skip > samples_per_frame) /* from xmaencode */
new_skip = samples_per_frame;
}
last_end_skip = new_skip; /* not seen */
end_skip += new_skip;
end_skip = new_skip;
}
VGM_LOG(" skip: st=%i, ed=%i\n", start_skip, end_skip);
}
}
#endif
samples += samples_per_frame;
frames++;
/* last bit in frame = more frames flag, end packet to avoid reading garbage in some cases
* (last frame spilling to other packets also has this flag, though it's ignored here) */
if (packet_offset_b < packet_size_b && !read_bitsBE_b(offset_b + packet_offset_b - 1, 1, streamFile)) {
break;
}
}
}
#if XMA_CHECK_SKIPS
//todo this seems to usually work, but not always
/* apply skips (not sure why 64, empty samples generated by the decoder not in the file?) */
samples = samples + 64 - start_skip;
samples = samples + 64 - end_skip;
msd->skip_samples = 64 + samples_per_frame; //todo not always correct
#endif
//todo FFmpeg seems to decode 1 subframe late vs xmaencode, and doesn't write 128 init samples, so skips are not useful ATM
//samples = samples + 128 - start_skip - end_skip; /* 128 init samples added by xmaencode */
msd->num_samples = samples;
msd->skip_samples = start_skip;
if (msd->loop_flag && loop_end_frame > loop_start_frame) {
msd->loop_start_sample = loop_start_frame * samples_per_frame + msd->loop_start_subframe * samples_per_subframe;
msd->loop_end_sample = loop_end_frame * samples_per_frame + msd->loop_end_subframe * samples_per_subframe;
#if XMA_CHECK_SKIPS
/* maybe this is needed */
//msd->loop_start_sample -= msd->skip_samples;
//msd->loop_end_sample -= msd->skip_samples;
#endif
//todo maybe this is needed
//msd->loop_start_sample -= start_skip;
//msd->loop_end_sample -= start_skip;
}
}
@ -658,7 +639,28 @@ void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile) {
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);
int start_stream = 0;
int channels_per_stream = 0;
/* get from stream config (needed to find skips) */
if (msd->chunk_offset) {
int format = read_16bitLE(msd->chunk_offset,streamFile);
if (format == 0x0165 || format == 0x6501) { /* XMA1 */
channels_per_stream = read_8bit(msd->chunk_offset + 0x0C + 0x14*start_stream + 0x11,streamFile);
} else if (format == 0x0166 || format == 0x6601) { /* new XMA2 */
channels_per_stream = msd->channels > 1 ? 2 : 1;
} else { /* old XMA2 */
int version = read_8bit(msd->chunk_offset,streamFile);
channels_per_stream = read_8bit(msd->chunk_offset + 0x20 + (version==3 ? 0x00 : 0x08) + 0x4*start_stream + 0x00,streamFile);
}
}
else if (msd->channels) {
channels_per_stream = msd->channels > 1 ? 2 : 1;
}
if (channels_per_stream > 2)
channels_per_stream = 0;
ms_audio_get_samples(msd, streamFile, start_stream, channels_per_stream, 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) {
@ -667,21 +669,20 @@ void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_
int samples_per_frame = 0;
int samples_per_subframe = 0;
int bits_frame_size = 0;
int start_packet = 0;
int channels_per_stream = msd->channels;
/* do some WMAPRO setup (code from ffmpeg) */
if (!(decode_flags & 0x40)) {
VGM_LOG("MS_SAMPLES: no frame length in WMAPro\n");
msd->num_samples = 0;
return;
}
samples_per_frame = wma_get_samples_per_frame(version, sample_rate, decode_flags);
bits_frame_size = floor(log(block_align) / log(2)) + 4; /* max bits needed to represent this block_align */
samples_per_subframe = 0; /* not really needed WMAPro can't use loop subframes (complex subframe lengths) */
msd->xma_version = 0; /* signal it's not XMA */
/* 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);
ms_audio_get_samples(msd, streamFile, start_packet, channels_per_stream, 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) {
@ -745,27 +746,46 @@ void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * chan
/* 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);
total_channels += read_8bit(chunk_offset+0x0C+0x14*i+0x11,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) {
void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * out_loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_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;
int num_samples, loop_start_sample, loop_end_sample, loop_flag;
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 */
num_samples = read_32bit(chunk_offset+0x18,streamFile); /* max samples from all frames */
loop_start_sample = read_32bit(chunk_offset+0x28,streamFile);
loop_end_sample = loop_start_sample + read_32bit(chunk_offset+0x2C,streamFile);
loop_flag = (uint8_t)read_8bit(chunk_offset+0x30,streamFile) != 0;
/* num_samples isn't used by xmaencode, so final_num_samples = num_samples + setup_samples (128) - start_skip (~512) - end_skip (0..512) */
/* loop values seem to be after applying skips, so loop_end wouldn't be higher than final_num_samples */
/* flag rarely set, use loop_end as marker */
if (!loop_flag) {
loop_flag = loop_end_sample > 0;
/* loop_end_sample - 128 + start_skip + end_skip = num_samples, use approx */
if (loop_start_sample == 384 && loop_end_sample - 128 + 512 + 512 >= num_samples) {
VGM_LOG("XMA2 PARSE: disabling full loop\n");
loop_flag = 0; /* some XMA have full loop set without loop flag and shouldn't loop */
}
}
if(out_num_samples) *out_num_samples = num_samples;
if(out_loop_start_sample) *out_loop_start_sample = loop_start_sample;
if(out_loop_end_sample) *out_loop_end_sample = loop_end_sample;
if(out_loop_flag) *out_loop_flag = loop_flag;
/* play_begin+end = pcm_samples in original sample rate (not usable when resampled = looped) */
/* 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); */
}

View File

@ -218,11 +218,11 @@ static int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size) {
/* main read */
switch(data->config.type) {
case FFMPEG_EA_XMA: ret = ffmpeg_custom_read_eaxma(data, buf, buf_size); break;
case FFMPEG_WWISE_OPUS: ret = ffmpeg_custom_read_wwise_opus(data, buf, buf_size); break;
//case FFMPEG_EA_SCHL: ret = ffmpeg_custom_read_ea_schl(data, buf, buf_size); break;
//case FFMPEG_SFH: ret = ffmpeg_custom_read_sfh(data, buf, buf_size); break;
default: ret = ffmpeg_custom_read_standard(data, buf, buf_size); break;
case FFMPEG_EA_XMA: ret = ffmpeg_custom_read_eaxma(data, buf, buf_size); break;
case FFMPEG_SWITCH_OPUS: ret = ffmpeg_custom_read_switch_opus(data, buf, buf_size); break;
//case FFMPEG_EA_SCHL: ret = ffmpeg_custom_read_ea_schl(data, buf, buf_size); break;
//case FFMPEG_SFH: ret = ffmpeg_custom_read_sfh(data, buf, buf_size); break;
default: ret = ffmpeg_custom_read_standard(data, buf, buf_size); break;
}
data->virtual_offset += ret;
//data->real_offset = ; /* must be updated in function */
@ -285,11 +285,11 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) {
/* main seek */
switch(data->config.type) {
case FFMPEG_EA_XMA: offset = ffmpeg_custom_seek_eaxma(data, offset); break;
case FFMPEG_WWISE_OPUS: offset = ffmpeg_custom_seek_wwise_opus(data, offset); break;
//case FFMPEG_EA_SCHL: offset = ffmpeg_custom_seek_ea_schl(data, offset); break;
//case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break;
default: offset = ffmpeg_custom_seek_standard(data, offset); break;
case FFMPEG_EA_XMA: offset = ffmpeg_custom_seek_eaxma(data, offset); break;
case FFMPEG_SWITCH_OPUS: offset = ffmpeg_custom_seek_switch_opus(data, offset); break;
//case FFMPEG_EA_SCHL: offset = ffmpeg_custom_seek_ea_schl(data, offset); break;
//case FFMPEG_SFH: offset = ffmpeg_custom_seek_sfh(data, offset); break;
default: offset = ffmpeg_custom_seek_standard(data, offset); break;
}
data->virtual_offset = offset;
//data->real_offset = ; /* must be updated in function */
@ -302,11 +302,11 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) {
static int64_t ffmpeg_size(ffmpeg_codec_data * data) {
int64_t bytes;
switch(data->config.type) {
case FFMPEG_EA_XMA: bytes = ffmpeg_custom_size_eaxma(data); break;
case FFMPEG_WWISE_OPUS: bytes = ffmpeg_custom_size_wwise_opus(data); break;
//case FFMPEG_EA_SCHL: bytes = ffmpeg_custom_size_ea_schl(data); break;
//case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break;
default: bytes = ffmpeg_custom_size_standard(data); break;
case FFMPEG_EA_XMA: bytes = ffmpeg_custom_size_eaxma(data); break;
case FFMPEG_SWITCH_OPUS: bytes = ffmpeg_custom_size_switch_opus(data); break;
//case FFMPEG_EA_SCHL: bytes = ffmpeg_custom_size_ea_schl(data); break;
//case FFMPEG_SFH: bytes = ffmpeg_custom_size_sfh(data); break;
default: bytes = ffmpeg_custom_size_standard(data); break;
}
return bytes;

View File

@ -27,9 +27,9 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size
int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset);
int64_t ffmpeg_custom_size_eaxma(ffmpeg_codec_data *data);
int ffmpeg_custom_read_wwise_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size);
int64_t ffmpeg_custom_seek_wwise_opus(ffmpeg_codec_data *data, int64_t virtual_offset);
int64_t ffmpeg_custom_size_wwise_opus(ffmpeg_codec_data *data);
int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size);
int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset);
int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data);
//int ffmpeg_custom_read_ea_schl(ffmpeg_codec_data *data, uint8_t *buf, int buf_size);
//int64_t ffmpeg_custom_seek_ea_schl(ffmpeg_codec_data *data, int64_t virtual_offset);

View File

@ -3,58 +3,121 @@
#ifdef VGM_USE_FFMPEG
#define EAXMA_XMA_BLOCK_SIZE 0x800
#define EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK 3 /* only seen up to 3 (Dante's Inferno) */
#define EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK 4 /* XMA2 max is 8ch = 4 * 2ch */
#define EAXMA_XMA_PACKET_SIZE 0x800
#define EAXMA_XMA_BUFFER_SIZE (EAXMA_XMA_MAX_PACKETS_PER_SNS_BLOCK * EAXMA_XMA_MAX_STREAMS_PER_SNS_BLOCK * EAXMA_XMA_PACKET_SIZE)
/**
* EA-XMA is XMA with padding removed (so a real 0x450 block would be padded to a virtual 0x800 block).
* //todo missing multichannel (packet multistream) support, unknown layout
* EA-XMA is XMA2 with padding removed (so a real 0x450 block would be padded to a virtual 0x800 block).
* Each EA-XMA SNS block contains 1~3 packets per stream, and multistream uses fully separate streams
* (no packet_skip set). We'll pad and reinterleave packets so it resembles standard XMA2.
*
* XMA2 data layout (XMA1 is the same but doesn't use blocks, they are only for seeking):
* - frames (containing 1..4 subframes): decode into 128*4 samples
* - packets: size 0x800, containing N frames (last frame can spill into next packet), must be padded
* - blocks: fixed size, containing N packets (last packet's frames won't spill into next block)
* - stream: N interleaved packets (1/2ch) for multichannel (Nch) audio. Interleave is not fixed:
* at file start/new block has one packet per stream, then must follow the "packet_skip" value
* in the XMA packet header to find its next packet (skiping packets from other streams).
* ex.: s1_p1 skip1, s2_p1 skip2, s1_p2 skip0 s1_p3 skip1, s2_p2 skip1, s1_p4...
*/
static int get_block_max_packets(int num_streams, off_t packets_offset, STREAMFILE * streamfile);
int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) {
uint8_t v_buf[0x8000]; /* intermediate buffer, could be simplified */
uint8_t v_buf[EAXMA_XMA_BUFFER_SIZE]; /* intermediate buffer, could be simplified */
int buf_done = 0;
uint64_t real_offset = data->real_offset;
uint64_t virtual_offset = data->virtual_offset - data->header_size;
uint64_t virtual_base = data->virtual_base;
/* EA-XMA always uses late XMA2 streams (2ch + ... + 1/2ch) */
int num_streams = (data->config.channels / 2) + (data->config.channels % 2 ? 1 : 0);
/* read and transform SNS/EA-XMA block into XMA block by adding padding */
/* read and transform SNS/EA-XMA blocks into XMA packets */
while (buf_done < buf_size) {
int bytes_to_copy;
size_t data_size, extra_size = 0, gap_size = 0;
int s, p, bytes_to_copy, max_packets;
size_t data_size = 0, gap_size = 0;
size_t block_size = read_32bitBE(real_offset, data->streamfile);
/* 0x04(4): some kind of size? 0x08(4): decoded samples */
/* 0x04(4): decoded samples */
off_t packets_offset = real_offset + 0x08;
/* setup */
data_size = (block_size & 0x00FFFFFF) - 0x0c; //todo last block size may be slightly off?
if (data_size % EAXMA_XMA_BLOCK_SIZE) /* aligned padding */
extra_size = EAXMA_XMA_BLOCK_SIZE - (data_size % EAXMA_XMA_BLOCK_SIZE);
if (buf_done == 0) /* first read */
gap_size = virtual_offset - virtual_base; /* might start a few bytes into the block */
max_packets = get_block_max_packets(num_streams, packets_offset, data->streamfile);
if (max_packets == 0) goto fail;
if (data_size + extra_size > 0x8000) {
VGM_LOG("EA-XMA: total size bigger than buffer at %lx\n", (off_t)real_offset);
return 0;
if (max_packets * num_streams * EAXMA_XMA_PACKET_SIZE > EAXMA_XMA_BUFFER_SIZE) {
VGM_LOG("EA XMA: block too big at %lx\n", (off_t)real_offset);
goto fail;
}
bytes_to_copy = data_size + extra_size - gap_size;
/* data is divided into a sub-block per stream (N packets), can be smaller than block_size (= has padding)
* copy XMA data re-interleaving for multichannel. To simplify some calcs fills the same number of packets
* per stream and adjusts packet headers (see above for XMA2 multichannel layout). */
//to-do this doesn't make correct blocks sizes (but blocks are not needed to decode)
for (s = 0; s < num_streams; s++) {
size_t packets_size;
size_t packets_size4 = read_32bitBE(packets_offset, data->streamfile); /* size * 4, no idea */
packets_size = (packets_size4 / 4) - 0x04;
/* Re-interleave all packets in order, one per stream. If one stream has more packets than
* others we add empty packets to keep the same number for all, avoiding packet_skip calcs */
for (p = 0; p < max_packets; p++) {
off_t packet_offset = packets_offset + 0x04 + p * EAXMA_XMA_PACKET_SIZE; /* can be off but will copy 0 */
off_t v_buf_offset = p * EAXMA_XMA_PACKET_SIZE * num_streams + s * EAXMA_XMA_PACKET_SIZE;
size_t packet_to_do = packets_size - p * EAXMA_XMA_PACKET_SIZE;
size_t extra_size = 0;
uint32_t header;
if (packets_size < p * EAXMA_XMA_PACKET_SIZE)
packet_to_do = 0; /* empty packet */
else if (packet_to_do > EAXMA_XMA_PACKET_SIZE)
packet_to_do = EAXMA_XMA_PACKET_SIZE;
/* padding will be full size if packet_to_do is 0 */
if (packet_to_do < EAXMA_XMA_PACKET_SIZE)
extra_size = EAXMA_XMA_PACKET_SIZE - (packet_to_do % EAXMA_XMA_PACKET_SIZE);
/* copy data (or fully pad if empty packet) */
read_streamfile(v_buf + v_buf_offset, packet_offset, packet_to_do, data->streamfile);
memset(v_buf + v_buf_offset + packet_to_do, 0xFF, extra_size); /* add padding, typically 0xFF */
/* rewrite packet header to add packet skips for multichannel (EA XMA streams are fully separate and have none)
* header bits: 6=num_frames, 15=first_frame_bits_offset, 3=metadata, 8=packet_skip */
if (packet_to_do == 0)
header = 0x3FFF800; /* new empty packet header (0 num_frames, first_frame_bits_offset set to max) */
else
header = (uint32_t)read_32bitBE(packet_offset, data->streamfile);
/* get base header + change packet_skip since we know interleave is always 1 packet per stream */
header = (header & 0xFFFFFF00) | ((header & 0x000000FF) + num_streams - 1);
put_32bitBE(v_buf + v_buf_offset, header);
}
packets_offset += (packets_size4 / 4);
}
if (buf_done == 0) /* first read */
gap_size = virtual_offset - virtual_base; /* might start a few bytes into the XMA */
data_size = max_packets * num_streams * EAXMA_XMA_PACKET_SIZE;
bytes_to_copy = data_size - gap_size;
if (bytes_to_copy > buf_size - buf_done)
bytes_to_copy = buf_size - buf_done;
/* transform */
read_streamfile(v_buf, real_offset + 0x0c, data_size, data->streamfile);
memset(v_buf + data_size, 0xFF, extra_size); /* padding can be any value, typically 0xFF */
/* pad + copy */
memcpy(buf + buf_done, v_buf + gap_size, bytes_to_copy);
buf_done += bytes_to_copy;
/* move when block is fully done */
if (data_size + extra_size == bytes_to_copy + gap_size) {
if (data_size == bytes_to_copy + gap_size) {
real_offset += (block_size & 0x00FFFFFF);
virtual_base += data_size + extra_size;
virtual_base += data_size;
}
buf_done += bytes_to_copy;
/* exit on last block just in case, though should reach file size */
if (block_size & 0x80000000)
break;
@ -64,6 +127,9 @@ int ffmpeg_custom_read_eaxma(ffmpeg_codec_data *data, uint8_t *buf, int buf_size
data->real_offset = real_offset;
data->virtual_base = virtual_base;
return buf_size;
fail:
return 0;
}
int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset) {
@ -89,8 +155,8 @@ int64_t ffmpeg_custom_seek_eaxma(ffmpeg_codec_data *data, int64_t virtual_offset
size_t block_size = read_32bitBE(real_offset, data->streamfile);
data_size = (block_size & 0x00FFFFFF) - 0x0c;
if (data_size % EAXMA_XMA_BLOCK_SIZE)
extra_size = EAXMA_XMA_BLOCK_SIZE - (data_size % EAXMA_XMA_BLOCK_SIZE);
if (data_size % EAXMA_XMA_PACKET_SIZE)
extra_size = EAXMA_XMA_PACKET_SIZE - (data_size % EAXMA_XMA_PACKET_SIZE);
/* stop if virtual_offset lands inside current block */
if (data_size + extra_size > virtual_offset)
@ -117,26 +183,32 @@ int64_t ffmpeg_custom_size_eaxma(ffmpeg_codec_data *data) {
}
/* needed to know in meta for fake RIFF */
size_t ffmpeg_get_eaxma_virtual_size(off_t real_offset, size_t real_size, STREAMFILE *streamFile) {
size_t ffmpeg_get_eaxma_virtual_size(int channels, off_t real_offset, size_t real_size, STREAMFILE *streamFile) {
size_t virtual_size = 0;
size_t real_end_offset = real_offset + real_size;
/* EA-XMA always uses late XMA2 streams (2ch + ... + 1/2ch) */
int num_streams = (channels / 2) + (channels % 2 ? 1 : 0);
/* count all SNS/EAXMA blocks size + padding size */
while (real_offset < real_size) {
size_t data_size;
size_t block_size = read_32bitBE(real_offset, streamFile);
data_size = (block_size & 0x00FFFFFF) - 0x0c;
while (real_offset < real_end_offset) {
int max_packets;
size_t block_size = read_32bitBE(real_offset + 0x00, streamFile);
/* 0x04(4): decoded samples */
off_t packets_offset = real_offset + 0x08;
if ((block_size & 0xFF000000) && !(block_size & 0x80000000)) {
VGM_LOG("EA-XMA: unknown flag found at %lx\n", (off_t)real_offset);
goto fail;
}
real_offset += (block_size & 0x00FFFFFF);
max_packets = get_block_max_packets(num_streams, packets_offset, streamFile);
if (max_packets == 0) goto fail;
virtual_size += data_size;
if (data_size % EAXMA_XMA_BLOCK_SIZE) /* XMA block padding */
virtual_size += EAXMA_XMA_BLOCK_SIZE - (data_size % EAXMA_XMA_BLOCK_SIZE);
/* fixed data_size per block for multichannel, see reads */
virtual_size += max_packets * num_streams * EAXMA_XMA_PACKET_SIZE;
real_offset += (block_size & 0x00FFFFFF);
/* exit on last block just in case, though should reach real_size */
if (block_size & 0x80000000)
@ -147,7 +219,33 @@ size_t ffmpeg_get_eaxma_virtual_size(off_t real_offset, size_t real_size, STREAM
fail:
return 0;
}
/* a block can have N streams each with a varying number of packets, get max */
static int get_block_max_packets(int num_streams, off_t packets_offset, STREAMFILE * streamfile) {
int s;
int max_packets = 0;
for (s = 0; s < num_streams; s++) {
size_t packets_size;
size_t packets_size4 = read_32bitBE(packets_offset, streamfile); /* size * 4, no idea */
int num_packets;
if (packets_size4 == 0) {
VGM_LOG("EA XMA: null packets in stream %i at %lx\n", s, (off_t)packets_offset);
goto fail;
}
packets_size = (packets_size4 / 4) - 0x04;
num_packets = (int)(packets_size / EAXMA_XMA_PACKET_SIZE) + 1;
if (num_packets > max_packets)
max_packets = num_packets;
}
return max_packets;
fail:
return 0;
}
#endif

View File

@ -44,7 +44,7 @@ fail:
}
int ffmpeg_custom_read_wwise_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) {
int ffmpeg_custom_read_switch_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) {
uint8_t v_buf[0x8000]; /* intermediate buffer, could be simplified */
int buf_done = 0;
uint64_t real_offset = data->real_offset;
@ -98,7 +98,7 @@ int ffmpeg_custom_read_wwise_opus(ffmpeg_codec_data *data, uint8_t *buf, int buf
return buf_size;
}
int64_t ffmpeg_custom_seek_wwise_opus(ffmpeg_codec_data *data, int64_t virtual_offset) {
int64_t ffmpeg_custom_seek_switch_opus(ffmpeg_codec_data *data, int64_t virtual_offset) {
int64_t real_offset, virtual_base;
int64_t current_virtual_offset = data->virtual_offset;
@ -138,13 +138,13 @@ int64_t ffmpeg_custom_seek_wwise_opus(ffmpeg_codec_data *data, int64_t virtual_o
return virtual_offset;
}
int64_t ffmpeg_custom_size_wwise_opus(ffmpeg_codec_data *data) {
int64_t ffmpeg_custom_size_switch_opus(ffmpeg_codec_data *data) {
uint64_t real_offset = data->real_start;
uint64_t real_size = data->real_size;
uint64_t real_end_offset = data->real_start + data->real_size;
uint64_t virtual_size = data->header_size;
/* count all Wwise Opus blocks size + OggS page size */
while (real_offset < real_size) {
while (real_offset < real_end_offset) {
size_t extra_size;
size_t data_size = read_32bitBE(real_offset, data->streamfile);
/* 0x00: data size, 0x04: ? (not a sequence or CRC), 0x08+: data */
@ -159,7 +159,23 @@ int64_t ffmpeg_custom_size_wwise_opus(ffmpeg_codec_data *data) {
return virtual_size;
}
size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate, STREAMFILE *streamFile) {
size_t num_samples = 0;
off_t end_offset = offset + data_size;
/* count by reading all frames */
while (offset < end_offset) {
uint8_t buf[4];
size_t block_size = read_32bitBE(offset, streamFile);
read_streamfile(buf, offset+4, 4, streamFile);
num_samples += get_opus_samples_per_frame(buf, sample_rate);
offset += 0x08 + block_size;
}
return num_samples;
}
/* ************************************************** */
@ -316,8 +332,8 @@ fail:
static size_t make_opus_comment(uint8_t * buf, int buf_size) {
size_t comment_size;
int vendor_string_length, user_comment_0_length;
char * vendor_string = "libopus 1.0.2";
char * user_comment_0_string = "ENCODER=opusenc from opus-tools 0.1.6";
char * vendor_string = "vgmstream";
char * user_comment_0_string = "vgmstream Opus converter";
vendor_string_length = strlen(vendor_string);
user_comment_0_length = strlen(user_comment_0_string);
@ -342,5 +358,4 @@ fail:
return 0;
}
#endif

View File

@ -87,7 +87,7 @@ void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int chan
}
}
/* decodes u-law (ITU G.711 non-linear PCM) */
/* decodes u-law (ITU G.711 non-linear PCM), from g711.c */
void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
@ -119,6 +119,40 @@ void decode_ulaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
}
}
/* decodes a-law (ITU G.711 non-linear PCM), from g711.c */
void decode_alaw(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
int sign, segment, quantization, sample;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t alawbyte = read_8bit(stream->offset+i,stream->streamfile);
alawbyte ^= 0x55;
sign = (alawbyte & 0x80);
segment = (alawbyte & 0x70) >> 4; /* exponent */
quantization = alawbyte & 0x0F; /* mantissa */
sample = (quantization << 4);
switch (segment) {
case 0:
sample += 8;
break;
case 1:
sample += 0x108;
break;
default:
sample += 0x108;
sample <<= segment - 1;
break;
}
sample = (sign) ? sample : -sample;
outbuf[sample_count] = sample;
}
}
void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian) {
int i, sample_count;
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;

View File

@ -32,6 +32,7 @@ static const char* extension_list[] = {
//"aiff", //common
"aix",
"akb",
"al2",
"amts", //fake extension (to be removed)
"ao", //txth/reserved [Cloudphobia (PC)]
"as4",
@ -200,6 +201,7 @@ static const char* extension_list[] = {
"ogl",
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"omu",
"opus",
"otm",
"p1d", //txth/reserved [Farming Simulator 18 (3DS)]
@ -409,6 +411,7 @@ static const coding_info coding_info_list[] = {
{coding_PCM8_int, "8-bit PCM with 1 byte interleave"},
{coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"},
{coding_ULAW, "8-bit u-Law"},
{coding_ALAW, "8-bit a-Law"},
{coding_PCMFLOAT, "32-bit float PCM"},
{coding_CRI_ADX, "CRI ADX 4-bit ADPCM"},
{coding_CRI_ADX_exp, "CRI ADX 4-bit ADPCM with exponential scale"},
@ -638,9 +641,9 @@ static const meta_info meta_info_list[] = {
{meta_FSB4, "FMOD Sample Bank (FSB4) Header"},
{meta_FSB5, "FMOD Sample Bank (FSB5) Header"},
{meta_RWX, "RWX Header"},
{meta_XWB, "Microsoft XWB Header"},
{meta_XWB, "Microsoft XWB header"},
{meta_PS2_XA30, "Reflections XA30 PS2 header"},
{meta_MUSC, "MUSC Header"},
{meta_MUSC, "Krome MUSC header"},
{meta_MUSX_V004, "MUSX / Version 004 Header"},
{meta_MUSX_V005, "MUSX / Version 005 Header"},
{meta_MUSX_V006, "MUSX / Version 006 Header"},
@ -811,7 +814,7 @@ static const meta_info meta_info_list[] = {
{meta_FFW, "Freedom Fighters BGM header"},
{meta_DSP_DSPW, "DSPW dsp header"},
{meta_PS2_JSTM, "JSTM Header"},
{meta_PS3_XVAG, "XVAG Header"},
{meta_XVAG, "Sony XVAG header"},
{meta_PS3_CPS, "tri-Crescendo CPS Header"},
{meta_SQEX_SCD, "Square-Enix SCD header"},
{meta_NGC_NST_DSP, "Animaniacs NST header"},
@ -888,6 +891,8 @@ static const meta_info meta_info_list[] = {
{meta_BINK, "RAD Game Tools Bink header"},
{meta_EA_SNU, "Electronic Arts SNU header"},
{meta_AWC, "Rockstar AWC header"},
{meta_NSW_OPUS, ".OPUS header"},
{meta_PC_AL2, "Illwinter Game Design AL2 raw header"},
#ifdef VGM_USE_VORBIS
{meta_OGG_VORBIS, "Ogg Vorbis"},

View File

@ -18,15 +18,15 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) {
/* check header (the first 0x10 are BE/LE depending on platform) */
/* 0x00(1): related to sample rate? (03=48000)
* 0x01(1): flags? (when set seems to be a bank and has extra data before start_offset) //todo
* 0x01(1): flags/count? (when set has extra block data before start_offset)
* 0x02(1): always 0?
* 0x03(1): channels? (usually matches but rarely may be 0)
* 0x04(4): some size, maybe >>2 ~= number of frames
* 0x08(4): start offset
* 0x0c(4): some sub-offset? (0x20, found when 0x01 is set) */
* 0x0c(4): some sub-offset? (0x20, found when @0x01 is set) */
/* use start offset as endianness flag */
if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x00F00000) {
/* use start_offset as endianness flag */
if ((uint32_t)read_32bitLE(0x08,streamFile) > 0x0000FFFF) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
@ -48,6 +48,7 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) {
#if 0
//todo not working ok with blocks in XAS
//todo check if EA-XMA loops (Dante's Inferno doesn't)
if (flags & 0x60) { /* full loop, seen in ambient tracks */
loop_flag = 1;
loop_start = 0;
@ -81,7 +82,7 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_EA_SNU;
switch(codec) {
case 0x04: /* "Xas1": EA-XAS (Dead Space) */
case 0x04: /* "Xas1": EA-XAS (Dead Space PC/PS3) */
vgmstream->coding_type = coding_EA_XAS;
vgmstream->layout_type = layout_ea_sns_blocked;
break;
@ -112,8 +113,8 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) {
ffmpeg_custom_config cfg;
stream_size = get_streamfile_size(streamFile) - start_offset;
virtual_size = ffmpeg_get_eaxma_virtual_size(start_offset,stream_size, streamFile);
block_size = 0x8000; /* ? */
virtual_size = ffmpeg_get_eaxma_virtual_size(vgmstream->channels, start_offset,stream_size, streamFile);
block_size = 0x10000; /* todo unused and not correctly done by the parser */
block_count = stream_size / block_size + (stream_size % block_size ? 1 : 0);
bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, virtual_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
@ -122,6 +123,7 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) {
memset(&cfg, 0, sizeof(ffmpeg_custom_config));
cfg.type = FFMPEG_EA_XMA;
cfg.virtual_size = virtual_size;
cfg.channels = vgmstream->channels;
vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,stream_size, &cfg);
if (!vgmstream->codec_data) goto fail;

View File

@ -332,7 +332,7 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
uint8_t buf[FAKE_RIFF_BUFFER_SIZE];
size_t bytes, block_size, block_count;
/* not accurate but not needed by FFmpeg */
block_size = 2048;
block_size = 0x8000; /* FSB default */
block_count = fsbh.datasize / block_size; /* read_32bitLE(custom_data_offset +0x14) -1? */
/* make a fake riff so FFmpeg can parse the XMA2 */

View File

@ -251,13 +251,13 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case 0x0A: {/* FMOD_SOUND_FORMAT_XMA */
uint8_t buf[100];
uint8_t buf[0x100];
int bytes, block_size, block_count;
block_size = 0x10000; /* XACT default */
block_size = 0x8000; /* FSB default */
block_count = StreamSize / block_size + (StreamSize % block_size ? 1 : 0);
bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, StreamSize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, StreamSize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, StartOffset,StreamSize);

View File

@ -94,8 +94,8 @@ fail:
/* Tries to find the decryption key from a list. Simply decodes a few frames and checks if there aren't too many
* clipped samples, as it's common for invalid keys (though possible with valid keys in poorly mastered files). */
static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffer, int header_size, unsigned int * out_key1, unsigned int * out_key2) {
sample testbuf[clHCA_samplesPerBlock];
int i;
sample *testbuf = NULL, *temp;
int i, j, bufsize = 0, tempsize;
size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info);
int min_clip_count = -1;
@ -123,13 +123,23 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe
clHCA_clear(hca, key1, key2);
if (clHCA_Decode(hca, buffer, header_size, 0) < 0) continue;
if (clHCA_getInfo(hca, &hca_data->info) < 0) continue;
if (hca_data->info.channelCount > 32) continue; /* nonsense don't alloc too much */
tempsize = sizeof(sample) * clHCA_samplesPerBlock * hca_data->info.channelCount;
if (tempsize > bufsize) { /* should happen once */
temp = (sample *)realloc(testbuf, tempsize);
if (!temp) goto end;
testbuf = temp;
bufsize = tempsize;
}
/* test enough frames, but not too many */
while (f < HCA_KEY_MAX_TEST_FRAMES && f < hca_data->info.blockCount) {
decode_hca(hca_data, testbuf, clHCA_samplesPerBlock, hca_data->info.channelCount);
j = clHCA_samplesPerBlock;
decode_hca(hca_data, testbuf, j, hca_data->info.channelCount);
for (s = 0; s < clHCA_samplesPerBlock; s++) {
j *= hca_data->info.channelCount;
for (s = 0; s < j; s++) {
if (testbuf[s] != 0x0000 && testbuf[s] != 0xFFFF)
sample_count++; /* ignore upper/lower blank samples */
@ -165,7 +175,9 @@ static void find_hca_key(hca_codec_data * hca_data, clHCA * hca, uint8_t * buffe
hca_data->sample_ptr = clHCA_samplesPerBlock;
read_streamfile(buffer, hca_data->start, header_size, hca_data->streamfile);
end:
VGM_LOG("HCA: best key=%08x%08x (clips=%i)\n", best_key2,best_key1, min_clip_count);
*out_key2 = best_key2;
*out_key1 = best_key1;
free(testbuf);//free(temp);
}

View File

@ -5,7 +5,11 @@ typedef struct {
uint64_t key;
} hcakey_info;
/* CRI's tools expect an unsigned 64 bit number, but keys are commonly found online in hex form */
/**
* List of known keys, extracted from the game files (mostly found in 2ch.net).
* CRI's tools expect an unsigned 64 bit number string, but keys are commonly found online in hex form.
* Keys only use 56 bits though, so the upper 8 bits can be ignored.
*/
static const hcakey_info hcakey_list[] = {
// HCA Decoder default
@ -14,8 +18,6 @@ static const hcakey_info hcakey_list[] = {
// Phantasy Star Online 2 (multi?)
// used by most console games
{0xCC55463930DBE1AB}, // CC55463930DBE1AB / 14723751768204501419
// variation from VGAudio, but some 2ch poster says the above works with CRI's tools; seems to decode the same
{24002584467202475}, // 0055463930DBE1AB
// Old Phantasy Star Online 2 (multi?)
{61891147883431481}, // 30DBE1ABCC554639

View File

@ -536,7 +536,7 @@ VGMSTREAM * init_vgmstream_dsp_dspw(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_jstm(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_xvag(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE* streamFile);
@ -645,7 +645,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_x360_nub(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile);
@ -682,4 +682,8 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE * streamFile);
#endif /*_META_H*/

View File

@ -1,73 +1,50 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
/* MUSC (near all Spyro games and many other using this) */
/* MUSC - from Krome's PS2 games (The Legend of Spyro, Ty the Tasmanian Tiger) */
VGMSTREAM * init_vgmstream_musc(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag;
int channel_count;
int loop_flag, channel_count;
off_t start_offset;
size_t data_size;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("mus",filename_extension(filename)) &&
strcasecmp("musc",filename_extension(filename)))
goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x4D555343) /* MUSC */
goto fail;
/* check file size */
if ((read_32bitLE(0x10,streamFile)+read_32bitLE(0x14,streamFile)) != (get_streamfile_size(streamFile)))
goto fail;
loop_flag = 0;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* .mus is the real extension, .musc is the header ID */
if (!check_extensions(streamFile,"mus,musc"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4D555343) /* "MUSC" */
goto fail;
start_offset = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->channels = channel_count;
vgmstream->sample_rate = (uint16_t) read_16bitLE(0x06,streamFile);
vgmstream->num_samples = read_32bitLE(0x14,streamFile)/channel_count/16*28;
data_size = read_32bitLE(0x14,streamFile);
if (start_offset + data_size != get_streamfile_size(streamFile))
goto fail;
/* always does full loops unless it ends in silence */
loop_flag = read_32bitBE(get_streamfile_size(streamFile) - 0x10,streamFile) != 0x0C000000;
channel_count = 2;
#if 0
if (loop_flag)
{
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x14,streamFile))*28/16/channel_count;
}
#endif
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile)/2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x06,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_MUSC;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile) / 2;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,64 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* .OPUS - from Lego City Undercover (Switch) */
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count;
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x01000080)
goto fail;
start_offset = 0x28;
channel_count = read_8bit(0x09,streamFile); /* assumed */
/* other values in the header: no idea */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x0c,streamFile);
vgmstream->meta_type = meta_NSW_OPUS;
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
size_t bytes, skip, data_size;
ffmpeg_custom_config cfg;
data_size = get_streamfile_size(streamFile) - start_offset;
skip = 0; //todo
bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate);
if (bytes <= 0) goto fail;
memset(&cfg, 0, sizeof(ffmpeg_custom_config));
cfg.type = FFMPEG_SWITCH_OPUS;
vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile);
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -2,7 +2,7 @@
#include "../coding/coding.h"
/* Namco NUB xma - from Tekken 6, Galaga Legions DX */
VGMSTREAM * init_vgmstream_x360_nub(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, chunk_offset;
size_t data_size, chunk_size;

View File

@ -0,0 +1,40 @@
#include "meta.h"
#include "../coding/coding.h"
/* AL" - headerless a-law, found in Conquest of Elysium 3 (PC) */
VGMSTREAM * init_vgmstream_pc_al2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count;
if ( !check_extensions(streamFile,"al2"))
goto fail;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = 22050;
vgmstream->coding_type = coding_ALAW;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x01;
vgmstream->meta_type = meta_PC_AL2;
vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(streamFile), channel_count, 8);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
start_offset = 0;
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) {
STREAMFILE * streamHeader = NULL;
off_t start_offset, chunk_offset, name_offset = 0;
size_t data_size, chunk_size;
int loop_flag = 0, channel_count, is_separate, type, sample_rate;
int loop_flag = 0, channel_count, is_separate = 0, type, sample_rate;
int32_t loop_start, loop_end;
int total_streams, target_stream = streamFile->stream_index;

View File

@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
off_t start_offset, data_offset, chunk_offset, name_offset = 0;
size_t data_size;
int is_sgx, is_sgb;
int is_sgx, is_sgb = 0;
int loop_flag, channels, type;
int sample_rate, num_samples, loop_start_sample, loop_end_sample;
int total_streams, target_stream = streamFile->stream_index;

View File

@ -1,14 +1,11 @@
#include "meta.h"
#include "../coding/coding.h"
#define FAKE_RIFF_BUFFER_SIZE 100
/**
* VAWX - found in feelplus games: No More Heroes Heroes Paradise, Moon Diver
*/
/* VAWX - found in feelplus games (No More Heroes Heroes Paradise, Moon Diver) */
VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, datasize;
off_t start_offset, data_size;
int loop_flag = 0, channel_count, type;
@ -52,17 +49,17 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
case 1: { /* XMA2 */
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[FAKE_RIFF_BUFFER_SIZE];
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
/* todo not accurate (needed for >2ch) */
datasize = get_streamfile_size(streamFile)-start_offset;
block_size = 2048;
block_count = datasize / block_size; /* read_32bitLE(custom_data_offset +0x14) -1? */
bytes = ffmpeg_make_riff_xma2(buf, FAKE_RIFF_BUFFER_SIZE, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
data_size = get_streamfile_size(streamFile)-start_offset;
block_size = 0x10000; /* VAWX default */
block_count = (uint16_t)read_16bitBE(0x3A, streamFile); /* also at 0x56 */
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
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,data_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
@ -75,22 +72,22 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
}
case 7: { /* ATRAC3 */
uint8_t buf[FAKE_RIFF_BUFFER_SIZE];
uint8_t buf[0x100];
int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples;
datasize = read_32bitBE(0x54,streamFile);
data_size = read_32bitBE(0x54,streamFile);
block_size = 0x98 * vgmstream->channels;
joint_stereo = 0;
max_samples = atrac3_bytes_to_samples(datasize, block_size);
max_samples = atrac3_bytes_to_samples(data_size, block_size);
encoder_delay = 0x0; //max_samples - vgmstream->num_samples; /* todo not correct */
vgmstream->num_samples = max_samples; /* use calc samples since loop points are too, breaks looping in some files otherwise */
/* 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,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
if (bytes <= 0)
goto fail;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
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;

View File

@ -138,8 +138,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
case 0x0002: ww.codec = IMA; break; /* newer Wwise (conflicts with MSADPCM, probably means "platform's ADPCM") */
//case 0x0011: ww.codec = IMA; break; /* older Wwise (used?) */
case 0x0069: ww.codec = IMA; break; /* older Wwise (Spiderman Web of Shadows X360, LotR Conquest PC) */
case 0x0161: ww.codec = XWMA; break;
case 0x0162: ww.codec = XWMA; break;
case 0x0161: ww.codec = XWMA; break; /* WMAv2 */
case 0x0162: ww.codec = XWMA; break; /* WMAPro */
case 0x0165: ww.codec = XMA2; break; /* always with the "XMA2" chunk, Wwise doesn't use XMA1 */
case 0x0166: ww.codec = XMA2; break;
case 0x3039: ww.codec = OPUS; break;
@ -265,6 +265,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
cfg.blocksize_1_exp = read_8bit(vorb_offset + block_offsets + 0x00, streamFile); /* small */
cfg.blocksize_0_exp = read_8bit(vorb_offset + block_offsets + 0x01, streamFile); /* big */
}
ww.data_size -= audio_offset;
/* detect setup type:
* - full inline: ~2009, ex. The King of Fighters XII X360, The Saboteur PC
@ -284,8 +285,6 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
}
}
//ww.data_size -= audio_offset; //todo test
vgmstream->codec_data = init_vorbis_custom_codec_data(streamFile, start_offset + setup_offset, VORBIS_WWISE, &cfg);
if (!vgmstream->codec_data) goto fail;
}
@ -319,6 +318,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
audio_offset = read_32bit(extra_offset + data_offsets + 0x04, streamFile); /* within data */
cfg.blocksize_1_exp = read_8bit(extra_offset + block_offsets + 0x00, streamFile); /* small */
cfg.blocksize_0_exp = read_8bit(extra_offset + block_offsets + 0x01, streamFile); /* big */
ww.data_size -= audio_offset;
/* 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. */
@ -329,8 +329,6 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
cfg.packet_type = STANDARD;
}
//ww.data_size -= audio_offset; //todo test
/* try with the selected codebooks */
vgmstream->codec_data = init_vorbis_custom_codec_data(streamFile, start_offset + setup_offset, VORBIS_WWISE, &cfg);
if (!vgmstream->codec_data) {
@ -436,6 +434,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
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;
@ -446,11 +445,14 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
msd.data_size = ww.data_size;
if (ww.format == 0x0162)
wmapro_get_samples(&msd, streamFile, ww.block_align, ww.sample_rate,0x0000);
wmapro_get_samples(&msd, streamFile, ww.block_align, ww.sample_rate,0x00E0);
else
wma_get_samples(&msd, streamFile, ww.block_align, ww.sample_rate,0x0000);
wma_get_samples(&msd, streamFile, ww.block_align, ww.sample_rate,0x001F);
vgmstream->num_samples = ffmpeg_data->totalSamples; /* ffmpeg_data->totalSamples is approximate from avg-br */
vgmstream->num_samples = msd.num_samples;
if (!vgmstream->num_samples)
vgmstream->num_samples = ffmpeg_data->totalSamples; /* very wrong, from avg-br */
//num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2
}
break;
@ -482,7 +484,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
size_t seek_size;
vgmstream->num_samples += read_32bit(ww.fmt_offset + 0x18, streamFile);
//todo 0x1c and 0x20: related to samples/looping?
/* 0x1c: null? 0x20: data_size without seek_size */
seek_size = read_32bit(ww.fmt_offset + 0x24, streamFile);
start_offset += seek_size;
@ -498,7 +500,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
if (bytes <= 0) goto fail;
memset(&cfg, 0, sizeof(ffmpeg_custom_config));
cfg.type = FFMPEG_WWISE_OPUS;
cfg.type = FFMPEG_SWITCH_OPUS;
//cfg.big_endian = ww.big_endian; /* internally BE */
vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,ww.data_size, &cfg);

View File

@ -66,13 +66,12 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
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 */
/* fix samples; for now only XMA1 is fixed, but XMA2 num_samples don't include skip samples and xmaencode.exe doesn't use it */
if (is_xma1) {
ms_sample_data msd;
memset(&msd,0,sizeof(ms_sample_data));
msd.xma_version = 1;
msd.xma_version = is_xma1 ? 1 : 2;
msd.channels = channel_count;
msd.data_offset = start_offset;
msd.data_size = data_size;
@ -81,14 +80,14 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
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 */
msd.chunk_offset= chunk_offset;
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 */
/* XMA2 loop/num_samples don't seem to use msd.skip_samples */
}
@ -146,7 +145,8 @@ fail:
#if 0
/**
* Get real XMA sample rate (from Microsoft docs).
* Info only, not for playback as the encoder adjusts sample rate for looping purposes (sample<>data align).
* Info only, not for playback as the encoder adjusts sample rate for looping purposes (sample<>data align),
* When converting to PCM, xmaencode does use the modified sample rate.
*/
static int32_t get_xma_sample_rate(int32_t general_rate) {
int32_t xma_rate = 48000; /* default XMA */

View File

@ -5,7 +5,7 @@
static int ps_adpcm_find_loop_offsets(STREAMFILE *streamFile, int channel_count, off_t start_offset, off_t * loop_start, off_t * loop_end);
/* XVAG - Sony's (second party?) format (God of War III, Ratchet & Clank Future, The Last of Us, Uncharted) */
VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int loop_flag = 0, channel_count, codec;
@ -57,7 +57,7 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) {
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->meta_type = meta_PS3_XVAG;
vgmstream->meta_type = meta_XVAG;
switch (codec) {
case 0x06: /* PS ADPCM: God of War III, Uncharted 1/2, Ratchet and Clank Future */

View File

@ -455,7 +455,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
}
start_offset = xwb.data_offset;
start_offset = xwb.stream_offset;
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
goto fail;

View File

@ -292,7 +292,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_ffw,
init_vgmstream_dsp_dspw,
init_vgmstream_ps2_jstm,
init_vgmstream_ps3_xvag,
init_vgmstream_xvag,
init_vgmstream_ps3_cps,
init_vgmstream_sqex_scd,
init_vgmstream_ngc_nst_dsp,
@ -350,7 +350,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_wwise,
init_vgmstream_ubi_raki,
init_vgmstream_x360_pasx,
init_vgmstream_x360_nub,
init_vgmstream_nub_xma,
init_vgmstream_xma,
init_vgmstream_sxd,
init_vgmstream_ogl,
@ -369,6 +369,8 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_stm,
init_vgmstream_ea_snu,
init_vgmstream_awc,
init_vgmstream_nsw_opus,
init_vgmstream_pc_al2,
init_vgmstream_txth, /* should go at the end (lower priority) */
#ifdef VGM_USE_FFMPEG
@ -981,6 +983,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_PCM8_SB_int:
case coding_PCM8_U_int:
case coding_ULAW:
case coding_ALAW:
case coding_PCMFLOAT:
return 1;
#ifdef VGM_USE_VORBIS
@ -1140,6 +1143,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_PCM8_SB_int:
case coding_PCM8_U_int:
case coding_ULAW:
case coding_ALAW:
return 1;
case coding_PCMFLOAT:
return 4;
@ -1378,6 +1382,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_ALAW:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_alaw(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break;
case coding_PCMFLOAT:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_pcmfloat(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,

View File

@ -95,6 +95,7 @@ typedef enum {
coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave */
coding_ULAW, /* 8-bit u-Law (non-linear PCM) */
coding_ALAW, /* 8-bit a-Law (non-linear PCM) */
coding_PCMFLOAT, /* 32 bit float PCM */
@ -361,7 +362,7 @@ typedef enum {
meta_RWX, /* Air Force Delta Storm (XBOX) */
meta_XWB, /* Microsoft XACT framework (Xbox, X360, Windows) */
meta_PS2_XA30, /* Driver - Parallel Lines (PS2) */
meta_MUSC, /* Spyro Games, possibly more */
meta_MUSC, /* Krome PS2 games */
meta_MUSX_V004, /* Spyro Games, possibly more */
meta_MUSX_V005, /* Spyro Games, possibly more */
meta_MUSX_V006, /* Spyro Games, possibly more */
@ -565,7 +566,7 @@ typedef enum {
meta_SQEX_SCD, /* Square-Enix SCD */
meta_NGC_NST_DSP, /* Animaniacs [NGC] */
meta_BAF, /* Bizarre Creations (Blur, James Bond) */
meta_PS3_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */
meta_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */
meta_PS3_CPS, /* Eternal Sonata (PS3) */
meta_PS3_MSF, /* MSF header */
meta_NUB_VAG, /* Namco VAG from NUB archives */
@ -635,6 +636,8 @@ typedef enum {
meta_BINK, /* RAD Game Tools BINK audio/video */
meta_EA_SNU, /* Electronic Arts SNU (Dead Space) */
meta_AWC, /* Rockstar AWC (GTA5, RDR) */
meta_NSW_OPUS, /* Lego City Undercover (Switch) */
meta_PC_AL2, /* Conquest of Elysium 3 (PC) */
#ifdef VGM_USE_VORBIS
meta_OGG_VORBIS, /* Ogg Vorbis */
@ -1037,8 +1040,8 @@ typedef struct {
/* Custom FFMPEG modes */
typedef enum {
FFMPEG_STANDARD, /* default FFmpeg */
FFMPEG_WWISE_OPUS, /* Opus without Ogg layer */
FFMPEG_EA_XMA, /* XMA with padding removed in SNS blocks */
FFMPEG_SWITCH_OPUS, /* Opus without Ogg layer */
FFMPEG_EA_XMA, /* XMA with padding removed and custom streams in SNS blocks */
//FFMPEG_EA_SCHL, /* Normal header+data (ex. ATRAC3) in SCxx blocks */
//FFMPEG_SFH, /* ATRAC3plus header+data in SFH blocks */
//FFMPEG_AWC_XMA, /* XMA data in AWC blocks, 1 streams per channel */
@ -1048,6 +1051,7 @@ typedef enum {
typedef struct {
int stream_index; /* FFmpeg's sub-stream (as opposed to an internal stream in custom read/seeks) */
int codec_endian;
int channels;
ffmpeg_custom_t type; /* ffmpeg subtype */
size_t virtual_size; /* external value, if meta needs to know/supply it */