diff --git a/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj index 7f7461209..007a8adee 100644 --- a/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj @@ -345,6 +345,11 @@ 838BDB7B1D3B1FC20022CA6F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB7A1D3B1FC20022CA6F /* CoreMedia.framework */; }; 838BDB7D1D3B1FCC0022CA6F /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB7C1D3B1FCC0022CA6F /* CoreVideo.framework */; }; 838BDB7F1D3B1FD10022CA6F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB7E1D3B1FD10022CA6F /* Cocoa.framework */; }; + 83A3F0741E3AD8B900D6A794 /* formats.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A3F0711E3AD8B900D6A794 /* formats.c */; }; + 83A3F0751E3AD8B900D6A794 /* formats.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A3F0721E3AD8B900D6A794 /* formats.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 */; }; 83BAFB6C19F45EB3005DAB60 /* bfstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BAFB6B19F45EB3005DAB60 /* bfstm.c */; }; 83D731101A7394BF00CA1366 /* g7221.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83D730EB1A738EB300CA1366 /* g7221.framework */; }; @@ -804,6 +809,11 @@ 838BDB7A1D3B1FC20022CA6F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; 838BDB7C1D3B1FCC0022CA6F /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; 838BDB7E1D3B1FD10022CA6F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 83A3F0711E3AD8B900D6A794 /* formats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = formats.c; sourceTree = ""; }; + 83A3F0721E3AD8B900D6A794 /* formats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = formats.h; sourceTree = ""; }; + 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = ""; }; + 83A3F07A1E3AD92400D6A794 /* ps2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2.c; sourceTree = ""; }; + 83A3F07B1E3AD92400D6A794 /* x360.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360.c; sourceTree = ""; }; 83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = ""; }; 83BAFB6B19F45EB3005DAB60 /* bfstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfstm.c; sourceTree = ""; }; 83D730E51A738EB200CA1366 /* g7221.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = g7221.xcodeproj; path = ../g7221/g7221.xcodeproj; sourceTree = ""; }; @@ -945,6 +955,9 @@ 836F6DDF18BDC2180095E648 /* coding */, 836F6DFF18BDC2180095E648 /* layout */, 836F6E2718BDC2180095E648 /* meta */, + 83A3F0711E3AD8B900D6A794 /* formats.c */, + 83A3F0721E3AD8B900D6A794 /* formats.h */, + 83A3F0731E3AD8B900D6A794 /* stack_alloc.h */, 836F6F1718BDC2190095E648 /* streamfile.c */, 836F6F1818BDC2190095E648 /* streamfile.h */, 836F6F1918BDC2190095E648 /* streamtypes.h */, @@ -1041,6 +1054,8 @@ 836F6E2718BDC2180095E648 /* meta */ = { isa = PBXGroup; children = ( + 83A3F07A1E3AD92400D6A794 /* ps2.c */, + 83A3F07B1E3AD92400D6A794 /* x360.c */, 8350C0591E071990009E0A93 /* ps2_svag_snk.c */, 8350C0541E071881009E0A93 /* xma.c */, 838BDB6D1D3B043C0022CA6F /* ffmpeg.c */, @@ -1321,7 +1336,9 @@ 836F6F3518BDC2190095E648 /* nwa_decoder.h in Headers */, 836F6F2718BDC2190095E648 /* g72x_state.h in Headers */, 836F705418BDC2190095E648 /* streamfile.h in Headers */, + 83A3F0761E3AD8B900D6A794 /* stack_alloc.h in Headers */, 8323894B1D22419B00482226 /* clHCA.h in Headers */, + 83A3F0751E3AD8B900D6A794 /* formats.h in Headers */, 836F705918BDC2190095E648 /* vgmstream.h in Headers */, 48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */, 836F705718BDC2190095E648 /* util.h in Headers */, @@ -1533,6 +1550,7 @@ 836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */, 836F703C18BDC2190095E648 /* wii_bns.c in Sources */, 836F6FA718BDC2190095E648 /* nds_strm.c in Sources */, + 83A3F0741E3AD8B900D6A794 /* formats.c in Sources */, 836F6F6E18BDC2190095E648 /* aix.c in Sources */, 836F703118BDC2190095E648 /* ss_stream.c in Sources */, 836F701018BDC2190095E648 /* ps2_xau.c in Sources */, @@ -1596,6 +1614,7 @@ 836F6F8218BDC2190095E648 /* ea_header.c in Sources */, 836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */, 836F6F7318BDC2190095E648 /* bcstm.c in Sources */, + 83A3F07D1E3AD92400D6A794 /* x360.c in Sources */, 836F704018BDC2190095E648 /* wii_sng.c in Sources */, 8350C0551E071881009E0A93 /* xma.c in Sources */, 836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */, @@ -1647,6 +1666,7 @@ 836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */, 836F6FE718BDC2190095E648 /* ps2_mib.c in Sources */, 836F6FAB18BDC2190095E648 /* ngc_bo2.c in Sources */, + 83A3F07C1E3AD92400D6A794 /* ps2.c in Sources */, 836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */, 836F702118BDC2190095E648 /* rs03.c in Sources */, 836F6F8418BDC2190095E648 /* emff.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index 92efe52dd..8baa4dc34 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -3,43 +3,42 @@ #include "../vgmstream.h" +/* adx_decoder */ void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - void adx_next_key(VGMSTREAMCHANNEL * stream); +/* g721_decoder */ void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void g72x_init_state(struct g72x_state *state_ptr); +/* ima_decoder */ void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_int_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_eacs_ima(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); - void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); - void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); - void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); - void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - 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_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +/* ngc_dsp_decoder */ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem); - int32_t dsp_nibbles_to_samples(int32_t nibbles); +void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing); +/* ngc_dtk_decoder */ void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +/* ngc_afc_decoder */ +void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* pcm_decoder */ void decode_pcm16LE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_pcm16LE_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); @@ -50,98 +49,108 @@ 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); +/* psx_decoder */ void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_invert_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - void decode_psx_badflags(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_hevag(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); -void decode_ffxi_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_hevag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_short_vag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - +/* xa_decoder */ void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void init_get_high_nibble(VGMSTREAM * vgmstream); -void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); +/*eaxa_decoder */ +void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_ea_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +/* sdx2_decoder */ +void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +/* sdx2_decoder */ +void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* ws_decoder */ +void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* acm_decoder */ +void decode_acm(ACMStream * acm, sample * outbuf, int32_t samples_to_do, int channelspacing); + +/* nwa_decoder */ +void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do); + +/* 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_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do); + +/* aica_decoder */ +void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* nds_procyon_decoder */ +void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* l5_555_decoder */ +void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* SASSC_decoder */ +void decode_SASSC(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* lsf_decode */ +void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +/* mtaf_decoder */ +void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels); + +/* hca_decoder */ +void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); + +/* ogg_vorbis_decoder */ #ifdef VGM_USE_VORBIS void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); #endif +/* mpeg_decoder */ +#ifdef VGM_USE_MPEG +mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels); +void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do); +void decode_mpeg(VGMSTREAMCHANNEL * stream, mpeg_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); +long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi); +void mpeg_set_error_logging(mpeg_codec_data * data, int enable); +#endif + +/* g7221_decoder */ +#ifdef VGM_USE_G7221 +void decode_g7221(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); +#endif + +/* g719_decoder */ +#ifdef VGM_USE_G719 +void decode_g719(VGMSTREAM *vgmstream, sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); +#endif + +/* mp4_aac_decoder */ #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); #endif -void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); -void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); -void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); -void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -#ifdef VGM_USE_MPEG -void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream, - mpeg_codec_data * data, - sample * outbuf, int32_t samples_to_do); -mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels); -long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi); -void decode_mpeg(VGMSTREAMCHANNEL * stream, - mpeg_codec_data * data, - sample * outbuf, int32_t samples_to_do, int channels); -#endif - -#ifdef VGM_USE_G7221 -void decode_g7221(VGMSTREAM *vgmstream, - sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); -#endif - -#ifdef VGM_USE_G719 -void decode_g719(VGMSTREAM *vgmstream, - sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); -#endif - +/* at3_decoder */ #ifdef VGM_USE_MAIATRAC3PLUS -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 +/* ffmpeg_decoder */ #ifdef VGM_USE_FFMPEG void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels); - void reset_ffmpeg(VGMSTREAM *vgmstream); - void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample); -#endif -void decode_acm(ACMStream * acm, sample * outbuf, - int32_t samples_to_do, int channelspacing); - -void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do); - -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_mono(VGMSTREAM * vgmstream, sample * outbuf, 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); - -void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_SASSC(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); - -void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels); - -void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); +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_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_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); #endif + +#endif /*_CODING_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/eaxa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/eaxa_decoder.c index 63dce2418..9d748a94b 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/eaxa_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/eaxa_decoder.c @@ -14,7 +14,7 @@ int32_t EA_TABLE[20]= { 0x00000000, 0x000000F0, 0x000001CC, 0x00000188, 0x00000007, 0x00000008, 0x0000000A, 0x0000000B, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFC}; -void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { +void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { uint8_t frame_info; int32_t sample_count; int32_t coef1,coef2; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c index ed04d357d..341022811 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c @@ -239,11 +239,6 @@ end: data->readNextPacket = readNextPacket; data->endOfStream = endOfStream; data->endOfAudio = endOfAudio; - - // And pad if we ran short (end of file) - if (framesReadNow < samples_to_do) { - memset(outbuf + framesReadNow * channels, 0, sizeof(sample) * channels * (samples_to_do - framesReadNow)); - } } @@ -268,42 +263,13 @@ void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample) { ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; int64_t ts; -#ifndef VGM_USE_FFMPEG_ACCURATE_LOOPING - /* Seek to loop start by timestamp (closest frame) + adjust skipping some samples */ - /* FFmpeg seeks by ts by design (since not all containers can accurately skip to a frame). */ - /* TODO: this seems to be off by +-1 frames in some cases */ - ts = num_sample; - if (ts >= data->sampleRate * 2) { - data->samplesToDiscard = data->sampleRate * 2; - ts -= data->samplesToDiscard; - } - else { - data->samplesToDiscard = (int)ts; - ts = 0; - } - - /* todo fix this properly */ - if (data->totalSamples) { - ts = (int)ts * (data->formatCtx->duration) / data->totalSamples; - } else { - data->samplesToDiscard = num_sample; - ts = 0; - } - - avformat_seek_file(data->formatCtx, data->streamIndex, ts - 1000, ts, ts, AVSEEK_FLAG_ANY); - avcodec_flush_buffers(data->codecCtx); -#endif /* ifndef VGM_USE_FFMPEG_ACCURATE_LOOPING */ - -#ifdef VGM_USE_FFMPEG_ACCURATE_LOOPING - /* Start from 0 and discard samples until loop_start for accurate looping (slower but not too noticeable) */ - /* We could also seek by offset (AVSEEK_FLAG_BYTE) to the frame closest to the loop then discard - * some samples, which is fast but would need calculations per format / when frame size is not constant */ + /* Start from 0 and discard samples until loop_start (slower but not too noticeable) */ + /* Due to various FFmpeg quirks seeking to a sample is erratic in many formats (would need extra steps) */ data->samplesToDiscard = num_sample; ts = 0; avformat_seek_file(data->formatCtx, data->streamIndex, ts, ts, ts, AVSEEK_FLAG_ANY); avcodec_flush_buffers(data->codecCtx); -#endif /* ifdef VGM_USE_FFMPEG_ACCURATE_LOOPING */ data->readNextPacket = 1; data->bytesConsumedFromDecodedFrame = INT_MAX; @@ -312,4 +278,208 @@ void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample) { } + + +/* ******************************************** */ +/* FAKE RIFF HELPERS */ +/* ******************************************** */ +static int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec); + +/** + * Copies a ATRAC3 riff to buf + * + * returns number of bytes in buf or -1 when buf is not big enough + */ +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) { + uint16_t codec_ATRAC3 = 0x0270; + size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4; + + if (buf_size < riff_size) + return -1; + + 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, "fmt ", 4); + put_32bitLE(buf+0x10, 0x20);/*fmt size*/ + put_16bitLE(buf+0x14, codec_ATRAC3); + 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) */ + put_32bitLE(buf+0x20, (int16_t)(block_align)); /* block align */ + + put_16bitLE(buf+0x24, 0x0e); /* extra data size */ + put_16bitLE(buf+0x26, 1); /* unknown, always 1 */ + put_16bitLE(buf+0x28, channels==1 ? 0x0800 : 0x1000); /* unknown (some size? 0x1000=2ch, 0x0800=1ch) */ + put_16bitLE(buf+0x2a, 0); /* unknown, always 0 */ + put_16bitLE(buf+0x2c, joint_stereo ? 0x0001 : 0x0000); + put_16bitLE(buf+0x2e, joint_stereo ? 0x0001 : 0x0000); /* repeated? */ + put_16bitLE(buf+0x30, 1); /* unknown, always 1 (frame_factor?) */ + put_16bitLE(buf+0x32, 0); /* unknown, always 0 */ + + memcpy(buf+0x34, "fact", 4); + put_32bitLE(buf+0x38, 0x8); /* fact size */ + put_32bitLE(buf+0x3c, sample_count); + put_32bitLE(buf+0x40, encoder_delay); + + memcpy(buf+0x44, "data", 4); + put_32bitLE(buf+0x48, data_size); /* data size */ + + return riff_size; +} + +/** + * Copies a XMA2 riff to buf + * + * returns number of bytes in buf or -1 when buf is not big enough + */ +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) { + uint16_t codec_XMA2 = 0x0166; + size_t riff_size = 4+4+ 4 + 0x3c + 4+4; + size_t bytecount; + uint32_t streams = 0; + uint32_t speakers = 0; /* see audiodefs.h */ + + if (buf_size < riff_size) + return -1; + + bytecount = sample_count * channels * sizeof(sample); + + /* untested (no support for > 2ch xma for now) */ + switch (channels) { + case 1: + streams = 1; + speakers = 0x00000004; /* FC */ + break; + case 2: + streams = 1; + speakers = 0x00000001 | 0x00000002; /* FL FR */ + break; + case 3: + streams = 3; + speakers = 0x00000001 | 0x00000002 | 0x00000004; /* FL FC FR */ + break; + case 4: + streams = 2; + speakers = 0x00000001 | 0x00000002 | 0x00000010 | 0x00000020; /* FL FR BL BR */ + break; + case 5: + streams = 3; + speakers = 0x00000001 | 0x00000002 | 0x00000010 | 0x00000020 | 0x00000004; /* FL C FR BL BR*/ + break; + case 6: + streams = 3; + speakers = 0x00000001 | 0x00000002 | 0x00000010 | 0x00000020 | 0x00000200 | 0x00000400; /* FL FR BL BR SL SR */ + break; + default: + streams = 1; + speakers = 0x80000000; + break; + } + + /*memset(buf,0, sizeof(uint8_t) * fmt_size);*/ + + 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, "fmt ", 4); + put_32bitLE(buf+0x10, 0x34);/*fmt size*/ + 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) */ + put_16bitLE(buf+0x20, (int16_t)(channels*sizeof(sample))); /* block align */ + put_16bitLE(buf+0x22, sizeof(sample)*8); /* bits per sample */ + + put_16bitLE(buf+0x24, 0x22); /* extra data size */ + 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 */ + /* (looping values not set, expected to be handled externally) */ + put_32bitLE(buf+0x34, 0); /* play begin */ + put_32bitLE(buf+0x38, 0); /* play length */ + put_32bitLE(buf+0x3c, 0); /* loop begin */ + 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 = entried in seek table */ + + memcpy(buf+0x48, "data", 4); + put_32bitLE(buf+0x4c, data_size); /* data size */ + + return riff_size; +} + + +/** + * Copies a XMA2 riff to buf from a fmt chunk offset + * + * returns number of bytes in buf or -1 when buf is not big enough + */ +int ffmpeg_make_riff_xma2_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) { + size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4; + uint8_t chunk[100]; + + if (buf_size < riff_size || fmt_size > 100) + goto fail; + if (read_streamfile(chunk,fmt_offset,fmt_size, streamFile) != fmt_size) + goto fail; + + if (big_endian) + ffmpeg_fmt_chunk_swap_endian(chunk, 0x166); + + 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, "fmt ", 4); + put_32bitLE(buf+0x10, fmt_size);/*fmt size*/ + memcpy(buf+0x14, chunk, fmt_size); + + memcpy(buf+0x14+fmt_size, "data", 4); + put_32bitLE(buf+0x14+fmt_size+4, data_size); /* data size */ + + return riff_size; + +fail: + return -1; +} + +/** + * Swaps endianness + * + * returns 0 on error + */ +static int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec) { + if (codec != 0x166) + goto fail; + + put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*wFormatTag*/ + put_16bitLE(chunk + 0x02, get_16bitBE(chunk + 0x02));/*nChannels*/ + put_32bitLE(chunk + 0x04, get_32bitBE(chunk + 0x04));/*nSamplesPerSec*/ + put_32bitLE(chunk + 0x08, get_32bitBE(chunk + 0x08));/*nAvgBytesPerSec*/ + put_16bitLE(chunk + 0x0c, get_16bitBE(chunk + 0x0c));/*nBlockAlign*/ + put_16bitLE(chunk + 0x0e, get_16bitBE(chunk + 0x0e));/*wBitsPerSample*/ + put_16bitLE(chunk + 0x10, get_16bitBE(chunk + 0x10));/*cbSize*/ + put_16bitLE(chunk + 0x12, get_16bitBE(chunk + 0x12));/*NumStreams*/ + put_32bitLE(chunk + 0x14, get_32bitBE(chunk + 0x14));/*ChannelMask*/ + put_32bitLE(chunk + 0x18, get_32bitBE(chunk + 0x18));/*SamplesEncoded*/ + put_32bitLE(chunk + 0x1c, get_32bitBE(chunk + 0x1c));/*BytesPerBlock*/ + put_32bitLE(chunk + 0x20, get_32bitBE(chunk + 0x20));/*PlayBegin*/ + put_32bitLE(chunk + 0x24, get_32bitBE(chunk + 0x24));/*PlayLength*/ + put_32bitLE(chunk + 0x28, get_32bitBE(chunk + 0x28));/*LoopBegin*/ + put_32bitLE(chunk + 0x2c, get_32bitBE(chunk + 0x2c));/*LoopLength*/ + /* put_8bit(chunk + 0x30, get_8bit(chunk + 0x30));*//*LoopCount*/ + /* put_8bit(chunk + 0x31, get_8bit(chunk + 0x31));*//*EncoderVersion*/ + put_16bitLE(chunk + 0x32, get_16bitBE(chunk + 0x32));/*BlockCount*/ + + return 1; + +fail: + return 0; +} + #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g72x_state.h b/Frameworks/vgmstream/vgmstream/src/coding/g72x_state.h index bf1a6ade5..9eec93bb0 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g72x_state.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/g72x_state.h @@ -1,5 +1,5 @@ /* - * streamtypes.h - widely used type definitions + * g72x_state.h - internal state used by g721 decoder */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c index 92c742406..f7b43c5b7 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c @@ -226,4 +226,11 @@ long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi) { return (int64_t)bytes * mi->rate * 8 / (mi->bitrate * 1000); } + +/** + * disables/enables stderr output, useful for MPEG known to contain recoverable errors + */ +void mpeg_set_error_logging(mpeg_codec_data * data, int enable) { + mpg123_param(data->m, MPG123_ADD_FLAGS, MPG123_QUIET, !enable); +} #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c index d631476bc..50e27672a 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c @@ -3,6 +3,8 @@ #include "coding.h" #include "../util.h" +#define MTAF_BLOCK_SUPPORT 0 + // A hybrid of IMA and Yamaha ADPCM found in Metal Gear Solid 3 // Thanks to X_Tra (http://metalgear.in/) for pointing me to the step size table. @@ -81,62 +83,79 @@ static int16_t step_size[32][16] = { void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels) { int32_t sample_count; - unsigned long cur_off = stream->offset; + off_t cur_off = stream->offset; int i; - int c = channel%2; - int16_t init_idx; - int16_t init_hist; + int c = channel%2; /* global channel to stream channel */ int32_t hist = stream->adpcm_history1_16; - int step_idx = stream->adpcm_step_index; - - //printf("channel %d: first_sample = %d, stream->offset = 0x%lx, cur_off = 0x%lx init_idx = %d\n", channel, first_sample, (unsigned long)stream->offset, cur_off, init_idx); + int32_t step_idx = stream->adpcm_step_index; + uint8_t byte = 0; -#if 0 - if (init_idx < 0 || init_idx > 31) { - fprintf(stderr, "step idx out of range at 0x%lx ch %d\n", cur_off, c); - exit(1); - } - if (0 != read_16bitLE(cur_off+10+c*4, stream->streamfile)) { - fprintf(stderr, "exp. zero after hist at 0x%lx ch %d\n", cur_off, c); - exit(1); + +#if MTAF_BLOCK_SUPPORT + { + /* "macroblock" support (layout/mtaf_block.c) was removed since the extractor now produces clean files; + * this a hack to skip those blocks, left as a reminder (not well tested) */ + int unk, size, empty, frames, repeat = 1; + do { + unk = read_32bitLE(cur_off+0x00, stream->streamfile); /* always BE 0x01001100? */ + size = read_32bitLE(cur_off+0x04, stream->streamfile); /* block size */ + empty = read_32bitLE(cur_off+0x08, stream->streamfile); /* always 0? */ + frames = read_32bitLE(cur_off+0x0c, stream->streamfile); /* total frames of 0x110 */ + if (unk == 0x00110001 && empty == 0 && size > 0) { + if (frames == 0) { + stream->offset += size; /* full skip */ + } else if ((size-0x10) == frames*0x110) { + stream->offset += 0x10; /* header skip */ + repeat = 0; + } + cur_off = stream->offset; + } + else { + repeat = 0; + } + + } while(repeat); } #endif - first_sample = first_sample%0x100; - - if (first_sample%0x100 == 0) { - while (read_8bit(cur_off, stream->streamfile) != 0) { - cur_off += 16; - } - - stream->offset = cur_off; + first_sample = first_sample % 0x100; - init_idx = read_16bitLE(cur_off+4+c*2, stream->streamfile); - init_hist = read_16bitLE(cur_off+8+c*4, stream->streamfile); - - hist = init_hist; + /* read header when we hit a new frame every 0x100 samples */ + if (first_sample == 0) { + int32_t init_idx, init_hist; -#if 0 - if (step_idx != init_idx) { - fprintf(stderr, "step_idx does not match at 0x%lx, %d!=%d\n",cur_off,step_idx, init_idx); - exit(1); + /* 0x10 header: owner stream, frame count, step-L, step-R, hist-L, hist-R */ + /* uint32_t stream = read_8bit(cur_off+0+c*2, stream->streamfile); */ /* 0=first */ + /* uint24_t frames = (uint24_t)read_16bitLE(cur_off+1, stream->streamfile); */ /* 1=first */ + init_idx = read_16bitLE(cur_off+4+c*2, stream->streamfile); /* step-L/R */ + init_hist = read_16bitLE(cur_off+4+4+c*4, stream->streamfile); /* hist-L/R: hist 16bit + empty 16bit */ + + VGM_ASSERT( read_16bitLE(cur_off+4+4+2+c*4, stream->streamfile) != 0, + "init_hist not 16bit at 0x%lx, ch=%d\n", cur_off, c); + VGM_ASSERT( init_idx < 0 || init_idx > 31, + "init_idx out of range at 0x%lx, ch=%d\n", cur_off, c); + VGM_ASSERT( step_idx != init_idx, + "step_idx does not match init_idx at 0x%lx, step=%d, init=%d\n",cur_off,step_idx, init_idx); + + /* avoid index out of range in corrupt files */ + if (init_idx < 0) { + init_idx = 0; + } else if (init_idx > 31) { + init_idx = 31; } -#endif + step_idx = init_idx; + hist = init_hist; } for (i=first_sample,sample_count=0; istreamfile); - if (i%2!=1) - { - // low nibble first - nibble = byte&0xf; - } - else - { - // high nibble last + uint8_t nibble; + + if (i%2 != 1) { /* low nibble first */ + byte = read_8bit(cur_off + 0x10 + 0x80*c + i/2, stream->streamfile); + nibble = byte & 0x0f; + } else { /* high nibble last */ nibble = byte >> 4; } @@ -145,12 +164,9 @@ void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, outbuf[sample_count] = hist; step_idx += index_table[nibble]; - if (step_idx < 0) - { + if (step_idx < 0) { /* clip step */ step_idx = 0; - } - if (step_idx > 31) - { + } else if (step_idx > 31) { step_idx = 31; } } /* end sample loop */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c index 27825ae96..5b87c45b8 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c @@ -20,11 +20,6 @@ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci for (i=first_sample,sample_count=0; ioffset+1+i/2,stream->streamfile); -#ifdef DEBUG - if (hist1==stream->loop_history1 && hist2==stream->loop_history2) fprintf(stderr,"yo! %#x (start %#x) %d\n",stream->offset+framesin*8+i/2,stream->channel_start_offset,stream->samples_done); - stream->samples_done++; -#endif - outbuf[sample_count] = clamp16(( (((i&1? get_low_nibble_signed(sample_byte): @@ -61,11 +56,6 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels for (i=first_sample,sample_count=0; iloop_history1 && hist2==stream->loop_history2) fprintf(stderr,"yo! %#x (start %#x) %d\n",stream->offset+framesin*8+i/2,stream->channel_start_offset,stream->samples_done); - stream->samples_done++; -#endif - outbuf[sample_count] = clamp16(( (((i&1? get_low_nibble_signed(sample_byte): @@ -104,3 +94,19 @@ int32_t dsp_nibbles_to_samples(int32_t nibbles) { if (remainder>0) return whole_frames*14+remainder-2; else return whole_frames*14; } + + +/** + * reads DSP coefs built in the streamfile + */ +void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing) { + int ch, i; + /* get ADPCM coefs */ + for (ch=0; ch < vgmstream->channels; ch++) { + for (i=0; i < 16; i++) { + vgmstream->ch[ch].adpcm_coef[i] = + read_16bitBE(offset + ch*spacing + i*2, streamFile); + } + } +} + diff --git a/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c index c84842693..f04457ee7 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c @@ -3,8 +3,7 @@ #include "../util.h" /* for some algos, maybe closer to the real thing */ -#define VAG_USE_INTEGER_TABLE 0 - +#define VAG_USE_INTEGER_TABLE 0 /* PS ADPCM table (precalculated divs) */ static const double VAG_f[5][2] = { @@ -14,6 +13,7 @@ static const double VAG_f[5][2] = { { 98.0 / 64.0 , -55.0 / 64.0 }, { 122.0 / 64.0 , -60.0 / 64.0 } }; +#if VAG_USE_INTEGER_TABLE /* PS ADPCM table */ static const int8_t VAG_coefs[5][2] = { { 0 , 0 }, @@ -22,7 +22,7 @@ static const int8_t VAG_coefs[5][2] = { { 98 , -55 }, { 122 , -60 } }; - +#endif /* PSVita ADPCM table */ static const int16_t HEVAG_coefs[128][4] = { @@ -214,7 +214,7 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, stream->adpcm_history2_32=hist2; } -void decode_invert_psx(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) { int predict_nr, shift_factor, sample; int32_t hist1=stream->adpcm_history1_32; @@ -294,84 +294,6 @@ void decode_psx_badflags(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel stream->adpcm_history2_32=hist2; } -/* FF XI's Vag-ish format */ -void decode_ffxi_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - - int predict_nr, shift_factor, sample; - int32_t hist1=stream->adpcm_history1_32; - int32_t hist2=stream->adpcm_history2_32; - - short scale; - int i; - int32_t sample_count; - int32_t predictor; - - int framesin = first_sample/16; - - predict_nr = read_8bit(stream->offset+framesin*9,stream->streamfile) >> 4; - shift_factor = read_8bit(stream->offset+framesin*9,stream->streamfile) & 0xf; - first_sample = first_sample % 16; - - for (i=first_sample,sample_count=0; ioffset+(framesin*9)+1+i/2,stream->streamfile); - - sample=0; - - scale = ((i&1 ? - sample_byte >> 4 : - sample_byte & 0x0f)<<12); - -#if !VAG_USE_INTEGER_TABLE - predictor = - (int)((hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1])); -#else - predictor = - (hist1*VAG_coefs[predict_nr][0]+hist2*VAG_coefs[predict_nr][1])/64; -#endif - sample=(scale >> shift_factor) + predictor; - - outbuf[sample_count] = clamp16(sample); - hist2=hist1; - hist1=sample; - } - stream->adpcm_history1_32=hist1; - stream->adpcm_history2_32=hist2; -} - -void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - - int predict_nr, shift_factor, sample; - int32_t hist1=stream->adpcm_history1_32; - int32_t hist2=stream->adpcm_history2_32; - - short scale; - int i; - int32_t sample_count; - - int framesin = first_sample/64; - - predict_nr = read_8bit(stream->offset+framesin*33,stream->streamfile) >> 4; - shift_factor = read_8bit(stream->offset+framesin*33,stream->streamfile) & 0xf; - - first_sample = first_sample % 64; - - for (i=first_sample,sample_count=0; ioffset+(framesin*33)+1+i/2,stream->streamfile); - - scale = ((i&1 ? - sample_byte >> 4 : - sample_byte & 0x0f)<<12); - - sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]); - - outbuf[sample_count] = clamp16(sample); - hist2=hist1; - hist1=sample; - } - stream->adpcm_history1_32=hist1; - stream->adpcm_history2_32=hist2; -} - /** * Sony's HEVAG (High Efficiency VAG) ADPCM, used in PSVita games (hardware decoded). @@ -379,7 +301,7 @@ void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspa * * Original research and algorithm by id-daemon / daemon1. */ -void decode_hevag_adpcm(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) { uint8_t predict_nr, shift, flag, byte; int32_t scale = 0; @@ -405,6 +327,10 @@ void decode_hevag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels first_sample = first_sample % 28; + if (first_sample & 1) { /* if first sample is odd, read byte first */ + byte = read_8bit(stream->offset+(framesin*16)+2+first_sample/2,stream->streamfile); + } + for (i = first_sample, sample_count = 0; i < first_sample + samples_to_do; i++, sample_count += channelspacing) { sample = 0; @@ -442,11 +368,10 @@ void decode_hevag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels /** - * Short VAG ADPCM, found in PS3 Afrika (SGDX type 5). - * Uses 8 byte blocks and no flag. + * PS ADPCM of configurable size, with no flag. + * Found in PS3 Afrika (SGDX type 5) in size 4, FF XI in sizes 3/5/9/41, Blur and James Bond in size 33. */ -void decode_short_vag_adpcm(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) { uint8_t predict_nr, shift, byte; int16_t scale = 0; @@ -454,37 +379,50 @@ void decode_short_vag_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int chan int32_t hist1 = stream->adpcm_history1_32; int32_t hist2 = stream->adpcm_history2_32; - int i, sample_count; + int i, sample_count, bytes_per_frame, samples_per_frame; + const int header_size = 1; + int framesin; + bytes_per_frame = frame_size - header_size; + samples_per_frame = bytes_per_frame * 2; - int framesin = first_sample / 6; + framesin = first_sample / samples_per_frame; - /* 2 byte header: predictor = 1st, shift = 2nd */ - byte = (uint8_t)read_8bit(stream->offset+framesin*8+0,stream->streamfile); + /* 1 byte header: predictor = 1st, shift = 2nd */ + byte = (uint8_t)read_8bit(stream->offset+framesin*frame_size+0,stream->streamfile); predict_nr = byte >> 4; shift = byte & 0x0f; - first_sample = first_sample % 6; + first_sample = first_sample % samples_per_frame; + + if (first_sample & 1) { /* if restarting on a high nibble, read byte first */ + byte = (uint8_t)read_8bit(stream->offset+(framesin*frame_size)+header_size+first_sample/2,stream->streamfile); + } for (i = first_sample, sample_count = 0; i < first_sample + samples_to_do; i++, sample_count += channelspacing) { sample = 0; if (predict_nr < 5) { - - if (i & 1) {/* odd/even nibble */ - scale = byte >> 4; - } else { - byte = (uint8_t)read_8bit(stream->offset+(framesin*8)+1+i/2,stream->streamfile); + if (!(i&1)) { /* low nibble first */ + byte = (uint8_t)read_8bit(stream->offset+(framesin*frame_size)+header_size+i/2,stream->streamfile); scale = (byte & 0x0f); + } else { /* high nibble last */ + scale = byte >> 4; } + scale = scale << 12; /* shift + sign extend (only if scale is int16_t) */ /*if (scale > 7) { scale = scale - 16; }*/ - scale = scale << 12; /* shift + sign extend only if scale is int16_t */ - - sample = (hist1 * VAG_coefs[predict_nr][0] + +#if VAG_USE_INTEGER_TABLE + sample = (scale >> shift) + + (hist1 * VAG_coefs[predict_nr][0] + hist2 * VAG_coefs[predict_nr][1] ) / 64; - sample = sample + (scale >> shift); + sample = sample + ; +#else + sample = (int)( (scale >> shift) + + (hist1 * VAG_f[predict_nr][0] + + hist2 * VAG_f[predict_nr][1]) ); +#endif } outbuf[sample_count] = clamp16(sample); diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c new file mode 100644 index 000000000..5b388a19c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -0,0 +1,871 @@ +#include "formats.h" + +//#define VGM_REGISTER_TYPE(extension) ... +//#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */ + + +/* some extensions could be #ifdef but no really needed */ +/* some formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension is not parsed */ + +static const char* extension_list[] = { + "2dx9", + "2pfs", + + "aa3", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) + "aaap", + "aax", + //"ac3", //FFmpeg, not parsed //common? + "acm", + "adm", + "adp", + "adpcm", + "ads", + "adx", + "afc", + "agsc", + "ahx", + "aifc", + "aifcl", + //"aiff", //common + "aix", + "akb", //AAC + "amts", + "as4", + "asd", + "asf", + "asr", + "ass", + "ast", + "at3", + "aud", + "aus", + + "b1s", + "baf", + "baka", + "bar", + "bcstm", + "bcwav", + "bdsp", + "bfstm", + "bfwav", + "bfwavnsmbu", + "bg00", + "bgw", + "bh2pcm", + "bmdx", + "bms", + "bnk", + "bns", + "bnsf", + "bo2", + "brstm", + "brstmspm", + "btsnd", + "bvg", + + "caf", + "capdsp", + "cbd2", + "ccc", + "cfn", + "ckd", + "cnk", + "cps", + "cxs", + + "dcs", + "ddsp", + "de2", + "dmsg", + "dsp", + "dspw", + "dtk", + "dvi", + "dxh", + + "eam", + "emff", + "enth", + + "fag", + "ffw", + "filp", + "fsb", + "fwav", + + "g1l", + "gbts", + "gca", + "gcm", + "gcub", + "gcw", + "genh", + "gms", + "gsb", + + "hca", + "hgc1", + "his", + "hlwav", + "hps", + "hsf", + "hwas", + + "iab", + "iadp", + "idsp", + "idvi", + "ikm", + "ild", + "int", + "isd", + "isws", + "ivaud", + "ivag", + "ivb", + + "joe", + "jstm", + + "kces", + "kcey", + "khv", + "kovs", + "kraw", + + "leg", + "logg", + "lpcm", + "lps", + "lsf", + "lwav", + + "matx", + "mca", + "mcg", + "mi4", + "mib", + "mic", + "mihb", + "mnstr", + "mpdsp", + "mpds", + "msa", + "msf", + "mss", + "msvp", + "mtaf", + "mus", + "musc", + "musx", + "mwv", + "mxst", + "myspd", + + "ndp", + "ngca", + "nps", + "npsf", + "nus3bank", //todo not existing? + "nwa", + + "oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) + "omu", + "otm", + + "p2bt", + "p3d", + "past", + "pcm", + "pdt", + "pnb", + "pona", + "pos", + "ps2stm", + "psh", + "psnd", + "psw", + + "ras", + "raw", + "rkv", + "rnd", + "rrds", + "rsd", + "rsf", + "rstm", + "rvws", + "rwar", + "rwav", + "rws", + "rwsd", + "rwx", + "rxw", + + "s14", + "sab", + "sad", + "sap", + "sc", + "scd", + "sck", + "sd9", + "sdt", + "seg", + "sf0", + "sfl", + "sfs", + "sfx", + "sgb", + "sgd", + "sgx", + "sl3", + "sli", + "smp", + "smpl", + "snd", + "snds", + "sng", + "sns", + "spd", + "spm", + "sps", + "spsd", + "spw", + "ss2", + "ss3", + "ss7", + "ssm", + "sss", + "ster", + "sth", + //"stm", //common + "stma", + "str", + "strm", + "sts", + "stx", + "svag", + "svs", + "swag", + "swav", + "swd", + + "tec", + "thp", + "tk1", + "tk5", + "tra", + "tun", + "tydsp", + + "um3", + + "vag", + "vas", + "vawx", + "vb", + "vbk", + "vgs", + "vgv", + "vig", + + "vds", + "vdm", + "vms", + "vms", + "voi", + "vpk", + "vs", + "vsf", + + "waa", + "wac", + "wad", + "wam", + "was", + "wavm", + "wb", + "wii", + "wmus", + "wp2", + "wpd", + "wsd", + "wsi", + "wvs", + + "xa", + "xa2", + "xa30", + "xag", + "xau", + "xma", + "xma2", + "xmu", + "xnb", + "xsf", + "xss", + "xvag", + "xvas", + "xwav", + "xwb", + "xwm", //FFmpeg, not parsed (XWMA) + "xwma", //FFmpeg, not parsed (XWMA) + "xwv", + + "ydsp", + "ymf", + + "zsd", + "zwdsp", + + "vgmstream" + + //, NULL //end mark +}; + +/** + * List of supported formats. + * + * For plugins that need to know (test.exe doesn't use it) + */ +const char ** vgmstream_get_formats() { + return extension_list; +} + +/** + * Number of elements in the list. + */ +int vgmstream_get_formats_length() { + return sizeof(extension_list) / sizeof(char*); +} + + +/* internal description info */ + +typedef struct { + coding_t type; + const char *description; +} coding_info; + +typedef struct { + layout_t type; + const char *description; +} layout_info; + +typedef struct { + meta_t type; + const char *description; +} meta_info; + + +static const coding_info coding_info_list[] = { + {coding_PCM16BE, "Big Endian 16-bit PCM"}, + {coding_PCM16LE, "Little Endian 16-bit PCM"}, + {coding_PCM16LE_int, "Little Endian 16-bit PCM with 2 byte interleave"}, + {coding_PCM16LE_XOR_int, "Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"}, + {coding_PCM8, "8-bit PCM"}, + {coding_PCM8_U, "8-bit unsigned PCM"}, + {coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave"}, + {coding_PCM8_int, "8-bit PCM with 1 byte interleave"}, + {coding_PCM8_SB_int, "8-bit PCM with sign bit, 1 byte interleave"}, + {coding_CRI_ADX, "CRI ADX 4-bit ADPCM"}, + {coding_CRI_ADX_enc_8, "CRI ADX 4-bit ADPCM (type 8 encryption)"}, + {coding_CRI_ADX_enc_9, "CRI ADX 4-bit ADPCM (type 8 encryption)"}, + {coding_NGC_DSP, "Nintendo DSP 4-bit ADPCM"}, + {coding_NGC_DTK, "Nintendo DTK 4-bit ADPCM"}, + {coding_NGC_AFC, "Nintendo AFC 4-bit ADPCM"}, + {coding_CRI_HCA, "CRI HCA"}, + {coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"}, + {coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"}, + {coding_G721, "CCITT G.721 4-bit ADPCM"}, + {coding_PSX, "Playstation 4-bit ADPCM"}, + {coding_PSX_badflags, "Playstation 4-bit ADPCM (bad flags)"}, + {coding_PSX_bmdx, "Playstation 4-bit ADPCM (BMDX encryption)"}, + {coding_PSX_cfg, "Playstation 4-bit ADPCM (configurable)"}, + {coding_HEVAG, "Playstation Vita HEVAG 4-bit ADPCM"}, + {coding_XA, "CD-ROM XA 4-bit ADPCM"}, + {coding_XBOX, "XBOX 4-bit IMA ADPCM"}, + {coding_INT_XBOX, "XBOX 4-bit IMA ADPCM (interleaved)"}, + {coding_EA_XA, "Electronic Arts 4-bit ADPCM (XA based)"}, + {coding_EA_ADPCM, "Electronic Arts R1 4-bit ADPCM (XA based)"}, + {coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, + {coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"}, + {coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"}, + {coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"}, + {coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"}, + {coding_INT_DVI_IMA, "Interleaved Intel DVI 4-bit IMA ADPCM"}, + {coding_EACS_IMA, "EACS 4-bit IMA ADPCM"}, + {coding_MAXIS_ADPCM, "Maxis XA (EA ADPCM Variant)"}, + {coding_INT_IMA, "Interleaved 4-bit IMA ADPCM"}, + {coding_IMA, "4-bit IMA ADPCM"}, + {coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"}, + {coding_RAD_IMA, "'Radical' 4-bit IMA ADPCM"}, + {coding_RAD_IMA_mono, "'Radical' 4-bit IMA ADPCM (mono)"}, + {coding_APPLE_IMA4, "Apple Quicktime 4-bit IMA ADPCM"}, + {coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"}, + {coding_WS, "Westwood Studios ADPCM"}, + {coding_ACM, "InterPlay ACM"}, + {coding_NWA0, "NWA DPCM Level 0"}, + {coding_NWA1, "NWA DPCM Level 1"}, + {coding_NWA2, "NWA DPCM Level 2"}, + {coding_NWA3, "NWA DPCM Level 3"}, + {coding_NWA4, "NWA DPCM Level 4"}, + {coding_NWA5, "NWA DPCM Level 5"}, + {coding_MSADPCM, "Microsoft 4-bit ADPCM"}, + {coding_AICA, "Yamaha AICA 4-bit ADPCM"}, + {coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"}, + {coding_L5_555, "Level-5 0x555 4-bit ADPCM"}, + {coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"}, + {coding_LSF, "lsf 4-bit ADPCM"}, + {coding_MTAF, "Konami MTAF 4-bit ADPCM"}, +#ifdef VGM_USE_VORBIS + {coding_ogg_vorbis, "Vorbis"}, +#endif +#ifdef VGM_USE_MPEG + {coding_fake_MPEG2_L2, "MPEG-2 Layer II Audio"}, + {coding_MPEG1_L1, "MPEG-1 Layer I Audio"}, + {coding_MPEG1_L2, "MPEG-1 Layer II Audio"}, + {coding_MPEG1_L3, "MPEG-1 Layer III Audio (MP3)"}, + {coding_MPEG2_L1, "MPEG-2 Layer I Audio"}, + {coding_MPEG2_L2, "MPEG-2 Layer II Audio"}, + {coding_MPEG2_L3, "MPEG-2 Layer III Audio (MP3)"}, + {coding_MPEG25_L1, "MPEG-2.5 Layer I Audio"}, + {coding_MPEG25_L2, "MPEG-2.5 Layer II Audio"}, + {coding_MPEG25_L3, "MPEG-2.5 Layer III Audio (MP3)"}, +#endif +#ifdef VGM_USE_G7221 + {coding_G7221, "ITU G.722.1 (Polycom Siren 7)"}, + {coding_G7221C, "ITU G.722.1 annex C (Polycom Siren 14)"}, +#endif +#ifdef VGM_USE_G719 + {coding_G719, "ITU G.719 annex B (Polycom Siren 22)"}, +#endif +#ifdef VGM_USE_MAIATRAC3PLUS + {coding_AT3plus, "ATRAC3plus"}, +#endif +#ifdef VGM_USE_FFMPEG + {coding_FFmpeg, "FFmpeg"}, +#endif +}; + +static const layout_info layout_info_list[] = { + {layout_none, "flat (no layout)"}, + {layout_interleave, "interleave"}, + {layout_interleave_shortblock, "interleave with short last block"}, + {layout_interleave_byte, "sub-frame interleave"}, + {layout_mxch_blocked, "MxCh blocked"}, + {layout_ast_blocked, "AST blocked"}, + {layout_halpst_blocked, "HALPST blocked"}, + {layout_xa_blocked, "CD-ROM XA"}, + {layout_ea_blocked, "Electronic Arts Audio Blocks"}, + {layout_eacs_blocked, "Electronic Arts (Old Version) Audio Blocks"}, + {layout_caf_blocked, "CAF blocked"}, + {layout_wsi_blocked, ".wsi blocked"}, + {layout_xvas_blocked, ".xvas blocked"}, + {layout_str_snds_blocked, ".str SNDS blocked"}, + {layout_ws_aud_blocked, "Westwood Studios .aud blocked"}, + {layout_matx_blocked, "Matrix .matx blocked"}, + {layout_de2_blocked, "de2 blocked"}, + {layout_vs_blocked, "vs blocked"}, + {layout_emff_ps2_blocked, "EMFF (PS2) blocked"}, + {layout_emff_ngc_blocked, "EMFF (NGC/WII) blocked"}, + {layout_gsb_blocked, "GSB blocked"}, + {layout_thp_blocked, "THP Movie Audio blocked"}, + {layout_filp_blocked, "FILp blocked"}, + {layout_psx_mgav_blocked, "MGAV blocked"}, + {layout_ps2_adm_blocked, "ADM blocked"}, + {layout_dsp_bdsp_blocked, "DSP blocked"}, + {layout_ivaud_blocked, "GTA IV blocked"}, + {layout_ps2_iab_blocked, "IAB blocked"}, + {layout_ps2_strlr_blocked, "The Bouncer STR blocked"}, + {layout_tra_blocked, "TRA blocked"}, + {layout_acm, "ACM blocked"}, + {layout_mus_acm, "multiple ACM files, ACM blocked"}, + {layout_aix, "AIX interleave, internally 18-byte interleaved"}, + {layout_aax, "AAX blocked, 18-byte interleaved"}, + {layout_scd_int, "SCD multistream interleave"}, +#ifdef VGM_USE_VORBIS + {layout_ogg_vorbis, "Ogg"}, +#endif +#ifdef VGM_USE_MPEG + {layout_fake_mpeg, "MPEG Audio stream with incorrect frame headers"}, + {layout_mpeg, "MPEG Audio stream"}, +#endif +}; + +static const meta_info meta_info_list[] = { + {meta_RSTM, "Nintendo RSTM header"}, + {meta_STRM, "Nintendo STRM header"}, + {meta_ADX_03, "CRI ADX header type 03"}, + {meta_ADX_04, "CRI ADX header type 04"}, + {meta_ADX_05, "CRI ADX header type 05"}, + {meta_AIX, "CRI AIX header"}, + {meta_AAX, "CRI AAX header"}, + {meta_UTF_DSP, "CRI ADPCM_WII header"}, + {meta_DSP_AGSC, "Retro Studios AGSC header"}, + {meta_DSP_CSMP, "Retro Studios CSMP header"}, + {meta_NGC_ADPDTK, "assumed Nintendo ADP by .adp extension and valid first frame"}, + {meta_RSF, "assumed Retro Studios RSF by .rsf extension and valid first bytes"}, + {meta_AFC, "Nintendo AFC header"}, + {meta_AST, "Nintendo AST header"}, + {meta_HALPST, "HAL Laboratory HALPST header"}, + {meta_DSP_RS03, "Retro Studios RS03 header"}, + {meta_DSP_STD, "Standard Nintendo DSP header"}, + {meta_DSP_CSTR, "Namco Cstr header"}, + {meta_GCSW, "GCSW header"}, + {meta_PS2_SShd, "SShd header"}, + {meta_PS2_NPSF, "Namco Production Sound File (NPSF) header"}, + {meta_RWSD, "Nintendo RWSD header (single stream)"}, + {meta_RWAR, "Nintendo RWAR header (single RWAV stream)"}, + {meta_RWAV, "Nintendo RWAV header"}, + {meta_CWAV, "Nintendo CWAV header"}, + {meta_FWAV, "Nintendo FWAV header"}, + {meta_PSX_XA, "RIFF/CDXA header"}, + {meta_PS2_RXW, "RXWS header)"}, + {meta_PS2_RAW, "assumed RAW Interleaved PCM by .int extension"}, + {meta_PS2_OMU, "Alter Echo OMU Header"}, + {meta_DSP_STM, "Nintendo STM header"}, + {meta_PS2_EXST, "EXST header"}, + {meta_PS2_SVAG, "Konami SVAG header"}, + {meta_PS2_MIB, "assumed MIB Interleaved file by .mib extension"}, + {meta_PS2_MIB_MIH, "assumed MIB with MIH Info Header file by .mib+.mih extension"}, + {meta_DSP_MPDSP, "Single DSP header stereo by .mpdsp extension"}, + {meta_PS2_MIC, "assume KOEI MIC file by .mic extension"}, + {meta_DSP_JETTERS, "Double DSP header stereo by _lr.dsp extension"}, + {meta_DSP_MSS, "Double DSP header stereo by .mss extension"}, + {meta_DSP_GCM, "Double DSP header stereo by .gcm extension"}, + {meta_DSP_WII_IDSP, "Wii IDSP Double DSP header"}, + {meta_RSTM_SPM, "Nintendo RSTM header and .brstmspm extension"}, + {meta_RAW, "assumed RAW PCM file by .raw extension"}, + {meta_PS2_VAGi, "Sony VAG Interleaved header (VAGi)"}, + {meta_PS2_VAGp, "Sony VAG Mono header (VAGp)"}, + {meta_PS2_VAGs, "Sony VAG Stereo header (VAGp)"}, + {meta_PS2_VAGm, "Sony VAG Mono header (VAGm)"}, + {meta_PS2_pGAV, "Sony VAG Stereo Little Endian header (pGAV)"}, + {meta_PSX_GMS, "assumed Grandia GMS file by .gms extension"}, + {meta_PS2_STR, "assumed STR + STH File by .str & .sth extension"}, + {meta_PS2_ILD, "ILD header"}, + {meta_PS2_PNB, "assumed PNB (PsychoNauts Bgm File) by .pnb extension"}, + {meta_XBOX_WAVM, "assumed Xbox WAVM file by .wavm extension"}, + {meta_XBOX_RIFF, "Xbox RIFF/WAVE file with 0x0069 Codec ID"}, + {meta_DSP_STR, "assumed Conan Gamecube STR File by .str extension"}, + {meta_EAXA_R2, "Electronic Arts XA R2"}, + {meta_EAXA_R3, "Electronic Arts XA R3"}, + {meta_EA_ADPCM, "Electronic Arts XA R1"}, + {meta_EA_IMA, "Electronic Arts container with IMA blocks"}, + {meta_EAXA_PSX, "Electronic Arts With PSX ADPCM"}, + {meta_EA_PCM, "Electronic Arts With PCM"}, + {meta_CFN, "Namco CAF Header"}, + {meta_PS2_VPK, "VPK Header"}, + {meta_GENH, "GENH Generic Header"}, + {meta_DSP_SADB, "sadb header"}, + {meta_SADL, "sadl header"}, + {meta_PS2_BMDX, "Beatmania .bmdx header"}, + {meta_DSP_WSI, ".wsi header"}, + {meta_AIFC, "Audio Interchange File Format AIFF-C"}, + {meta_AIFF, "Audio Interchange File Format"}, + {meta_STR_SNDS, ".str SNDS SHDR chunk"}, + {meta_WS_AUD, "Westwood Studios .aud header"}, + {meta_WS_AUD_old, "Westwood Studios .aud (old) header"}, + {meta_PS2_IVB, "IVB/BVII header"}, + {meta_PS2_SVS, "Square SVS header"}, + {meta_RIFF_WAVE, "RIFF WAVE header"}, + {meta_RIFF_WAVE_POS, "RIFF WAVE header and .pos for looping"}, + {meta_NWA, "Visual Art's NWA header"}, + {meta_NWA_NWAINFOINI, "Visual Art's NWA header and NWAINFO.INI for looping"}, + {meta_NWA_GAMEEXEINI, "Visual Art's NWA header and Gameexe.ini for looping"}, + {meta_XSS, "Dino Crisis 3 XSS File"}, + {meta_HGC1, "Knights of the Temple 2 hgC1 Header"}, + {meta_AUS, "Capcom AUS Header"}, + {meta_RWS, "RWS Header"}, + {meta_EACS_PC, "EACS Header (PC)"}, + {meta_EACS_PSX, "EACS Header (PSX)"}, + {meta_EACS_SAT, "EACS Header (SATURN)"}, + {meta_SL3, "SL3 Header"}, + {meta_FSB1, "FMOD Sample Bank (FSB1) Header"}, + {meta_FSB2, "FMOD Sample Bank (FSB2) Header"}, + {meta_FSB3, "FMOD Sample Bank (FSB3) Header"}, + {meta_FSB4, "FMOD Sample Bank (FSB4) Header"}, + {meta_FSB5, "FMOD Sample Bank (FSB5) Header"}, + {meta_RWX, "RWX Header"}, + {meta_XWB, "XWB WBND Header"}, + {meta_XA30, "XA30 Header"}, + {meta_MUSC, "MUSC Header"}, + {meta_MUSX_V004, "MUSX / Version 004 Header"}, + {meta_MUSX_V005, "MUSX / Version 005 Header"}, + {meta_MUSX_V006, "MUSX / Version 006 Header"}, + {meta_MUSX_V010, "MUSX / Version 010 Header"}, + {meta_MUSX_V201, "MUSX / Version 201 Header"}, + {meta_LEG, "Legaia 2 - Duel Saga LEG Header"}, + {meta_FILP, "Bio Hazard - Gun Survivor FILp Header"}, + {meta_IKM, "Zwei!! IKM Header"}, + {meta_SFS, "Baroque SFS Header"}, + {meta_DVI, "DVI Header"}, + {meta_KCEY, "KCEYCOMP Header"}, + {meta_BG00, "Falcom BG00 Header"}, + {meta_PS2_RSTM, "Rockstar Games RSTM Header"}, + {meta_ACM, "InterPlay ACM Header"}, + {meta_MUS_ACM, "MUS playlist and multiple InterPlay ACM Headered files"}, + {meta_PS2_KCES, "Konami KCES Header"}, + {meta_PS2_DXH, "Tokobot Plus DXH Header"}, + {meta_PS2_PSH, "Dawn of Mana - Seiken Densetsu 4 PSH Header"}, + {meta_RIFF_WAVE_labl, "RIFF WAVE header with loop markers"}, + {meta_RIFF_WAVE_smpl, "RIFF WAVE header with sample looping info"}, + {meta_RIFX_WAVE, "RIFX WAVE header"}, + {meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"}, + {meta_XNBm, "XNBm header"}, + {meta_PCM_SCD, "PCM file with custom header (SCD)"}, + {meta_PCM_PS2, "PCM file with custom header (PS2)"}, + {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"}, + {meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"}, + {meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"}, + {meta_PS2_TEC, "assumed TECMO badflagged stream by .tec extension"}, + {meta_XBOX_WVS, "Metal Arms WVS Header (XBOX)"}, + {meta_NGC_WVS, "Metal Arms WVS Header (GameCube)"}, + {meta_XBOX_STMA, "Midnight Club 2 STMA Header"}, + {meta_XBOX_MATX, "assumed Matrix file by .matx extension"}, + {meta_DE2, "gurumin .de2 with embedded funky RIFF"}, + {meta_VS, "Men in Black VS Header"}, + {meta_DC_STR, "Sega Stream Asset Builder header"}, + {meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"}, + {meta_XBOX_XMU, "XMU header"}, + {meta_XBOX_XVAS, "assumed TMNT file by .xvas extension"}, + {meta_PS2_XA2, "Acclaim XA2 Header"}, + {meta_DC_IDVI, "IDVI Header"}, + {meta_NGC_YMF, "YMF DSP Header"}, + {meta_PS2_CCC, "CCC Header"}, + {meta_PSX_FAG, "FAG Header"}, + {meta_PS2_MIHB, "Merged MIH+MIB"}, + {meta_DSP_WII_MUS, "mus header"}, + {meta_WII_SNG, "SNG DSP Header"}, + {meta_RSD2VAG, "RSD2/VAG Header"}, + {meta_RSD2PCMB, "RSD2/PCMB Header"}, + {meta_RSD2XADP, "RSD2/XADP Header"}, + {meta_RSD3VAG, "RSD3/VAG Header"}, + {meta_RSD3GADP, "RSD3/GADP Header"}, + {meta_RSD3PCM, "RSD3/PCM Header"}, + {meta_RSD3PCMB, "RSD3/PCMB Header"}, + {meta_RSD4PCMB, "RSD4/PCMB Header"}, + {meta_RSD4PCM, "RSD4/PCM Header"}, + {meta_RSD4RADP, "RSD4/RADP Header"}, + {meta_RSD4VAG, "RSD4/VAG Header"}, + {meta_RSD6XADP, "RSD6/XADP Header"}, + {meta_RSD6VAG, "RSD6/VAG Header"}, + {meta_RSD6WADP, "RSD6/WADP Header"}, + {meta_RSD6RADP, "RSD6/RADP Header"}, + {meta_DC_ASD, "ASD Header"}, + {meta_NAOMI_SPSD, "SPSD Header"}, + {meta_FFXI_BGW, "BGW BGMStream header"}, + {meta_FFXI_SPW, "SPW SeWave header"}, + {meta_PS2_ASS, "ASS Header"}, + {meta_IDSP, "IDSP Header"}, + {meta_WAA_WAC_WAD_WAM, "WAA/WAC/WAD/WAM RIFF Header"}, + {meta_PS2_SEG, "SEG (PS2) Header"}, + {meta_XBOX_SEG, "SEG (XBOX) Header"}, + {meta_NDS_STRM_FFTA2, "Final Fantasy Tactics A2 RIFF Header"}, + {meta_STR_ASR, "Donkey Kong Jet Race KNON/WII Header"}, + {meta_ZWDSP, "Zack and Wiki custom DSP Header"}, + {meta_GCA, "GCA DSP Header"}, + {meta_SPT_SPD, "SPT+SPD DSP Header"}, + {meta_ISH_ISD, "ISH+ISD DSP Header"}, + {meta_GSP_GSB, "Tecmo GSP+GSB Header"}, + {meta_YDSP, "Yuke's DSP (YDSP) Header"}, + {meta_MSVP, "MSVP Header"}, + {meta_NGC_SSM, "SSM DSP Header"}, + {meta_PS2_JOE, "Disney/Pixar JOE Header"}, + {meta_VGS, "Guitar Hero Encore Rocks the 80's Header"}, + {meta_DC_DCSW_DCS, "Evil Twin DCS file with helper"}, + {meta_WII_SMP, "SMP DSP Header"}, + {meta_EMFF_PS2, "Eidos Music File Format Header"}, + {meta_EMFF_NGC, "Eidos Music File Format Header"}, + {meta_THP, "THP Movie File Format Header"}, + {meta_STS_WII, "Shikigami no Shiro (WII) Header"}, + {meta_PS2_P2BT, "Pop'n'Music 7 Header"}, + {meta_PS2_GBTS, "Pop'n'Music 9 Header"}, + {meta_NGC_DSP_IADP, "IADP Header"}, + {meta_RSTM_shrunken, "Nintendo RSTM header, corrupted by Atlus"}, + {meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"}, + {meta_RIFF_WAVE_SNS, "RIFF WAVE header with .sns flavoring"}, + {meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"}, + {meta_SAT_BAKA, "BAKA header from Crypt Killer"}, + {meta_NDS_SWAV, "SWAV Header"}, + {meta_PS2_VSF, "Musashi: Samurai Legend VSF Header"}, + {meta_NDS_RRDS, "Ridger Racer DS Header"}, + {meta_PS2_TK5, "Tekken 5 Stream Header"}, + {meta_PS2_SND, "Might and Magic SSND Header"}, + {meta_PS2_VSF_TTA, "VSF with SMSS Header"}, + {meta_ADS, "dhSS Header"}, + {meta_WII_STR, "HOTD Overkill - STR+STH WII Header"}, + {meta_PS2_MCG, "Gunvari MCG Header"}, + {meta_ZSD, "ZSD Header"}, + {meta_RedSpark, "RedSpark Header"}, + {meta_PC_IVAUD, "assumed GTA IV Audio file by .ivaud extension"}, + {meta_DSP_WII_WSD, "Standard Nintendo DSP headers in .wsd"}, + {meta_WII_NDP, "Vertigo NDP Header"}, + {meta_PS2_SPS, "Ape Escape 2 SPS Header"}, + {meta_PS2_XA2_RRP, "Acclaim XA2 Header"}, + {meta_NDS_HWAS, "NDS 'HWAS' Header"}, + {meta_NGC_LPS, "Rave Master LPS Header"}, + {meta_NAOMI_ADPCM, "NAOMI/NAOMI2 Arcade games ADPCM header"}, + {meta_SD9, "beatmania IIDX SD9 header"}, + {meta_2DX9, "beatmania IIDX 2DX9 header"}, + {meta_DSP_YGO, "Konami custom DSP Header"}, + {meta_PS2_VGV, "Rune: Viking Warlord VGV Header"}, + {meta_NGC_GCUB, "GCub Header"}, + {meta_NGC_SCK_DSP, "The Scorpion King SCK Header"}, + {meta_NGC_SWD, "PSF + Standard DSP Headers"}, + {meta_CAFF, "Apple Core Audio Format Header"}, + {meta_PC_MXST, "Lego Island MxSt Header"}, + {meta_PC_SOB_SAB, "Worms 4: Mayhem SOB/SAB Header"}, + {meta_MAXIS_XA, "Maxis XAI/XAJ Header"}, + {meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"}, + {meta_WII_BNS, "Nintendo BNS header"}, + {meta_WII_WAS, "WAS (iSWS) DSP header"}, + {meta_XBOX_HLWAV, "Half Life 2 bgm header"}, + {meta_STX, "Nintendo .stx header"}, + {meta_PS2_STM, "Red Dead Revolver .stm (.ps2stm)"}, + {meta_MYSPD, "U-Sing .myspd header"}, + {meta_HIS, "Her Interactive Sound header"}, + {meta_PS2_AST, "KOEI AST header"}, + {meta_CAPDSP, "Capcom custom DSP header"}, + {meta_DMSG, "RIFF/DMSGsegh header"}, + {meta_PONA_3DO, "Policenauts BGM header"}, + {meta_PONA_PSX, "Policenauts BGM header"}, + {meta_NGC_DSP_AAAP, "Double standard dsp header in 'AAAp'"}, + {meta_NGC_DSP_KONAMI, "Konami dsp header"}, + {meta_PS2_STER, "STER Header"}, + {meta_BNSF, "Namco Bandai BNSF header"}, + {meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"}, + {meta_S14, "assumed Polycom Siren 14 by .s14 extension"}, + {meta_SSS, "assumed Polycom Siren 14 by .sss extension"}, + {meta_PS2_GCM, "GCM 'MCG' Header"}, + {meta_PS2_SMPL, "Homura 'SMPL' Header"}, + {meta_PS2_MSA, "Psyvariar -Complete Edition- MSA header"}, + {meta_PC_SMP, "Ghostbusters .smp Header"}, + {meta_NGC_PDT, "PDT DSP header"}, + {meta_NGC_BO2, "Blood Omen 2 DSP header"}, + {meta_P3D, "Prototype P3D Header"}, + {meta_PS2_TK1, "Tekken TK5STRM1 Header"}, + {meta_PS2_ADSC, "ADSC Header"}, + {meta_NGC_DSP_MPDS, "MPDS DSP header"}, + {meta_DSP_STR_IG, "Infogrames dual dsp header"}, + {meta_PSX_MGAV, "Electronic Arts RVWS header"}, + {meta_PS2_B1S, "B1S header"}, + {meta_PS2_WAD, "WAD header"}, + {meta_DSP_XIII, "XIII dsp header"}, + {meta_NGC_DSP_STH_STR, "STH dsp header"}, + {meta_DSP_CABELAS, "Cabelas games dsp header"}, + {meta_PS2_LPCM, "LPCM header"}, + {meta_PS2_VMS, "VMS Header"}, + {meta_PS2_XAU, "XAU Header"}, + {meta_GH3_BAR, "Guitar Hero III Mobile .bar"}, + {meta_FFW, "Freedom Fighters BGM header"}, + {meta_DSP_DSPW, "DSPW dsp header"}, + {meta_PS2_JSTM, "JSTM Header"}, + {meta_PS3_XVAG, "XVAG Header"}, + {meta_PS3_CPS, "CPS Header"}, + {meta_SQEX_SCD, "Square-Enix SCD"}, + {meta_NGC_NST_DSP, "Animaniacs NST header"}, + {meta_BAF, ".baf WAVE header"}, + {meta_PS3_MSF, "PS3 MSF header"}, + {meta_NUB_VAG, "VAG (NUB) header"}, + {meta_PS3_PAST, "SNDP header"}, + {meta_PS3_SGDX, "SGXD header"}, + {meta_NGCA, "NGCA header"}, + {meta_WII_RAS, "RAS header"}, + {meta_PS2_SPM, "SPM header"}, + {meta_X360_TRA, "assumed DefJam Rapstar Audio File by .tra extension"}, + {meta_PS2_VGS, "Princess Soft VGS header"}, + {meta_PS2_IAB, "IAB header"}, + {meta_PS2_STRLR, "STR L/R header"}, + {meta_LSF_N1NJ4N, ".lsf !n1nj4n header"}, + {meta_VAWX, "feelplus VAWX header"}, + {meta_PC_SNDS, "assumed Heavy Iron IMA by .snds extension"}, + {meta_PS2_WMUS, "assumed The Warriors Sony ADPCM by .wmus extension"}, + {meta_HYPERSCAN_KVAG, "Mattel Hyperscan KVAG"}, + {meta_IOS_PSND, "PSND Header"}, + {meta_BOS_ADP, "ADP! header"}, + {meta_EB_SFX, "Excitebots .sfx header"}, + {meta_EB_SF0, "assumed Excitebots .sf0 by extension"}, + {meta_PS3_KLBS, "klBS Header"}, + {meta_PS2_MTAF, "Konami MTAF header"}, + {meta_PS2_VAG1, "Konami VAG Mono header (VAG1)"}, + {meta_PS2_VAG2, "Konami VAG Stereo header (VAG2)"}, + {meta_TUN, "TUN 'ALP' header"}, + {meta_WPD, "WPD 'DPW' header"}, + {meta_MN_STR, "Mini Ninjas 'STR' header"}, + {meta_PS2_MSS, "Guerilla MSCC header"}, + {meta_PS2_HSF, "Lowrider 'HSF' header"}, + {meta_PS3_IVAG, "PS3 'IVAG' Header"}, + {meta_PS2_2PFS, "PS2 '2PFS' Header"}, + {meta_RSD6OOGV, "RSD6/OOGV Header"}, + {meta_UBI_CKD, "CKD 'RIFF' Header"}, + {meta_PS2_VBK, "PS2 VBK Header"}, + {meta_OTM, "Otomedius OTM Header"}, + {meta_CSTM, "Nintendo 3DS CSTM Header"}, + {meta_FSTM, "Nintendo Wii U FSTM Header"}, + {meta_KT_WIIBGM, "Koei Tecmo WiiBGM Header"}, + {meta_3DS_IDSP, "Nintendo IDSP Header"}, + {meta_WIIU_BTSND, "Wii U Menu Boot Sound"}, + {meta_MCA, "Capcom MCA Header"}, + {meta_XB3D_ADX, "Xenoblade 3D ADX Header"}, + {meta_HCA, "CRI MiddleWare HCA Header"}, + {meta_PS2_SVAG_SNK, "SNK SVAG header"}, + {meta_PS2_VDS_VDM, "Graffiti Kingdom VDS/VDM Header"}, + {meta_X360_CXS, "CXS Header"}, +#ifdef VGM_USE_VORBIS + {meta_OGG_VORBIS, "Ogg Vorbis"}, + {meta_OGG_SLI, "Ogg Vorbis with .sli (start,length) for looping"}, + {meta_OGG_SLI2, "Ogg Vorbis with .sli (from,to) for looping"}, + {meta_OGG_SFL, "Ogg Vorbis with SFPL for looping"}, + {meta_OGG_UM3, "Ogg Vorbis, Ultramarine3 'encryption'"}, + {meta_OGG_KOVS, "Ogg Vorbis, KOVS header"}, + {meta_OGG_PSYCH, "Ogg Vorbis, Psychic Software obfuscation"}, + #endif +#ifdef VGM_USE_MPEG + {meta_AHX, "CRI AHX header"}, +#endif +#ifdef VGM_USE_MP4V2 + {meta_MP4, "AAC header"}, +#endif +#ifdef VGM_USE_FFMPEG + {meta_FFmpeg, "FFmpeg supported file format"}, +#endif +}; + + +const char * get_vgmstream_coding_description(coding_t coding_type) { + int i, list_length; + + list_length = sizeof(coding_info_list) / sizeof(coding_info); + for (i=0; i < list_length; i++) { + if (coding_info_list[i].type == coding_type) + return coding_info_list[i].description; + } + + return NULL; +} +const char * get_vgmstream_layout_description(layout_t layout_type) { + int i, list_length; + + list_length = sizeof(layout_info_list) / sizeof(layout_info); + for (i=0; i < list_length; i++) { + if (layout_info_list[i].type == layout_type) + return layout_info_list[i].description; + } + + return NULL; +} +const char * get_vgmstream_meta_description(meta_t meta_type) { + int i, list_length; + + list_length = sizeof(meta_info_list) / sizeof(meta_info); + for (i=0; i < list_length; i++) { + if (meta_info_list[i].type == meta_type) + return meta_info_list[i].description; + } + + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/formats.h b/Frameworks/vgmstream/vgmstream/src/formats.h new file mode 100644 index 000000000..2fe6d910e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/formats.h @@ -0,0 +1,19 @@ +/* + * formats.h - utils to parse supported formats + */ +#ifndef _FORMATS_H_ +#define _FORMATS_H_ + +#include "vgmstream.h" + +/* rough number of chars counting all extensions (actually <1500 and extra space) */ +#define VGM_EXTENSION_LIST_CHAR_SIZE 2000 + +const char ** vgmstream_get_formats(); +int vgmstream_get_formats_length(); + +const char * get_vgmstream_coding_description(coding_t coding_type); +const char * get_vgmstream_layout_description(layout_t layout_type); +const char * get_vgmstream_meta_description(meta_t meta_type); + +#endif /* _FORMATS_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/layout/gsb_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/gsb_blocked.c index 80ce3eef1..eccd40d8d 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/gsb_blocked.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/gsb_blocked.c @@ -4,15 +4,25 @@ /* set up for the block at the given offset */ void gsb_block_update(off_t block_offset, VGMSTREAM * vgmstream) { int i; + int block_header_size = 0x20; /*from header*/ + int block_channel_size = 0x8000; /*from header, per channel*/ vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = 0x10000; /*read_32bitLE( - vgmstream->current_block_offset+0x10, - vgmstream->ch[0].streamfile); */ - vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x20; - vgmstream->current_block_size/=vgmstream->channels; + vgmstream->current_block_size = block_channel_size; + vgmstream->next_block_offset = vgmstream->current_block_offset + + block_header_size + + block_channel_size * vgmstream->channels; for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(vgmstream->current_block_size*i); + int interleave; + int filesize = vgmstream->ch[i].streamfile->get_size(vgmstream->ch[i].streamfile); + if (vgmstream->next_block_offset > filesize) + interleave = (filesize - vgmstream->current_block_offset - block_header_size) / vgmstream->channels; + else + interleave = block_channel_size; + + vgmstream->ch[i].offset = vgmstream->current_block_offset + + block_header_size + + (interleave*i); } } diff --git a/Frameworks/vgmstream/vgmstream/src/layout/layout.h b/Frameworks/vgmstream/vgmstream/src/layout/layout.h index 599e93538..4cb1df782 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/layout.h +++ b/Frameworks/vgmstream/vgmstream/src/layout/layout.h @@ -4,6 +4,7 @@ #include "../streamtypes.h" #include "../vgmstream.h" +/* blocked layouts */ void ast_block_update(off_t block_ofset, VGMSTREAM * vgmstream); void mxch_block_update(off_t block_ofset, VGMSTREAM * vgmstream); @@ -46,6 +47,19 @@ void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream); void ivaud_block_update(off_t block_offset, VGMSTREAM * vgmstream); +void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void dsp_bdsp_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void tra_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ps2_iab_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ps2_strlr_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +/* other layouts */ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); @@ -60,20 +74,4 @@ void render_vgmstream_aax(sample * buffer, int32_t sample_count, VGMSTREAM * vgm void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); -void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void dsp_bdsp_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void tra_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void mtaf_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void ps2_iab_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void ps2_strlr_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -void ps2_mtaf_block_update(off_t block_ofset, VGMSTREAM * vgmstream); - #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/2dx.c b/Frameworks/vgmstream/vgmstream/src/meta/2dx.c index ebe39903a..3993fa39b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/2dx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/2dx.c @@ -41,7 +41,7 @@ VGMSTREAM * init_vgmstream_2dx(STREAMFILE *streamFile) { vgmstream->num_samples = read_32bitLE(0x66,streamFile); vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = read_16bitLE(0x38,streamFile); - vgmstream->meta_type = meta_2DX; + vgmstream->meta_type = meta_2DX9; /* open the file for reading */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c index 917f2a9df..418694979 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c @@ -273,12 +273,6 @@ VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile) { for (i=0;i<16;i++) vgmstream->ch[1].adpcm_coef[i]=read_16bitBE(0x9c+i*2,streamFile); } -#ifdef DEBUG - vgmstream->ch[0].loop_history1 = read_16bitBE(0x66,streamFile); - vgmstream->ch[0].loop_history2 = read_16bitBE(0x68,streamFile); - vgmstream->ch[1].loop_history1 = read_16bitBE(0xc6,streamFile); - vgmstream->ch[1].loop_history2 = read_16bitBE(0xc8,streamFile); -#endif /* open the file for reading by each channel */ { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/baf.c b/Frameworks/vgmstream/vgmstream/src/meta/baf.c index cbd573156..dff1503fc 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/baf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/baf.c @@ -1,36 +1,41 @@ #include "meta.h" -#include "../util.h" /* .BAF - Bizarre Creations (Blur, James Bond 007: Blood Stone, etc) */ - VGMSTREAM * init_vgmstream_baf(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t WAVE_size,DATA_size; + off_t WAVE_size, DATA_size; off_t start_offset; long sample_count; + int sample_rate; const int frame_size = 33; - const int frame_samples = 64; + const int frame_samples = (frame_size-1) * 2; int channels; int loop_flag = 0; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("baf",filename_extension(filename))) goto fail; + /* check extensions */ + if ( !check_extensions(streamFile, "baf") ) + goto fail; /* check WAVE */ - if (read_32bitBE(0,streamFile) != 0x57415645) goto fail; + if (read_32bitBE(0,streamFile) != 0x57415645) /* "WAVE" */ + goto fail; WAVE_size = read_32bitBE(4,streamFile); - if (WAVE_size != 0x4c) goto fail; + if (WAVE_size != 0x4c) /* && WAVE_size != 0x50*/ + goto fail; /* check for DATA after WAVE */ - if (read_32bitBE(WAVE_size,streamFile) != 0x44415441) goto fail; + if (read_32bitBE(WAVE_size,streamFile) != 0x44415441) /* "DATA"*/ + goto fail; /* check that WAVE size is data size */ DATA_size = read_32bitBE(0x30,streamFile); if (read_32bitBE(WAVE_size+4,streamFile)-8 != DATA_size) goto fail; + /*if (WAVE_size == 0x50) sample_count = DATA_size * frame_samples / frame_size / channels;*/ sample_count = read_32bitBE(0x44,streamFile); + /*if (WAVE_size == 0x50) sample_rate = read_32bitBE(0x3c,streamFile);*/ + sample_rate = read_32bitBE(0x40,streamFile); + /* unsure how to detect channel count, so use a hack */ channels = (long long)DATA_size / frame_size * frame_samples / sample_count; @@ -40,33 +45,22 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *streamFile) { /* fill in the vital statistics */ start_offset = WAVE_size + 8; - vgmstream->sample_rate = read_32bitBE(0x40,streamFile); + vgmstream->sample_rate = sample_rate; vgmstream->num_samples = sample_count; - vgmstream->coding_type = coding_BAF_ADPCM; + vgmstream->coding_type = coding_PSX_cfg; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = frame_size; vgmstream->meta_type = meta_BAF; - /* open the file for reading by each channel */ - { - int i; - STREAMFILE *file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+vgmstream->interleave_block_size*i; - - } - } + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c b/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c index e210682b2..54307f73d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c @@ -7,13 +7,14 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { coding_t coding_type; - off_t head_offset; - off_t seek_offset; + off_t info_offset = 0, seek_offset = 0, data_offset = 0; + uint16_t temp_id; int codec_number; int channel_count; int loop_flag; - int ima = 0; + int i, ima = 0; off_t start_offset; + int section_count; /* check extension, case insensitive */ streamFile->get_name(streamFile, filename, sizeof(filename)); @@ -24,24 +25,46 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { /* check header */ if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */ goto fail; - if ((uint32_t)read_32bitBE(4, streamFile) != 0xFFFE4000) + if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF) goto fail; + section_count = read_16bitLE(0x10, streamFile); + for (i = 0; i < section_count; i++) { + temp_id = read_16bitLE(0x14 + i * 0xc, streamFile); + switch(temp_id) { + case 0x4000: + info_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + /* size_t info_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4001: + seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + /* size_t seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4002: + data_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + /* size_t data_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4003: + /* off_t regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */ + /* size_t regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4004: + /* off_t pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */ + /* size_t pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); */ + break; + default: + break; + } + } - - /* get head offset, check */ - head_offset = read_32bitLE(0x18, streamFile); - if ((uint32_t)read_32bitBE(head_offset, streamFile) != 0x494E464F) /* "INFO" */ - goto fail; - - seek_offset = read_32bitLE(0x24, streamFile); /* check type details */ - codec_number = read_8bit(head_offset + 0x20, streamFile); - loop_flag = read_8bit(head_offset + 0x21, streamFile); - channel_count = read_8bit(head_offset + 0x22, streamFile); + if (info_offset == 0) goto fail; + codec_number = read_8bit(info_offset + 0x20, streamFile); + loop_flag = read_8bit(info_offset + 0x21, streamFile); + channel_count = read_8bit(info_offset + 0x22, streamFile); switch (codec_number) { case 0: @@ -51,6 +74,7 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { coding_type = coding_PCM16LE; break; case 2: + if (seek_offset == 0) goto fail; if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */ ima = 1; coding_type = coding_INT_IMA; @@ -70,12 +94,12 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { if (!vgmstream) goto fail; /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitLE(head_offset + 0x2c, streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitLE(head_offset + 0x24, streamFile); + vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitLE(info_offset + 0x24, streamFile); /* channels and loop flag are set by allocate_vgmstream */ if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting { - vgmstream->loop_start_sample = read_32bitLE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); if (vgmstream->loop_start_sample > 10000) { vgmstream->loop_start_sample -= 5000; @@ -86,7 +110,7 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { } else { - vgmstream->loop_start_sample = read_32bitLE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); vgmstream->loop_end_sample = vgmstream->num_samples; } @@ -105,13 +129,13 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { if (ima) vgmstream->interleave_block_size = 0x200; else { - vgmstream->interleave_block_size = read_32bitLE(head_offset + 0x34, streamFile); - vgmstream->interleave_smallblock_size = read_32bitLE(head_offset + 0x44, streamFile); + vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile); + vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile); } if (vgmstream->coding_type == coding_NGC_DSP) { off_t coef_offset; - off_t tempoffset = head_offset; + off_t tempoffset = info_offset; int foundcoef = 0; int i, j; int coef_spacing = 0x2E; @@ -120,7 +144,7 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { { if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102) { - coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - head_offset; + coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset; foundcoef++; break; } @@ -129,17 +153,18 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { for (j = 0; jchannels; j++) { for (i = 0; i<16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(head_offset + coef_offset + j*coef_spacing + i * 2, streamFile); + vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(info_offset + coef_offset + j*coef_spacing + i * 2, streamFile); } } } - if (ima) // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. + if (ima) { // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. + if (seek_offset == 0) goto fail; start_offset = seek_offset; - else if (vgmstream->coding_type == coding_NGC_DSP) - start_offset = read_32bitLE(0x30, streamFile) + 0x20; - else // No SEEK header and not IMA, so just start after the DATA header - start_offset = 0x120; + } else { + if (data_offset == 0) goto fail; + start_offset = data_offset + 0x20; + } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bfstm.c b/Frameworks/vgmstream/vgmstream/src/meta/bfstm.c index d3094d4dd..449abea81 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bfstm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bfstm.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../util.h" +#include "../stack_alloc.h" VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; @@ -7,16 +8,16 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { coding_t coding_type; - off_t head_offset; - off_t seek_offset; - off_t data_offset; + off_t info_offset = 0, seek_offset = 0, data_offset = 0; + uint16_t temp_id; int codec_number; int channel_count; int loop_flag; + int i, j; int ima = 0; off_t start_offset; - int founddata; off_t tempoffset1; + int section_count; /* check extension, case insensitive */ streamFile->get_name(streamFile, filename, sizeof(filename)); @@ -30,33 +31,45 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { if ((uint16_t)read_16bitBE(4, streamFile) != 0xFEFF) goto fail; - founddata = 0; - tempoffset1 = 0x8; - - while (!(founddata)) - { - if ((uint32_t)read_32bitBE(tempoffset1, streamFile) == 0x40020000) - { - data_offset = read_32bitBE(tempoffset1 + 4, streamFile); - founddata++; - break; + section_count = read_16bitBE(0x10, streamFile); + for (i = 0; i < section_count; i++) { + temp_id = read_16bitBE(0x14 + i * 0xc, streamFile); + switch(temp_id) { + case 0x4000: + info_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + /* size_t info_size = read_32bitBE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4001: + seek_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + /* size_t seek_size = read_32bitBE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4002: + data_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + /* size_t data_size = read_32bitBE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4003: + /* off_t regn_offset = read_32bitBE(0x18 + i * 0xc, streamFile); */ + /* size_t regn_size = read_32bitBE(0x1c + i * 0xc, streamFile); */ + break; + case 0x4004: + /* off_t pdat_offset = read_32bitBE(0x18 + i * 0xc, streamFile); */ + /* size_t pdat_size = read_32bitBE(0x1c + i * 0xc, streamFile); */ + break; + default: + break; } - tempoffset1++; } - /* get head offset, check */ - head_offset = read_32bitBE(0x18, streamFile); - if ((uint32_t)read_32bitBE(head_offset, streamFile) != 0x494E464F) /* "INFO" */ + if (info_offset == 0) goto fail; + if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */ goto fail; - seek_offset = read_32bitBE(0x24, streamFile); - /* check type details */ - codec_number = read_8bit(head_offset + 0x20, streamFile); - loop_flag = read_8bit(head_offset + 0x21, streamFile); - channel_count = read_8bit(head_offset + 0x22, streamFile); + codec_number = read_8bit(info_offset + 0x20, streamFile); + loop_flag = read_8bit(info_offset + 0x21, streamFile); + channel_count = read_8bit(info_offset + 0x22, streamFile); switch (codec_number) { case 0: @@ -80,12 +93,12 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { if (!vgmstream) goto fail; /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitBE(head_offset + 0x2c, streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitBE(head_offset + 0x26, streamFile); + vgmstream->num_samples = read_32bitBE(info_offset + 0x2c, streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(info_offset + 0x26, streamFile); /* channels and loop flag are set by allocate_vgmstream */ if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting { - vgmstream->loop_start_sample = read_32bitBE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitBE(info_offset + 0x28, streamFile); if (vgmstream->loop_start_sample > 10000) { vgmstream->loop_start_sample -= 5000; @@ -96,7 +109,7 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { } else { - vgmstream->loop_start_sample = read_32bitBE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitBE(info_offset + 0x28, streamFile); vgmstream->loop_end_sample = vgmstream->num_samples; } @@ -115,41 +128,36 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { if (ima) vgmstream->interleave_block_size = 0x200; else { - vgmstream->interleave_block_size = read_32bitBE(head_offset + 0x34, streamFile); - vgmstream->interleave_smallblock_size = read_32bitBE(head_offset + 0x44, streamFile); + vgmstream->interleave_block_size = read_32bitBE(info_offset + 0x34, streamFile); + vgmstream->interleave_smallblock_size = read_32bitBE(info_offset + 0x44, streamFile); } if (vgmstream->coding_type == coding_NGC_DSP) { - off_t coef_offset; - off_t tempoffset2 = head_offset; - int foundcoef = 0; - int i, j; - int coef_spacing = 0x2E; - - while (!(foundcoef)) - { - if ((uint32_t)read_32bitBE(tempoffset2, streamFile) == 0x41020000) - { - coef_offset = read_32bitBE(tempoffset2 + 4, streamFile) + tempoffset2 + (channel_count * 8) - 4 - head_offset; - foundcoef++; - break; - } - tempoffset2++; - } - + off_t coeff_ptr_table; + VARDECL(off_t, coef_offset); + ALLOC(coef_offset, channel_count, off_t); + coeff_ptr_table = read_32bitBE(info_offset + 0x1c, streamFile) + info_offset + 8; // Getting pointer for coefficient pointer table + + for (i = 0; i < channel_count; i++) { + tempoffset1 = read_32bitBE(coeff_ptr_table + 8 + i * 8, streamFile); + coef_offset[i] = tempoffset1 + coeff_ptr_table; + coef_offset[i] += read_32bitBE(coef_offset[i] + 4, streamFile); + } + for (j = 0; jchannels; j++) { for (i = 0; i<16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(head_offset + coef_offset + j*coef_spacing + i * 2, streamFile); + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_offset[j] + i * 2, streamFile); } } } - if (ima) // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. + if (ima) { // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. + if (seek_offset == 0) goto fail; start_offset = seek_offset; - else if (vgmstream->coding_type == coding_NGC_DSP) + } else { + if (data_offset == 0) goto fail; start_offset = data_offset + 0x20; - else // No SEEK header and not IMA, so just start after the DATA header - start_offset = 0x120; + } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c b/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c index 12f0eec4f..a02f09e2a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c @@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_bfwav(STREAMFILE *streamFile) { coding_t coding_type; - int ima = 0; + /*int ima = 0;*/ int nsmbu_flag = 0; int32_t(*read_32bit)(off_t, STREAMFILE*) = read_32bitBE; int16_t(*read_16bit)(off_t, STREAMFILE*) = read_16bitBE; @@ -149,4 +149,4 @@ VGMSTREAM * init_vgmstream_bfwav(STREAMFILE *streamFile) { fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; -} \ No newline at end of file +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bgw.c b/Frameworks/vgmstream/vgmstream/src/meta/bgw.c index 841d95d63..12830685e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bgw.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bgw.c @@ -1,140 +1,172 @@ #include "meta.h" -#include "../util.h" -/* BGW (FF XI) */ +/* BGW - from Final Fantasy XI (PC) music files + * Some info from POLUtils */ VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; + uint32_t codec, filesize, blocksize, sample_rate; int32_t loop_start; + uint8_t block_align; + off_t start_offset; - int loop_flag = 0; - int channel_count; + int channel_count, loop_flag = 0; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("bgw",filename_extension(filename))) goto fail; - - /* "BGMStream" */ - if (read_32bitBE(0,streamFile) != 0x42474d53 || - read_32bitBE(4,streamFile) != 0x74726561 || - read_32bitBE(8,streamFile) != 0x6d000000 || - read_32bitBE(12,streamFile) != 0) goto fail; - - /* check file size with header value */ - if (read_32bitLE(0x10,streamFile) != get_streamfile_size(streamFile)) + /* check extensions */ + if ( !check_extensions(streamFile, "bgw") ) goto fail; - channel_count = read_8bit(0x2e,streamFile); + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x42474d53 || /* "BGMS" */ + read_32bitBE(0x04,streamFile) != 0x74726561 || /* "trea" */ + read_32bitBE(0x08,streamFile) != 0x6d000000 ) /* "m\0\0\0" */ + goto fail; + + codec = read_32bitLE(0x0c,streamFile); + filesize = read_32bitLE(0x10,streamFile); + /*file_id = read_32bitLE(0x14,streamFile);*/ + blocksize = read_32bitLE(0x18,streamFile); loop_start = read_32bitLE(0x1c,streamFile); + sample_rate = (read_32bitLE(0x20,streamFile) + read_32bitLE(0x24,streamFile)) & 0xFFFFFFFF; /* bizarrely obfuscated sample rate */ + start_offset = read_32bitLE(0x28,streamFile); + /*0x2c: unk (vol?) */ + /*0x2d: unk (0x10?) */ + channel_count = read_8bit(0x2e,streamFile); + block_align = read_8bit(0x2f,streamFile); + + + /* check file size with header value */ + if (filesize != get_streamfile_size(streamFile)) + goto fail; + loop_flag = (loop_start > 0); - + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ - start_offset = read_32bitLE(0x28,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_FFXI; - vgmstream->num_samples = read_32bitLE(0x18,streamFile)*16; - if (loop_flag) { - vgmstream->loop_start_sample = (loop_start-1)*16; - vgmstream->loop_end_sample = vgmstream->num_samples; + vgmstream->meta_type = meta_FFXI_BGW; + vgmstream->sample_rate = sample_rate; + + switch (codec) { + case 0: /* PS ADPCM */ + vgmstream->coding_type = coding_PSX_cfg; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */ + + vgmstream->num_samples = blocksize * block_align; + if (loop_flag) { + vgmstream->loop_start_sample = (loop_start-1) * block_align; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + break; + + case 3: /* ATRAC3 (encrypted) */ + default: + goto fail; } - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 9; - vgmstream->meta_type = meta_FFXI_BGW; /* 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;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+i*9; - - } - } + 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; } -/* .spw (SEWave, PlayOnline viewer for FFXI), very similar to bgw */ +/* SPW (SEWave) - from PlayOnline viewer for Final Fantasy XI (PC) */ VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + uint32_t codec, filesize, blocksize, sample_rate; + int32_t loop_start; + uint8_t block_align; off_t start_offset; - int loop_flag = 0; - int32_t loop_start; - int channel_count; + int channel_count, loop_flag = 0; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("spw",filename_extension(filename))) goto fail; + /* check extensions */ + if ( !check_extensions(streamFile, "spw") ) + goto fail; - /* "SeWave" */ - if (read_32bitBE(0,streamFile) != 0x53655761 || - read_32bitBE(4,streamFile) != 0x76650000) goto fail; + /* check header */ + if (read_32bitBE(0,streamFile) != 0x53655761 || /* "SeWa" */ + read_32bitBE(4,streamFile) != 0x76650000) /* "ve\0\0" */ + goto fail; /* check file size with header value */ if (read_32bitLE(0x8,streamFile) != get_streamfile_size(streamFile)) goto fail; - channel_count = read_8bit(0x2a,streamFile); + filesize = read_32bitLE(0x08,streamFile); + codec = read_32bitLE(0x0c,streamFile); + /*file_id = read_32bitLE(0x10,streamFile);*/ + blocksize = read_32bitLE(0x14,streamFile); loop_start = read_32bitLE(0x18,streamFile); + sample_rate = (read_32bitLE(0x1c,streamFile) + read_32bitLE(0x20,streamFile)) & 0xFFFFFFFF; /* bizarrely obfuscated sample rate */ + start_offset = read_32bitLE(0x24,streamFile); + /*0x2c: unk (0x00?) */ + /*0x2d: unk (0x00/01?) */ + channel_count = read_8bit(0x2a,streamFile); + block_align = read_8bit(0x2b,streamFile); + /*0x2c: unk (0x01 when PCM, 0x10 when VAG?) */ + + /* check file size with header value */ + if (filesize != get_streamfile_size(streamFile)) + goto fail; + loop_flag = (loop_start > 0); - + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; /* fill in the vital statistics */ - start_offset = read_32bitLE(0x24,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_FFXI; - vgmstream->num_samples = read_32bitLE(0x14,streamFile)*16; - if (loop_flag) { - vgmstream->loop_start_sample = (loop_start-1)*16; - vgmstream->loop_end_sample = vgmstream->num_samples; + vgmstream->meta_type = meta_FFXI_SPW; + vgmstream->sample_rate = sample_rate; + + switch (codec) { + case 0: /* PS ADPCM */ + vgmstream->coding_type = coding_PSX_cfg; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = (block_align / 2) + 1; /* half, even if channels = 1 */ + + vgmstream->num_samples = blocksize * block_align; + if (loop_flag) { + vgmstream->loop_start_sample = (loop_start-1) * block_align;; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + break; + + case 1: /* PCM */ + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + + vgmstream->num_samples = blocksize; + if (loop_flag) { + vgmstream->loop_start_sample = (loop_start-1); + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + break; + default: + goto fail; } - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 9; - vgmstream->meta_type = meta_FFXI_SPW; /* 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;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+i*9; - - } - } + 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; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/btsnd.c b/Frameworks/vgmstream/vgmstream/src/meta/btsnd.c index e27803ef7..b0afa30fd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/btsnd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/btsnd.c @@ -8,7 +8,6 @@ Wii U boot sound file for each game/app. VGMSTREAM * init_vgmstream_btsnd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - coding_t coding_type; int channel_count = 2; int loop_flag; off_t start_offset = 0x8; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_header.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_header.c index 0da2d047f..293f4c3ef 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_header.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_header.c @@ -225,7 +225,7 @@ VGMSTREAM * init_vgmstream_ea(STREAMFILE *streamFile) { vgmstream->meta_type=meta_EAXA_R2; } - vgmstream->coding_type=coding_EAXA; + vgmstream->coding_type=coding_EA_XA; vgmstream->layout_type=layout_ea_blocked; if((vgmstream->ea_platform==EA_GC) || (vgmstream->ea_platform==EA_X360)) vgmstream->ea_big_endian=1; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c index f07763515..32082f62e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c @@ -194,57 +194,6 @@ ffmpeg_codec_data * init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, u } -/** - * Manually init FFmpeg, from an offset and creating a fake RIFF from a streamfile. - */ -ffmpeg_codec_data * init_ffmpeg_faux_riff(STREAMFILE *streamFile, int64_t fmt_offset, uint64_t start, uint64_t size, int big_endian) { - if (fmt_offset > 0) { - size_t header_size = 0; - int max_header_size = (int)(start - fmt_offset); - uint8_t p[100]; - if (max_header_size < 18 || max_header_size > 100) - goto fail; - //p = av_malloc(max_header_size + 8 + 4 + 8 + 8); - //if (!p) goto fail; - if (read_streamfile(p + 8 + 4 + 8, fmt_offset, max_header_size, streamFile) != max_header_size) - goto fail; - - if (big_endian) { - int shift = 8 + 4 + 8; - put_16bitLE(p+shift, get_16bitBE(p)); - put_16bitLE(p+shift + 2, get_16bitBE(p + 2)); - put_32bitLE(p+shift + 4, get_32bitBE(p + 4)); - put_32bitLE(p+shift + 8, get_32bitBE(p + 8)); - put_16bitLE(p+shift + 12, get_16bitBE(p + 12)); - put_16bitLE(p+shift + 14, get_16bitBE(p + 14)); - put_16bitLE(p+shift + 16, get_16bitBE(p + 16)); - } - header_size = 8 + 4 + 8 + 8 + 18 + get_16bitLE(p + 8 + 4 + 8 + 16); - // Meh, dunno how to handle swapping the extra data - // FFmpeg doesn't need most of this data anyway - if ((unsigned)(get_16bitLE(p + 8 + 4 + 8) - 0x165) < 2) - memset(p + 8 + 4 + 8 + 18, 0, 34); - - // Fill out the RIFF structure - memcpy(p, "RIFF", 4); - put_32bitLE(p + 4, header_size + size - 8); - memcpy(p + 8, "WAVE", 4); - memcpy(p + 12, "fmt ", 4); - put_32bitLE(p + 16, 18 + get_16bitLE(p + 8 + 4 + 8 + 16)); - memcpy(p + header_size - 8, "data", 4); - put_32bitLE(p + header_size - 4, size); - - - return init_ffmpeg_header_offset(streamFile, p, header_size, start, size); - } - else { - return init_ffmpeg_header_offset(streamFile, NULL, 0, start, size); - } - -fail: - return NULL; -} - /** * Manually init FFmpeg, from a fake header / offset. * diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c index 165d6d883..29e3a89e3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c @@ -1,825 +1,405 @@ #include "meta.h" #include "../coding/coding.h" -#include "../util.h" -/* FSB1 */ -VGMSTREAM * init_vgmstream_fsb1(STREAMFILE *streamFile) { +#define FAKE_RIFF_BUFFER_SIZE 100 - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; +static VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset); - /* int fsb1_included_files; */ - int fsb1_format; - int loop_flag = 0; - int channel_count; +/* ************************************************************************************************************ + * FSB defines, copied from the public spec (https://www.fmod.org/questions/question/forum-4928/) + * The format is mostly compatible for FSB1/2/3/4, but not FSB5. Headers always use LE. A FSB contains + * main header + sample header(s) + raw data. In multistreams N sample headers are stored (and + * if the BASICHEADERS flag is set, all headers but the first use HEADER_BASIC = numsamples + datasize) + * ************************************************************************************************************ */ +/* These flags are used for FMOD_FSB_HEADER::mode */ +#define FMOD_FSB_SOURCE_FORMAT 0x00000001 /* all samples stored in their original compressed format */ +#define FMOD_FSB_SOURCE_BASICHEADERS 0x00000002 /* samples should use the basic header structure */ +#define FMOD_FSB_SOURCE_ENCRYPTED 0x00000004 /* all sample data is encrypted */ +#define FMOD_FSB_SOURCE_BIGENDIANPCM 0x00000008 /* pcm samples have been written out in big-endian format */ +#define FMOD_FSB_SOURCE_NOTINTERLEAVED 0x00000010 /* Sample data is not interleaved. */ +#define FMOD_FSB_SOURCE_MPEG_PADDED 0x00000020 /* Mpeg frames are now rounded up to the nearest 2 bytes for normal sounds, or 16 bytes for multichannel. */ +#define FMOD_FSB_SOURCE_MPEG_PADDED4 0x00000040 /* Mpeg frames are now rounded up to the nearest 4 bytes for normal sounds, or 16 bytes for multichannel. */ - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("fsb",filename_extension(filename))) goto fail; +/* These flags are used for FMOD_FSB_HEADER::version */ +#define FMOD_FSB_VERSION_3_0 0x00030000 /* FSB version 3.0 */ +#define FMOD_FSB_VERSION_3_1 0x00030001 /* FSB version 3.1 */ +#define FMOD_FSB_VERSION_4_0 0x00040000 /* FSB version 4.0 */ - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x46534231) /* "FSB1" */ - goto fail; - - /* "Check if the FSB is used as - conatiner or as single file" */ - if (read_32bitBE(0x04,streamFile) != 0x01000000) - goto fail; +/* FMOD 3 defines. These flags are used for FMOD_FSB_SAMPLE_HEADER::mode */ +#define FSOUND_LOOP_OFF 0x00000001 /* For non looping samples. */ +#define FSOUND_LOOP_NORMAL 0x00000002 /* For forward looping samples. */ +#define FSOUND_LOOP_BIDI 0x00000004 /* For bidirectional looping samples. (no effect if in hardware). */ +#define FSOUND_8BITS 0x00000008 /* For 8 bit samples. */ +#define FSOUND_16BITS 0x00000010 /* For 16 bit samples. */ +#define FSOUND_MONO 0x00000020 /* For mono samples. */ +#define FSOUND_STEREO 0x00000040 /* For stereo samples. */ +#define FSOUND_UNSIGNED 0x00000080 /* For user created source data containing unsigned samples. */ +#define FSOUND_SIGNED 0x00000100 /* For user created source data containing signed data. */ +#define FSOUND_MPEG 0x00000200 /* For MPEG layer 2/3 data. */ +#define FSOUND_CHANNELMODE_ALLMONO 0x00000400 /* Sample is a collection of mono channels. */ +#define FSOUND_CHANNELMODE_ALLSTEREO 0x00000800 /* Sample is a collection of stereo channel pairs */ +#define FSOUND_HW3D 0x00001000 /* Attempts to make samples use 3d hardware acceleration. (if the card supports it) */ +#define FSOUND_2D 0x00002000 /* Tells software (not hardware) based sample not to be included in 3d processing. */ +#define FSOUND_SYNCPOINTS_NONAMES 0x00004000 /* Specifies that syncpoints are present with no names */ +#define FSOUND_DUPLICATE 0x00008000 /* This subsound is a duplicate of the previous one i.e. it uses the same sample data but w/different mode bits */ +#define FSOUND_CHANNELMODE_PROTOOLS 0x00010000 /* Sample is 6ch and uses L C R LS RS LFE standard. */ +#define FSOUND_MPEGACCURATE 0x00020000 /* For FSOUND_Stream_Open - for accurate FSOUND_Stream_GetLengthMs/FSOUND_Stream_SetTime. WARNING, see FSOUND_Stream_Open for inital opening time performance issues. */ +#define FSOUND_HW2D 0x00080000 /* 2D hardware sounds. allows hardware specific effects */ +#define FSOUND_3D 0x00100000 /* 3D software sounds */ +#define FSOUND_32BITS 0x00200000 /* For 32 bit (float) samples. */ +#define FSOUND_IMAADPCM 0x00400000 /* Contents are stored compressed as IMA ADPCM */ +#define FSOUND_VAG 0x00800000 /* For PS2 only - Contents are compressed as Sony VAG format */ +#define FSOUND_XMA 0x01000000 /* For Xbox360 only - Contents are compressed as XMA format */ +#define FSOUND_GCADPCM 0x02000000 /* For Gamecube only - Contents are compressed as Gamecube DSP-ADPCM format */ +#define FSOUND_MULTICHANNEL 0x04000000 /* For PS2 and Gamecube only - Contents are interleaved into a multi-channel (more than stereo) format */ +#define FSOUND_OGG 0x08000000 /* For vorbis encoded ogg data */ +#define FSOUND_CELT 0x08000000 /* For vorbis encoded ogg data */ +#define FSOUND_MPEG_LAYER3 0x10000000 /* Data is in MP3 format. */ +#define FSOUND_MPEG_LAYER2 0x00040000 /* Data is in MP2 format. */ +#define FSOUND_LOADMEMORYIOP 0x20000000 /* For PS2 only - "name" will be interpreted as a pointer to data for streaming and samples. The address provided will be an IOP address */ +#define FSOUND_IMAADPCMSTEREO 0x20000000 /* Signify IMA ADPCM is actually stereo not two interleaved mono */ +#define FSOUND_IGNORETAGS 0x40000000 /* Skips id3v2 etc tag checks when opening a stream, to reduce seek/read overhead when opening files (helps with CD performance) */ +#define FSOUND_SYNCPOINTS 0x80000000 /* Specifies that syncpoints are present */ - loop_flag = 0; - channel_count = 2; +/* These flags are used for FMOD_FSB_SAMPLE_HEADER::mode */ +#define FSOUND_CHANNELMODE_MASK (FSOUND_CHANNELMODE_ALLMONO | FSOUND_CHANNELMODE_ALLSTEREO | FSOUND_CHANNELMODE_PROTOOLS) +#define FSOUND_CHANNELMODE_DEFAULT 0x00000000 /* Determine channel assignment automatically from channel count. */ +#define FSOUND_CHANNELMODE_RESERVED 0x00000C00 - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; +#define FSOUND_NORMAL (FSOUND_16BITS | FSOUND_SIGNED | FSOUND_MONO) - /* This will be tricky ;o) */ - fsb1_format = read_32bitBE(0x44,streamFile); - switch (fsb1_format) { - case 0x40008800: /* PS2 (Operation Genesis) */ - case 0x41008800: /* PS2 (Operation Genesis) */ - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - vgmstream->num_samples = (read_32bitLE(0x34,streamFile))*28/16/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x30,streamFile); - } - break; - default: - goto fail; +#define FSB_SAMPLE_DATA_ALIGN 32 - } - /* fill in the vital statistics */ - start_offset = 0x50; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x38,streamFile); - vgmstream->meta_type = meta_FSB1; - - /* 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;ich[i].streamfile = file; +/* simplified struct based on the original definitions */ +typedef struct { + /* main header */ + uint32_t id; + int32_t numsamples; /* number of samples(streams) in the file */ + uint32_t shdrsize; /* size in bytes of all of the sample headers including extended information */ + uint32_t datasize; /* size in bytes of compressed sample data */ + /* main header: FSB 3/3.1/4 */ + uint32_t version; /* extended fsb version */ + uint32_t flags; /* flags that apply to all samples(streams) in the fsb */ + /* sample header */ + uint32_t lengthsamples; + uint32_t lengthcompressedbytes; + uint32_t loopstart; + uint32_t loopend; + uint32_t mode; + int32_t deffreq; + uint16_t numchannels; + /* extra */ + uint32_t hdrsize; + uint32_t shdrsize_min; + meta_t meta_type; +} FSB_HEADER; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - -/* FSB3.0 and FSB3.1 */ -VGMSTREAM * init_vgmstream_fsb3(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int fsb_headerlen; - int channel_count; - int loop_flag = 0; - int FSBFlag = 0; - int i, c; - off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - - if (strcasecmp("fsb",filename_extension(filename))) - goto fail; - - /* check header for "FSB3" string */ - if (read_32bitBE(0x00,streamFile) != 0x46534233) - goto fail; - - /* "Check if the FSB is used as conatiner or as single file" */ - if (read_32bitLE(0x04,streamFile) != 0x1) - goto fail; - - /* Check if we're dealing with a FSB3.0 file */ - if ((read_32bitBE(0x10,streamFile) != 0x00000300) && - ((read_32bitBE(0x10,streamFile) != 0x01000300))) - goto fail; - - channel_count = read_16bitLE(0x56,streamFile); - fsb_headerlen = read_32bitLE(0x08,streamFile); - - FSBFlag = read_32bitLE(0x48,streamFile); - - if (FSBFlag&0x2 || FSBFlag&0x4 || FSBFlag&0x6) - loop_flag = 1; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - start_offset = fsb_headerlen+0x18; - vgmstream->sample_rate = (read_32bitLE(0x4C, streamFile)); - - - // Get the Decoder - if (FSBFlag&0x00000100) - { // Ignore format and treat as RAW PCM - vgmstream->coding_type = coding_PCM16LE; - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else if (channel_count > 1) - { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x2; - } - } - else if (FSBFlag&0x00400000) - { // XBOX IMA - vgmstream->coding_type = coding_XBOX; - vgmstream->layout_type = layout_none; - } - else if (FSBFlag&0x00800000) - { // PS2 ADPCM - vgmstream->coding_type = coding_PSX; - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else if (channel_count > 1) - { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - } - } - else if (FSBFlag&0x02000000) - { // Nintendo DSP - vgmstream->coding_type = coding_NGC_DSP; - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else if (channel_count > 1) - { - vgmstream->layout_type = layout_interleave_byte; - vgmstream->interleave_block_size = 2; - } - // read coeff(s), DSP only - for (c=0;cch[c].adpcm_coef[i]=read_16bitBE(0x68+c*0x2e +i*2,streamFile); - } - } - } - else goto fail; - - vgmstream->num_samples = read_32bitLE(0x38,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x40,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x44,streamFile); - } - - - if (read_32bitBE(0x10,streamFile) == 0x00000300) - { - vgmstream->meta_type = meta_FSB3_0; - } - else if (read_32bitBE(0x10,streamFile) == 0x01000300) - { - vgmstream->meta_type = meta_FSB3_1; - } - - /* 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;ich[i].streamfile = file; - - if (vgmstream->coding_type == coding_XBOX) { - /* xbox interleaving is a little odd */ - vgmstream->ch[i].channel_start_offset=start_offset; - } else { - vgmstream->ch[i].channel_start_offset= - start_offset+vgmstream->interleave_block_size*i; - } - vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} +/* ********************************************************************************** */ /* FSB4 */ -VGMSTREAM * init_vgmstream_fsb4(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_fsb(STREAMFILE *streamFile) { + return init_vgmstream_fsb_offset(streamFile, 0x0); +} + +/* FSB4 with "\0WAV" Header, found in Deadly Creatures (Wii) + * 16 byte header which holds the filesize + * (unsure if this is from a proper rip) */ +VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE *streamFile) { + if (read_32bitBE(0x00,streamFile) != 0x00574156) /* "\0WAV" */ + return NULL; + return init_vgmstream_fsb_offset(streamFile, 0x10); +} + +VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int fsb4_format; + off_t start_offset, h_off, s_off; + size_t custom_data_offset; int loop_flag = 0; - int channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("fsb",filename_extension(filename)) && - strcasecmp("wii",filename_extension(filename))) goto fail; + FSB_HEADER fsbh; + + /* check extensions */ + if ( !check_extensions(streamFile, "fsb,wii") ) + goto fail; + + h_off = offset; /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x46534234) /* "FSB4" */ - goto fail; - - /* "Check if the FSB is used as - conatiner or as single file" */ - if (read_32bitBE(0x04,streamFile) != 0x01000000) - goto fail; + fsbh.id = read_32bitBE(offset+0x00,streamFile); + if (fsbh.id == 0x46534231) { /* "FSB1" (somewhat different from other fsbs) */ + fsbh.meta_type = meta_FSB1; + fsbh.hdrsize = 0x10; + fsbh.shdrsize_min = 0x40; - if (read_32bitBE(0x60,streamFile) == 0x40008800 || - read_32bitBE(0x60,streamFile) == 0x40000802 || - read_32bitBE(0x60,streamFile) == 0x40100802 || - read_32bitBE(0x60,streamFile) == 0x000040A0 || - read_32bitBE(0x60,streamFile) == 0x40004020) { - loop_flag = 1; - } else { - loop_flag = 0; + /* main header */ + fsbh.numsamples = read_32bitLE(h_off+0x04,streamFile); + fsbh.datasize = read_32bitLE(h_off+0x08,streamFile); + fsbh.shdrsize = 0x40; + fsbh.version = 0; + fsbh.flags = 0; + + s_off = offset+fsbh.hdrsize; + /* sample header */ + /* 0x00:name(len=0x20) */ + fsbh.lengthsamples = read_32bitLE(s_off+0x20,streamFile); + fsbh.lengthcompressedbytes = read_32bitLE(s_off+0x24,streamFile); + fsbh.deffreq = read_32bitLE(s_off+0x28,streamFile); + /* 0x2c:? 0x2e:? 0x30:? 0x32:? */ + fsbh.mode = read_32bitLE(s_off+0x34,streamFile); + fsbh.loopstart = read_32bitLE(s_off+0x38,streamFile); + fsbh.loopend = read_32bitLE(s_off+0x3c,streamFile); + + fsbh.numchannels = (fsbh.mode & FSOUND_STEREO) ? 2 : 1; + if (fsbh.loopend > fsbh.lengthsamples) /* this seems common... */ + fsbh.lengthsamples = fsbh.loopend; + } + else { /* other FSBs (common/extended format) */ + if (fsbh.id == 0x46534232) { /* "FSB2" */ + fsbh.meta_type = meta_FSB2; + fsbh.hdrsize = 0x10; + fsbh.shdrsize_min = 0x40; /* guessed */ + } else if (fsbh.id == 0x46534233) { /* "FSB3" */ + fsbh.meta_type = meta_FSB3; + fsbh.hdrsize = 0x18; + fsbh.shdrsize_min = 0x40; + } else if (fsbh.id == 0x46534234) { /* "FSB4" */ + fsbh.meta_type = meta_FSB4; + fsbh.hdrsize = 0x30; + fsbh.shdrsize_min = 0x50; + } else { + goto fail; + } + + /* main header */ + fsbh.numsamples = read_32bitLE(h_off+0x04,streamFile); + fsbh.shdrsize = read_32bitLE(h_off+0x08,streamFile); + fsbh.datasize = read_32bitLE(h_off+0x0c,streamFile); + if (fsbh.hdrsize > 0x10) { + fsbh.version = read_32bitLE(h_off+0x10,streamFile); + fsbh.flags = read_32bitLE(h_off+0x14,streamFile); + /* FSB4: 0x18:hash 0x20:guid */ + } else { + fsbh.version = 0; + fsbh.flags = 0; + } + + if (fsbh.version == FMOD_FSB_VERSION_3_1) { + fsbh.shdrsize_min = 0x50; + } else if (fsbh.version != 0 /* FSB2 */ + && fsbh.version != FMOD_FSB_VERSION_3_0 + && fsbh.version != FMOD_FSB_VERSION_4_0) { + goto fail; + } + + if (fsbh.shdrsize < fsbh.shdrsize_min) goto fail; + + s_off = offset+fsbh.hdrsize; + /* sample header */ + /* 0x00:size 0x02:name(len=size) */ + fsbh.lengthsamples = read_32bitLE(s_off+0x20,streamFile); + fsbh.lengthcompressedbytes = read_32bitLE(s_off+0x24,streamFile); + fsbh.loopstart = read_32bitLE(s_off+0x28,streamFile); + fsbh.loopend = read_32bitLE(s_off+0x2c,streamFile); + fsbh.mode = read_32bitLE(s_off+0x30,streamFile); + fsbh.deffreq = read_32bitLE(s_off+0x34,streamFile); + /* 0x38:defvol 0x3a:defpan 0x3c:defpri */ + fsbh.numchannels = read_16bitLE(s_off+0x3e,streamFile); + /* FSB3.1/4: 0x40:mindistance 0x44:maxdistance 0x48:varfreq/size_32bits 0x4c:varvol 0x4e:fsbh.varpan */ + /* 0x50:extended_data (of size_32bits, when fsbh.shdrsize > 0x50) */ } + /* FSB header ok, check other stuff */ + if (fsbh.numsamples != 1) { /* multistream */ + VGM_LOG("FSB numsamples > 1 found\n"); + goto fail; + } + /* XOR encryption for some FSB4 */ + if (fsbh.flags & FMOD_FSB_SOURCE_ENCRYPTED) { + VGM_LOG("FSB ENCRYPTED found\n"); + goto fail; + } #if 0 - if (read_32bitBE(0x60,streamFile) != 0x20000882 && - read_32bitBE(0x60,streamFile) != 0x20100002 && - read_32bitBE(0x60,streamFile) != 0x20100882 && - read_32bitBE(0x60,streamFile) != 0x20100802 && - read_32bitBE(0x60,streamFile) != 0x20100082 && - read_32bitBE(0x60,streamFile) != 0x20000802) { - channel_count = 2; - } else { - channel_count = 1; + /* sometimes there is garbage at the end or missing bytes? (Guitar Hero Wii) */ + if (fsbh.hdrsize + fsbh.shdrsize + fsbh.datasize != streamFile->get_size(streamFile) - offset) { + VGM_LOG("FSB wrong head/datasize found\n"); + goto fail; } #endif - channel_count = (uint16_t)read_16bitLE(0x6E,streamFile); + start_offset = offset + fsbh.hdrsize + fsbh.shdrsize; + custom_data_offset = offset + fsbh.hdrsize + fsbh.shdrsize_min; /* DSP coefs, seek tables, etc */ + + /* Loops by default unless disabled (sometimes may add FSOUND_LOOP_NORMAL). Often streams + * repeat over and over (some tracks that shouldn't do this based on the flags, no real way to identify them). */ + loop_flag = !(fsbh.mode & FSOUND_LOOP_OFF); /* (fsbh.mode & FSOUND_LOOP_NORMAL) */ + /* ping-pong looping = no looping? (forward > reverse > forward) */ + VGM_ASSERT(fsbh.mode & FSOUND_LOOP_BIDI, "FSB BIDI looping found\n"); /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(fsbh.numchannels,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x64,streamFile); - fsb4_format = read_32bitBE(0x60,streamFile); - switch (fsb4_format) { - /* PC Blade Kitten */ - case 0x40004020: - case 0x20004000: - case 0x00004020: - case 0x000040A0: + vgmstream->sample_rate = fsbh.deffreq; + vgmstream->num_samples = fsbh.lengthsamples; + vgmstream->loop_start_sample = fsbh.loopstart; + vgmstream->loop_end_sample = fsbh.loopend; + vgmstream->meta_type = fsbh.meta_type; + + /* parse format */ + if (fsbh.mode & FSOUND_MPEG) { + /* FSB3: ?; FSB4: Shatter, Way of the Samurai 3/4, Forza Horizon 1/2, Dragon Age Origins */ +#if defined(VGM_USE_MPEG) + mpeg_codec_data *mpeg_data = NULL; + coding_t mpeg_coding_type; + + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, vgmstream->sample_rate, vgmstream->channels, &mpeg_coding_type, NULL, NULL); + if (!mpeg_data) goto fail; + + vgmstream->codec_data = mpeg_data; + vgmstream->coding_type = mpeg_coding_type; + vgmstream->layout_type = layout_mpeg; + + /* struct mpg123_frameinfo mpeg_info; */ + /* if (MPG123_OK != mpg123_info(mpeg_data->m, &mpeg_info)) goto fail; */ + VGM_ASSERT(fsbh.mode & FSOUND_MPEG_LAYER2, "FSB FSOUND_MPEG_LAYER2 found\n"); + VGM_ASSERT(fsbh.mode & FSOUND_IGNORETAGS, "FSB FSOUND_IGNORETAGS found\n"); + + /* when these flags are set each MPEG frame is 0-padded at the end, and mpg123 will complain to stderr (but ignore them) + * no way to easily skip the padding so for now we'll just disable stderr output */ + if ((fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED) || (fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED4)) { + mpeg_set_error_logging(mpeg_data, 0); + } + +#elif defined(VGM_USE_FFMPEG) + /* FFmpeg can't properly read FSB4 or FMOD's 0-padded MPEG data @ start_offset, this won't work */ + ffmpeg_codec_data *ffmpeg_data = NULL; + + ffmpeg_data = init_ffmpeg_offset(streamFile, 0, streamFile->get_size(streamFile)); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + +#else + VGM_LOG("FSB4 MPEG found\n"); + goto fail; +#endif + } + else if (fsbh.mode & FSOUND_IMAADPCM) { /* (codec 0x69, Voxware Byte Aligned) */ + if (fsbh.mode & FSOUND_IMAADPCMSTEREO) { /* noninterleaved, true stereo IMA */ + /* FSB4: Shatter, Blade Kitten (PC), Hard Corps: Uprising (PS3) */ + vgmstream->coding_type = coding_MS_IMA; /* todo not always working in Hard Corps, interleave problem? */ + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x24*vgmstream->channels; + //VGM_LOG("FSB FSOUND_IMAADPCMSTEREO found\n"); + } else { + /* FSB3: Bioshock (PC); FSB4: Blade Kitten (PC) */ vgmstream->coding_type = coding_MS_IMA; vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = 0x24*vgmstream->channels; - vgmstream->num_samples = (read_32bitLE(0x54,streamFile)/0x24/vgmstream->channels)*((0x24-4)*2); - //vgmstream->num_samples = read_32bitLE(0x50,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x58,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x5C,streamFile); + //VGM_LOG("FSB FSOUND_IMAADPCM found\n"); +#if 0 + if (fsbh.numchannels > 2) { /* Blade Kitten 5.1 */ + vgmstream->coding_type = coding_XBOX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x12 * vgmstream->channels; + } +#endif + + } + } + else if (fsbh.mode & FSOUND_VAG) { + /* FSB1: Jurassic Park Operation Genesis + * FSB3: ?; FSB4: Spider Man Web of Shadows, Speed Racer, Silent Hill: Shattered Memories (PS2) */ + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + } + else if (fsbh.mode & FSOUND_XMA) { + /* FSB4: Xbox360 Armored Core V, Hard Corps, Halo Anniversary */ +#if defined(VGM_USE_FFMPEG) + ffmpeg_codec_data *ffmpeg_data = NULL; + 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_count = fsbh.datasize / block_size; /* read_32bitLE(custom_data_offset +0x14) -1? */ + + /* make a fake riff so FFmpeg can parse the XMA2 */ + bytes = ffmpeg_make_riff_xma2(buf, FAKE_RIFF_BUFFER_SIZE, fsbh.lengthsamples, fsbh.datasize, fsbh.numchannels, fsbh.deffreq, block_count, block_size); + if (bytes <= 0) + goto fail; + + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,fsbh.datasize); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + +#else + VGM_LOG("FSB XMA found\n"); + goto fail; +#endif + } + else if (fsbh.mode & FSOUND_GCADPCM) { + /* FSB3: ?; FSB4: de Blob (Wii), Night at the Museum, M. Night Shyamalan Avatar: The Last Airbender */ + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave_byte; + vgmstream->interleave_block_size = 0x2; + dsp_read_coefs_be(vgmstream, streamFile, custom_data_offset, 0x2e); + } + else if (fsbh.mode & FSOUND_OGG) { + /* FSB4: ? (possibly FMOD's custom ogg) */ + + VGM_LOG("FSB4 FSOUND_OGG found\n"); + goto fail; + } + else if (fsbh.mode & FSOUND_CELT) { + /* FSB4: ? (The Witcher 2?) */ + + VGM_LOG("FSB4 FSOUND_CELT found\n"); + goto fail; + } + else { /* PCM */ + if (fsbh.mode & FSOUND_8BITS) { + VGM_LOG("FSB FSOUND_8BITS found\n"); + if (fsbh.mode & FSOUND_UNSIGNED) { + vgmstream->coding_type = coding_PCM8_U; /* ? coding_PCM8_U_int */ + } else { /* FSOUND_SIGNED */ + vgmstream->coding_type = coding_PCM8; /* ? coding_PCM8_int / coding_PCM8_SB_int */ } - break; - /* PS2 (Spider Man - Web of Shadows), Speed Racer */ - case 0x40008800: - case 0x20008800: // Silent Hill: Shattered Memories - vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - vgmstream->num_samples = (read_32bitLE(0x54,streamFile))*28/16/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x50,streamFile); + vgmstream->interleave_block_size = 0x1; + } else { /* Rocket Knight (PC), Another Century's Episode R (PS3), Toy Story 3 (Wii) */ + /* sometimes FSOUND_STEREO/FSOUND_MONO is not set (ex. Dead Space iOS), + * or only STEREO/MONO but not FSOUND_8BITS/FSOUND_16BITS is set */ + if (fsbh.flags & FMOD_FSB_SOURCE_BIGENDIANPCM) { + vgmstream->coding_type = coding_PCM16BE; + } else { + vgmstream->coding_type = coding_PCM16LE; /* ? coding_PCM16LE_int ? */ } - break; - /* de Blob 2*/ - case 0x00000886: - /* WII (de Blob, Night at the Museum) */ - case 0x40000802: - case 0x40000882: - case 0x40100802: - case 0x40200802: - case 0x00000802: - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x50,streamFile); - } - - if (read_32bitLE(0x14,streamFile)==0x20 || - read_32bitLE(0x14,streamFile)==0x22 || - read_32bitLE(0x14,streamFile)==0x00) - { - /* Night at the Museum */ - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave_byte; - vgmstream->interleave_block_size = 2; - } - else if (read_32bitLE(0x14,streamFile)==0x10 || - read_32bitLE(0x14,streamFile)==0x30) - { - /* de Blob, NatM sfx */ - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_none; - vgmstream->interleave_block_size = read_32bitLE(0x54,streamFile)/channel_count; - } - else if (read_32bitLE(0x14,streamFile)==0x40) { - /* M. Night Shamylan The Last Airbender */ - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave_byte; - vgmstream->interleave_block_size = 2; - - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x58,streamFile); - } - } - else goto fail; - - vgmstream->num_samples = (read_32bitLE(0x54,streamFile)/8/channel_count*14); - break; - - /* Night at the Museum */ - case 0x20000882: - case 0x20000802: - case 0x20100002: - case 0x20100882: - case 0x20100802: - case 0x20100082: - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_none; - vgmstream->num_samples = (read_32bitLE(0x54,streamFile)/8/channel_count*14); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x50,streamFile); - } - break; - - /* Rocket Knight (PC) */ - case 0x10000000: /* Dead Space (iOS) */ - case 0x50210000: - case 0x30210000: - case 0x30011000: - case 0x20005000: - case 0x30011080: - case 0x30211000: - case 0x40005020: - case 0x20204000: - case 0x40204020: - case 0x50011000: - case 0x20205000: - case 0x30610080: - case 0x50210080: /* Another Century's Episode R (PS3) */ - case 0x50010800: /* Toy Story 3 (PS3) */ - vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x2; - vgmstream->num_samples = (read_32bitLE(0x5C,streamFile)); - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x58,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x5C,streamFile); - } - break; - default: - goto fail; - } - - start_offset = read_32bitLE(0x08,streamFile)+0x30; - - vgmstream->meta_type = meta_FSB4; - - if (vgmstream->coding_type == coding_NGC_DSP) { - int c,i; - for (c=0;cch[c].adpcm_coef[i] = - read_16bitBE(0x80+c*0x2e + i*2,streamFile); - } } } - + + /* full channel interleave, used in short streams (ex. de Blob Wii SFXs) */ + if (fsbh.numchannels > 1 && (fsbh.flags & FMOD_FSB_SOURCE_NOTINTERLEAVED)) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = fsbh.lengthcompressedbytes / fsbh.numchannels; + } + + /* 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;ich[i].streamfile = file; - - - if (vgmstream->coding_type == coding_MS_IMA) { - // both IMA channels work with same bytes - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset; - } else { - 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; } - - -/* FSB4 with "WAV" Header, found in "Deadly Creatures (WII)" - 16 byte "WAV" header which holds the filesize...*/ -VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag; - int channel_count; - int fsb_headerlength; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("fsb",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x00574156) /* 0x0\"WAV" */ - goto fail; - if (read_32bitBE(0x10,streamFile) != 0x46534234) /* "FSB4" */ - goto fail; - - channel_count = (uint16_t)read_16bitLE(0x7E,streamFile); - - if (channel_count > 2) { - goto fail; - } - - loop_flag = (read_32bitBE(0x70,streamFile) == 0x40000802); - fsb_headerlength = read_32bitLE(0x18,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = fsb_headerlength + 0x40; - vgmstream->sample_rate = read_32bitLE(0x74,streamFile); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave_byte; - vgmstream->interleave_block_size = 0x2; - vgmstream->num_samples = (read_32bitLE(0x64,streamFile)/8/channel_count*14); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x60,streamFile); - } - - vgmstream->meta_type = meta_FSB4_WAV; - - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x90+i*2,streamFile); - } - if (vgmstream->channels == 2) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xBE + 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;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - - -// FSB3 & FSB4 MPEG TEST -VGMSTREAM * init_vgmstream_fsb_mpeg(STREAMFILE *streamFile) { -#ifdef VGM_USE_MPEG - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int channel_count, channels, loop_flag, fsb_mainheader_len, fsb_subheader_len, FSBFlag, rate; - long sample_rate = 0, num_samples = 0; - uint16_t mp3ID; - -#ifdef VGM_USE_MPEG - mpeg_codec_data *mpeg_data = NULL; - coding_t mpeg_coding_type = coding_MPEG1_L3; -#endif - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("fsb",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) == 0x46534233) /* "FSB3" */ - { - fsb_mainheader_len = 0x18; - } - else if (read_32bitBE(0x00,streamFile) == 0x46534234) /* "FSB4" */ - { - fsb_mainheader_len = 0x30; - } - else - { - goto fail; - } - - fsb_subheader_len = read_16bitLE(fsb_mainheader_len,streamFile); - - /* "Check if the FSB is used as conatiner or as single file" */ - if (read_32bitBE(0x04,streamFile) != 0x01000000) - goto fail; - -#if 0 - /* Check channel count, multi-channel not supported and will be refused */ - if ((read_16bitLE(0x6E,streamFile) != 0x2) && - (read_16bitLE(0x6E,streamFile) != 0x1)) - goto fail; -#endif - - start_offset = fsb_mainheader_len+fsb_subheader_len+0x10; - - /* Check the MPEG Sync Header */ - mp3ID = read_16bitBE(start_offset,streamFile); - if ((mp3ID&0xFFE0) != 0xFFE0) - goto fail; - - channel_count = read_16bitLE(fsb_mainheader_len+0x3E,streamFile); - if (channel_count != 1 && channel_count != 2) - goto fail; - - FSBFlag = read_32bitLE(fsb_mainheader_len+0x30,streamFile); - if (FSBFlag&0x2 || FSBFlag&0x4 || FSBFlag&0x6) - loop_flag = 1; - - num_samples = (read_32bitLE(fsb_mainheader_len+0x2C,streamFile)); - - mpeg_data = init_mpeg_codec_data(streamFile, start_offset, -1, -1, &mpeg_coding_type, &rate, &channels); // -1 to not check sample rate or channels - if (!mpeg_data) goto fail; - - //channel_count = channels; - sample_rate = rate; - - /* 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->channels = channel_count; - - /* Still WIP */ - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(fsb_mainheader_len+0x28,streamFile); - vgmstream->loop_end_sample = read_32bitLE(fsb_mainheader_len+0x2C,streamFile); - } - vgmstream->meta_type = meta_FSB_MPEG; - - /* NOTE: num_samples seems to be quite wrong for MPEG */ - vgmstream->codec_data = mpeg_data; - vgmstream->layout_type = layout_mpeg; - vgmstream->coding_type = mpeg_coding_type; - -#if 0 - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/960*1152; - vgmstream->loop_end_sample = read_32bitBE(0x1C,streamFile)/960*1152; - } -#endif - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - if(vgmstream->layout_type == layout_interleave) - { - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - else if(vgmstream->layout_type == layout_mpeg) { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); - vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset; - } - - } - else { goto fail; } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (mpeg_data) { - mpg123_delete(mpeg_data->m); - free(mpeg_data); - - if (vgmstream) { - vgmstream->codec_data = NULL; - } - } - if (vgmstream) close_vgmstream(vgmstream); -#endif - return NULL; -} - -#if 0 -// FSB5 MPEG -VGMSTREAM * init_vgmstream_fsb5_mpeg(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int channel_count, channels, loop_flag, fsb_mainheader_len, fsb_subheader_len, FSBFlag, rate; - long sample_rate = 0, num_samples = 0; - uint16_t mp3ID; - -#ifdef VGM_USE_MPEG - mpeg_codec_data *mpeg_data = NULL; - coding_t mpeg_coding_type = coding_MPEG1_L3; -#endif - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("fsb",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) == 0x46534235) /* "FSB5" */ - { - fsb_mainheader_len = 0x3C; - } - else - { - goto fail; - } - - //fsb_subheader_len = read_16bitLE(fsb_mainheader_len,streamFile); - - /* "Check if the FSB is used as conatiner or as single file" */ - if (read_32bitBE(0x04,streamFile) != 0x01000000) - goto fail; - -#if 0 - /* Check channel count, multi-channel not supported and will be refused */ - if ((read_16bitLE(0x6E,streamFile) != 0x2) && - (read_16bitLE(0x6E,streamFile) != 0x1)) - goto fail; -#endif - - start_offset = fsb_mainheader_len+fsb_subheader_len+0x10; - - /* Check the MPEG Sync Header */ - mp3ID = read_16bitBE(start_offset,streamFile); - if ((mp3ID&0xFFE0) != 0xFFE0) - goto fail; - - channel_count = read_16bitLE(fsb_mainheader_len+0x3E,streamFile); - if (channel_count != 1 && channel_count != 2) - goto fail; - - FSBFlag = read_32bitLE(fsb_mainheader_len+0x30,streamFile); - if (FSBFlag&0x2 || FSBFlag&0x4 || FSBFlag&0x6) - loop_flag = 1; - - num_samples = (read_32bitLE(fsb_mainheader_len+0x2C,streamFile)); - -#ifdef VGM_USE_MPEG - mpeg_data = init_mpeg_codec_data(streamFile, start_offset, -1, -1, &mpeg_coding_type, &rate, &channels); // -1 to not check sample rate or channels - if (!mpeg_data) goto fail; - - //channel_count = channels; - sample_rate = rate; - -#else - // reject if no MPEG support - goto fail; -#endif - - /* 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->channels = channel_count; - - /* Still WIP */ - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(fsb_mainheader_len+0x28,streamFile); - vgmstream->loop_end_sample = read_32bitLE(fsb_mainheader_len+0x2C,streamFile); - } - vgmstream->meta_type = meta_FSB_MPEG; - -#ifdef VGM_USE_MPEG - /* NOTE: num_samples seems to be quite wrong for MPEG */ - vgmstream->codec_data = mpeg_data; - vgmstream->layout_type = layout_mpeg; - vgmstream->coding_type = mpeg_coding_type; -#else - // reject if no MPEG support - goto fail; -#endif - - -#if 0 - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/960*1152; - vgmstream->loop_end_sample = read_32bitBE(0x1C,streamFile)/960*1152; - } -#endif - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - if(vgmstream->layout_type == layout_interleave) - { - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - -#ifdef VGM_USE_MPEG - else if(vgmstream->layout_type == layout_mpeg) { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); - vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset; - } - - } -#endif - else { goto fail; } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: -#ifdef VGM_USE_MPEG - if (mpeg_data) { - mpg123_delete(mpeg_data->m); - free(mpeg_data); - - if (vgmstream) { - vgmstream->codec_data = NULL; - } - } -#endif - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} -#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c index 8ffde4e55..240bd55c9 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb5.c @@ -15,7 +15,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { int NumSamples; int ChannelCount; int SampleRate; - int DSPInfoStart; + int DSPInfoStart = 0; int SampleHeaderStart, SampleHeaderLength, NameTableLength, SampleDataLength, CodingID, SampleMode; int ExtraFlag, ExtraFlagStart, ExtraFlagType, ExtraFlagSize, ExtraFlagEnd; @@ -298,3 +298,155 @@ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; } + +#if 0 +// FSB5 MPEG +VGMSTREAM * init_vgmstream_fsb5_mpeg(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int channel_count, channels, loop_flag, fsb_mainheader_len, fsb_subheader_len, FSBFlag, rate; + long sample_rate = 0, num_samples = 0; + uint16_t mp3ID; + +#ifdef VGM_USE_MPEG + mpeg_codec_data *mpeg_data = NULL; + coding_t mpeg_coding_type = coding_MPEG1_L3; +#endif + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("fsb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) == 0x46534235) /* "FSB5" */ + { + fsb_mainheader_len = 0x3C; + } + else + { + goto fail; + } + + //fsb_subheader_len = read_16bitLE(fsb_mainheader_len,streamFile); + + /* "Check if the FSB is used as conatiner or as single file" */ + if (read_32bitBE(0x04,streamFile) != 0x01000000) + goto fail; + +#if 0 + /* Check channel count, multi-channel not supported and will be refused */ + if ((read_16bitLE(0x6E,streamFile) != 0x2) && + (read_16bitLE(0x6E,streamFile) != 0x1)) + goto fail; +#endif + + start_offset = fsb_mainheader_len+fsb_subheader_len+0x10; + + /* Check the MPEG Sync Header */ + mp3ID = read_16bitBE(start_offset,streamFile); + if ((mp3ID&0xFFE0) != 0xFFE0) + goto fail; + + channel_count = read_16bitLE(fsb_mainheader_len+0x3E,streamFile); + if (channel_count != 1 && channel_count != 2) + goto fail; + + FSBFlag = read_32bitLE(fsb_mainheader_len+0x30,streamFile); + if (FSBFlag&0x2 || FSBFlag&0x4 || FSBFlag&0x6) + loop_flag = 1; + + num_samples = (read_32bitLE(fsb_mainheader_len+0x2C,streamFile)); + +#ifdef VGM_USE_MPEG + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, -1, -1, &mpeg_coding_type, &rate, &channels); // -1 to not check sample rate or channels + if (!mpeg_data) goto fail; + + //channel_count = channels; + sample_rate = rate; + +#else + // reject if no MPEG support + goto fail; +#endif + + /* 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->channels = channel_count; + + /* Still WIP */ + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(fsb_mainheader_len+0x28,streamFile); + vgmstream->loop_end_sample = read_32bitLE(fsb_mainheader_len+0x2C,streamFile); + } + vgmstream->meta_type = meta_FSB_MPEG; + +#ifdef VGM_USE_MPEG + /* NOTE: num_samples seems to be quite wrong for MPEG */ + vgmstream->codec_data = mpeg_data; + vgmstream->layout_type = layout_mpeg; + vgmstream->coding_type = mpeg_coding_type; +#else + // reject if no MPEG support + goto fail; +#endif + + +#if 0 + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/960*1152; + vgmstream->loop_end_sample = read_32bitBE(0x1C,streamFile)/960*1152; + } +#endif + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + if(vgmstream->layout_type == layout_interleave) + { + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + +#ifdef VGM_USE_MPEG + else if(vgmstream->layout_type == layout_mpeg) { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); + vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset; + } + + } +#endif + else { goto fail; } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: +#ifdef VGM_USE_MPEG + if (mpeg_data) { + mpg123_delete(mpeg_data->m); + free(mpeg_data); + + if (vgmstream) { + vgmstream->codec_data = NULL; + } + } +#endif + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/g1l.c b/Frameworks/vgmstream/vgmstream/src/meta/g1l.c index 17d9dd2a9..7ea4efe32 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/g1l.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/g1l.c @@ -1,118 +1,106 @@ #include "meta.h" #include "../util.h" -// Koei Tecmo G1L, found in the Warriors games -VGMSTREAM * init_vgmstream_g1l(STREAMFILE *streamFile) { +#include "../coding/coding.h" + +static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t offset); + +/* Koei Tecmo G1L - pack format, sometimes containing a single stream + * + * It probably makes more sense to extract it externally, it's here mainly for Hyrule Warriors */ +VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; + int type, num_streams, target_stream = 1; + off_t stream_offset; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - coding_t coding_type; - - off_t head_offset; - - int channel_count; - int loop_flag; - off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile, filename, sizeof(filename)); - if (strcasecmp("g1l", filename_extension(filename))) + if (!check_extensions(streamFile,"g1l")) goto fail; - /* check header */ - if ((uint32_t)read_32bitBE(0, streamFile) != 0x47314C5F) /* "G1L_" */ - goto fail; - if ((uint32_t)read_32bitBE(0x1c, streamFile) != 0x57696942) /* "WiiB" */ + if ((read_32bitBE(0x0, streamFile) != 0x47314C5F /* "G1L_" (BE) */ + || read_32bitBE(0x0, streamFile) != 0x5F4C3147) /* "_L1G" (LE) */ + && read_32bitBE(0x4, streamFile) != 0x30303030) /* "0000" (version?) */ goto fail; - /* check type details */ - if (read_32bitBE(0x30, streamFile) > 0) - loop_flag = 1; - else - loop_flag = 0; - channel_count = read_8bit(0x3f, streamFile); - - - coding_type = coding_NGC_DSP; - - - if (channel_count < 1) goto fail; - - /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitBE(0x2c, streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitBE(0x42, streamFile); - /* channels and loop flag are set by allocate_vgmstream */ - - vgmstream->loop_start_sample = read_32bitBE(0x30, streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - - - vgmstream->coding_type = coding_type; - if (channel_count == 1) - vgmstream->layout_type = layout_none; - - vgmstream->layout_type = layout_interleave_byte; - - vgmstream->meta_type = meta_G1L; - - vgmstream->interleave_block_size = 0x1; - - if (vgmstream->coding_type == coding_NGC_DSP) { - off_t coef_offset = 0x78; - - int i, j; - int coef_spacing = 0x60; - - for (j = 0; jchannels; j++) { - for (i = 0; i<16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_offset + j*coef_spacing + i * 2, streamFile); - } - } - - start_offset = 0x81c; + if (read_32bitBE(0x0, streamFile) == 0x47314C5F ) { + read_32bit = read_32bitBE; + } else { + read_32bit = read_32bitLE; } -#ifdef VGM_USE_MAIATRAC3PLUS - else if (vgmstream->coding_type == coding_AT3plus) { - start_offset = 0xc4; - } -#endif - else - goto fail; + /* 0x08 filesize */ + /* 0x0c first file offset (same as 0x18) */ + type = read_32bit(0x10,streamFile); + num_streams = read_32bit(0x14,streamFile); + if (target_stream < 0 || target_stream > num_streams) goto fail; + if (target_stream==0) target_stream = 1; + stream_offset = read_32bit(0x18 + 0x4*(target_stream-1),streamFile); + /* filesize = stream_offset - stream_next_offset*/ + switch(type) { /* type may not be correct */ + case 0x09: /* DSP (WiiBGM) from Hyrule Warriors (Wii U) */ + vgmstream = init_vgmstream_kt_wiibgm_offset(streamFile, stream_offset); + break; + case 0x01: /* ATRAC3plus (RIFF) from One Piece Pirate Warriors 2 (PS3) */ + case 0x00: /* OGG (KOVS) from Romance Three Kindgoms 13 (PC)*/ + case 0x0A: /* OGG (KOVS) from Dragon Quest Heroes (PC)*/ + default: + goto fail; + } - /* open the file for reading by each channel */ - { - int i; - for (i = 0; ilayout_type == layout_interleave_shortblock) - vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, - vgmstream->interleave_block_size); - else if (vgmstream->layout_type == layout_interleave) - vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, - STREAMFILE_DEFAULT_BUFFER_SIZE); - else - vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, - 0x1000); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset = - vgmstream->ch[i].offset = - start_offset + i*vgmstream->interleave_block_size; - } - } return vgmstream; - - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } + +/* Koei Tecmo "WiiBGM" DSP format - found in Hyrule Warriors, Romance of the Three Kingdoms 12 */ +VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE *streamFile) { + return init_vgmstream_kt_wiibgm_offset(streamFile, 0x0); +} + +static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t offset) { + VGMSTREAM * vgmstream = NULL; + int loop_flag, channel_count; + off_t start_offset; + + if (!check_extensions(streamFile,"g1l,dsp")) + goto fail; + + if (read_32bitBE(offset+0x0, streamFile) != 0x57696942 && /* "WiiB" */ + read_32bitBE(offset+0x4, streamFile) != 0x474D0000) /* "GM\0\0" */ + goto fail; + + /* check type details */ + loop_flag = read_32bitBE(offset+0x14, streamFile) > 0; + channel_count = read_8bit(offset+0x23, streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(offset+0x10, streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(offset+0x26, streamFile); + vgmstream->loop_start_sample = read_32bitBE(offset+0x14, streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave_byte; + vgmstream->meta_type = meta_KT_WIIBGM; + + vgmstream->interleave_block_size = 0x1; + + dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60); + start_offset = offset+0x800; + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + + fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/genh.c b/Frameworks/vgmstream/vgmstream/src/meta/genh.c index a72654857..3f7cefd8d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/genh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/genh.c @@ -215,7 +215,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { vgmstream->layout_type = layout_none; break; case coding_NGC_DTK: - vgmstream->layout_type = layout_dtk_interleave; + vgmstream->layout_type = layout_none; break; case coding_NGC_DSP: if (dsp_interleave_type == 0) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c b/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c index dba787108..d4c06d449 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c @@ -1,112 +1,145 @@ #include "meta.h" #include "../layout/layout.h" -#include "../util.h" +#include "../coding/coding.h" -/* GSP+GSB - 2008-11-28 - manakoAT -Super Swing Golf 1 & 2 (WII) */ +/* GSP+GSB - from Tecmo's Super Swing Golf 1 & 2 (WII), Quantum Theory (PS3/X360) */ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; STREAMFILE * streamFileGSP = NULL; - char filename[PATH_LIMIT]; - char filenameGSP[PATH_LIMIT]; - int channel_count; - int loop_flag; - int header_len; - int i; - off_t coef1_start; - off_t coef2_start; - off_t start_offset; + int loop_flag, channel_count; + off_t start_offset, chunk_offset, first_offset; + size_t datasize; + int codec_id; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("gsb",filename_extension(filename))) goto fail; + /* check extensions */ + if (!check_extensions(streamFile,"gsb")) + goto fail; - - strcpy(filenameGSP,filename); - strcpy(filenameGSP+strlen(filenameGSP)-3,"gsp"); - - streamFileGSP = streamFile->open(streamFile,filenameGSP,STREAMFILE_DEFAULT_BUFFER_SIZE); + streamFileGSP = open_stream_ext(streamFile, "gsp"); if (!streamFileGSP) goto fail; /* check header */ if (read_32bitBE(0x00,streamFileGSP) != 0x47534E44) /* "GSND" */ goto fail; + /* 0x04: version?, 0x08: 1?, 0x0c: 0?, */ + first_offset = read_32bitBE(0x10,streamFileGSP); /* usually 0x14*/ + + if (!find_chunk_be(streamFileGSP, 0x44415441,first_offset,1, &chunk_offset,NULL)) goto fail; /*"DATA"*/ + channel_count = read_16bitBE(chunk_offset+0x0e,streamFileGSP); + if (!find_chunk_be(streamFileGSP, 0x42534943,first_offset,1, &chunk_offset,NULL)) goto fail; /*"BSIC"*/ + loop_flag = read_8bit(chunk_offset+0x0c,streamFileGSP); - channel_count = (uint16_t)read_16bitBE(0x3A,streamFileGSP); - loop_flag = (read_32bitBE(0x64,streamFileGSP) != 0xFFFFFFFF); - header_len = read_32bitBE(0x1C,streamFileGSP); - - coef1_start = header_len-0x4C; - coef2_start = header_len-0x1C; - /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x34,streamFileGSP); - vgmstream->coding_type = coding_NGC_DSP; - if(loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x64,streamFileGSP); - vgmstream->loop_end_sample = read_32bitBE(0x68,streamFileGSP); - } - if (channel_count == 1) { - vgmstream->layout_type = layout_gsb_blocked; - } else if (channel_count > 1) { - vgmstream->layout_type = layout_gsb_blocked; - vgmstream->interleave_block_size = read_32bitBE(header_len-0x64,streamFileGSP); - } + if (!find_chunk_be(streamFileGSP, 0x48454144,first_offset,1, &chunk_offset,NULL)) goto fail; /*"HEAD"*/ + /* 0x00: header_size, 0x04: num_chunks */ - vgmstream->meta_type = meta_GSP_GSB; - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); - - if (!vgmstream->ch[i].streamfile) goto fail; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; - } - } + if (!find_chunk_be(streamFileGSP, 0x44415441,first_offset,1, &chunk_offset,NULL)) goto fail; /*"DATA"*/ + /* 0x00: filesize, 0x0c: always 10?, 0x10: always 0?, 0x18: always 0? */ + datasize = read_32bitBE(chunk_offset+0x00,streamFileGSP); + codec_id = read_32bitBE(chunk_offset+0x04,streamFileGSP); + vgmstream->sample_rate = read_32bitBE(chunk_offset+0x08,streamFileGSP); + vgmstream->channels = channel_count; /* 0x0e */ + vgmstream->num_samples = read_32bitBE(chunk_offset+0x14,streamFileGSP); + /* 0x1c: unk (varies with codec_id) */ - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFileGSP); - } - if (vgmstream->channels == 2) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFileGSP); - } - } - } + if (!find_chunk_be(streamFileGSP, 0x42534943,first_offset,1, &chunk_offset,NULL)) goto fail; /*"BSIC"*/ + /* 0x00+: probably volume/pan/etc */ + vgmstream->loop_start_sample = read_32bitBE(chunk_offset+0x10,streamFileGSP); + vgmstream->loop_end_sample = read_32bitBE(chunk_offset+0x14,streamFileGSP); + + //if (!find_chunk_be(streamFileGSP, 0x4E414D45,first_offset,1, &chunk_offset,NULL)) goto fail; /*"NAME"*/ + /* 0x00: name_size, 0x04+: name*/ - /* Calc num_samples */ start_offset = 0x0; - gsb_block_update(start_offset,vgmstream); - vgmstream->num_samples=0; - do { - - vgmstream->num_samples += vgmstream->current_block_size*14/8; - gsb_block_update(vgmstream->next_block_offset,vgmstream); - } while (vgmstream->next_block_offsetcoding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_gsb_blocked; - close_streamfile(streamFileGSP); streamFileGSP=NULL; + if (!find_chunk_be(streamFileGSP, 0x47434558,first_offset,1, &chunk_offset,NULL)) goto fail; /*"GCEX"*/ + //vgmstream->current_block_size = read_32bitBE(chunk_offset+0x00,streamFileGSP); + block_header_size = read_32bitBE(chunk_offset+0x04,streamFileGSP); + num_blocks = read_32bitBE(chunk_offset+0x08,streamFileGSP); + vgmstream->num_samples = (datasize - block_header_size * num_blocks) / 8 / vgmstream->channels * 14; + /* 0x0c+: unk */ + + dsp_read_coefs_be(vgmstream, streamFileGSP, chunk_offset+0x18, 0x30); + break; + } +#ifdef VGM_USE_FFMPEG + case 8: { /* ATRAC3 */ + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[100]; + int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples; + + block_size = 0x98 * vgmstream->channels; + joint_stereo = 0; + max_samples = (datasize / block_size) * 1024; + encoder_delay = max_samples - vgmstream->num_samples; /* todo guessed */ + + vgmstream->num_samples += encoder_delay; + /* make a fake riff so FFmpeg can parse the ATRAC3 */ + bytes = ffmpeg_make_riff_atrac3(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay); + if (bytes <= 0) + goto fail; + + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->loop_start_sample = (vgmstream->loop_start_sample / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize; + vgmstream->loop_end_sample = (vgmstream->loop_end_sample / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize; + + break; + } + + case 9: { /* XMA2 */ + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[200]; + int32_t bytes; + + if (!find_chunk_be(streamFileGSP, 0x584D4558,first_offset,1, &chunk_offset,NULL)) goto fail; /*"XMEX"*/ + /* 0x00: fmt0x166 header (BE), 0x34: seek table */ + + bytes = ffmpeg_make_riff_xma2_from_fmt(buf,200, chunk_offset,0x34, datasize, streamFileGSP, 1); + if (bytes <= 0) goto fail; + + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + break; + } +#endif + default: + goto fail; + } + vgmstream->meta_type = meta_GSP_GSB; + + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + + close_streamfile(streamFileGSP); return vgmstream; - - /* clean up anything we may have opened */ fail: if (streamFileGSP) close_streamfile(streamFileGSP); - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mca.c b/Frameworks/vgmstream/vgmstream/src/meta/mca.c index 518dd16b7..42ec643cb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mca.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mca.c @@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_mca(STREAMFILE *streamFile) { int channel_count; int loop_flag; int version; - size_t head_size, data_size; + size_t head_size, data_size, file_size; off_t start_offset, coef_offset, coef_start, coef_shift; int i, j; int coef_spacing; @@ -78,6 +78,16 @@ VGMSTREAM * init_vgmstream_mca(STREAMFILE *streamFile) { coef_offset = coef_start + coef_shift * 0x14; } + /* sanity check */ + file_size = get_streamfile_size(streamFile); + + if (start_offset + data_size > file_size) { + if (head_size + data_size > file_size) + goto fail; + + start_offset = file_size - data_size; + } + /* set up ADPCM coefs */ for (j = 0; jchannels; j++) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 43cd1c693..c9f25671c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -102,21 +102,24 @@ typedef struct { meta_t meta_type; layout_t layout_type; - // XOR setup with a single byte (SCD) - unsigned char scd_xor; - off_t scd_xor_len; + /* XOR setup (SCD) */ + int decryption_enabled; + void (*decryption_callback)(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read); + uint8_t scd_xor; + off_t scd_xor_length; + } vgm_vorbis_info_t; VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf); VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile); +#endif VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_hca_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size); #ifdef VGM_USE_FFMPEG -ffmpeg_codec_data * init_ffmpeg_faux_riff(STREAMFILE *streamFile, int64_t fmt_offset, uint64_t stream_offset, uint64_t stream_size, int fmt_big_endian); ffmpeg_codec_data * init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size); ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size); @@ -138,7 +141,6 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile); #endif VGMSTREAM * init_vgmstream_sfl(STREAMFILE * streamFile); -#endif VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile); @@ -182,18 +184,12 @@ VGMSTREAM * init_vgmstream_aus(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_rws(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_fsb1(STREAMFILE * streamFile); - -VGMSTREAM * init_vgmstream_fsb3(STREAMFILE * streamFile); - -VGMSTREAM * init_vgmstream_fsb4(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_fsb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_fsb5(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_fsb_mpeg(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_rwx(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_xwb(STREAMFILE * streamFile); @@ -606,7 +602,7 @@ VGMSTREAM * init_vgmstream_ps2_strlr(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps3_vawx(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_vawx(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pc_snds(STREAMFILE* streamFile); @@ -654,7 +650,8 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_bfwav(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_g1l(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE* streamFile); +VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_mca(STREAMFILE* streamFile); @@ -666,4 +663,8 @@ VGMSTREAM * init_vgmstream_ps2_svag_snk(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_xma(STREAMFILE* streamFile); #endif -#endif +VGMSTREAM * init_vgmstream_ps2_vds_vdm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE* streamFile); + +#endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mp4.c b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c index 4a6097e6c..3ea6b8c53 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mp4.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c @@ -58,7 +58,7 @@ int mp4_file_close( void* handle ) return 0; } -MP4FileProvider mp4_file_provider = { mp4_file_open, mp4_file_seek, mp4_file_get_size, mp4_file_read, mp4_file_write, mp4_file_close }; +MP4FileProvider mp4_file_provider = { mp4_file_open, mp4_file_seek, mp4_file_read, mp4_file_write, mp4_file_close, mp4_file_get_size }; #ifdef VGM_USE_FDKAAC VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_adpdtk.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_adpdtk.c index 613ffcfe2..214ac2ac4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_adpdtk.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_adpdtk.c @@ -29,7 +29,7 @@ VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile) { vgmstream->num_samples = file_size/32*28; vgmstream->sample_rate = 48000; vgmstream->coding_type = coding_NGC_DTK; - vgmstream->layout_type = layout_dtk_interleave; + vgmstream->layout_type = layout_none; vgmstream->meta_type = meta_NGC_ADPDTK; /* locality is such that two streamfiles is silly */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c index 5693e0bef..f90501f07 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c @@ -597,27 +597,26 @@ fail: return NULL; } -/* 3DS IDSP two standard DSP headers (SSB4) */ +/* IDSP with multiple standard DSP headers - from SSB4 (3DS), Tekken Tag Tournament 2 (Wii U) */ +#define MULTI_IDSP_MAX_CHANNELS 8 VGMSTREAM * init_vgmstream_3ds_idsp(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t idsp_offset = 0; + off_t idsp_offset = 0; off_t start_offset; off_t interleave; - struct dsp_header ch0_header,ch1_header; - int i; + struct dsp_header ch_headers[MULTI_IDSP_MAX_CHANNELS]; + int i, ch; int channel_count; /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - //if (strcasecmp("idsp",filename_extension(filename))) goto fail; + //if (check_extensions(streamFile,"idsp")) goto fail; /* check header magic */ - if( read_32bitBE(0x0,streamFile) != 0x49445350 ) + if( read_32bitBE(0x0,streamFile) != 0x49445350 ) /* "IDSP" */ { - /* check header magic */ + /* try NUS3 format instead */ if (read_32bitBE(0,streamFile) != 0x4E555333) goto fail; /* "NUS3" */ /* Header size */ @@ -630,106 +629,87 @@ VGMSTREAM * init_vgmstream_3ds_idsp(STREAMFILE *streamFile) { idsp_offset += read_32bitLE( 0x3C, streamFile ) + 8; idsp_offset += read_32bitLE( 0x44, streamFile ) + 8; idsp_offset += 8; + + /* check magic */ + if (read_32bitBE(idsp_offset,streamFile) != 0x49445350) goto fail; /* "IDSP" */ } - /* check magic */ - if (read_32bitBE(idsp_offset,streamFile) != 0x49445350) goto fail; /* "IDSP" */ - channel_count = read_32bitBE(idsp_offset+0x8, streamFile); - if(channel_count != 2 && channel_count != 1) goto fail; - - if (read_dsp_header(&ch0_header, idsp_offset+0x40, streamFile)) goto fail; - if (channel_count == 2 && read_dsp_header(&ch1_header, idsp_offset+0xa0, streamFile)) goto fail; - + if (channel_count > MULTI_IDSP_MAX_CHANNELS) goto fail; + start_offset = read_32bitBE(idsp_offset+0x28,streamFile) + idsp_offset; - interleave = 16; + interleave = 0x10; - /* check initial predictor/scale */ - if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) - goto fail; - if (channel_count == 2 && ch1_header.initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) - goto fail; + /* read standard dsp header per channel and do some validations */ + for (ch=0; ch < channel_count; ch++) { + /* read 0x60 header per channel */ + if (read_dsp_header(&ch_headers[ch], idsp_offset + 0x40 + 0x60*ch, streamFile)) goto fail; - /* check type==0 and gain==0 */ - if (ch0_header.format || ch0_header.gain || - (channel_count == 2 &&(ch1_header.format || ch1_header.gain))) - goto fail; + /* check initial values */ + if (ch_headers[ch].initial_ps != (uint8_t)read_8bit(start_offset + interleave*ch, streamFile)) goto fail; + if (ch_headers[ch].format || ch_headers[ch].gain) goto fail; - /* check for agreement */ - if ( channel_count == 2 &&( - ch0_header.sample_count != ch1_header.sample_count || - ch0_header.nibble_count != ch1_header.nibble_count || - ch0_header.sample_rate != ch1_header.sample_rate || - ch0_header.sample_rate != read_32bitBE(idsp_offset+0xc, streamFile) || - ch0_header.loop_flag != ch1_header.loop_flag || - ch0_header.loop_start_offset != ch1_header.loop_start_offset || - ch0_header.loop_end_offset != ch1_header.loop_end_offset + /* check for agreement with prev channel*/ + if (ch > 0 && ( + ch_headers[ch].sample_count != ch_headers[ch-1].sample_count || + ch_headers[ch].nibble_count != ch_headers[ch-1].nibble_count || + ch_headers[ch].sample_rate != ch_headers[ch-1].sample_rate || + ch_headers[ch].loop_flag != ch_headers[ch-1].loop_flag || + ch_headers[ch].loop_start_offset != ch_headers[ch-1].loop_start_offset || + ch_headers[ch].loop_end_offset != ch_headers[ch-1].loop_end_offset )) goto fail; - if (ch0_header.loop_flag) { - off_t loop_off; + +#if 0 //this is wrong for >2ch and will fail /* check loop predictor/scale */ - loop_off = ch0_header.loop_start_offset/8/channel_count*8; - loop_off = (loop_off/interleave*interleave*channel_count) + (loop_off%interleave); - if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) - goto fail; - if (channel_count == 2 && - ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) - goto fail; + if (ch_headers[ch].loop_flag) { + off_t loop_off; + loop_off = ch_headers[ch].loop_start_offset / 8 / channel_count * 8; + loop_off = (loop_off / interleave * interleave * channel_count) + (loop_off%interleave); + VGM_LOG("loop_ps=%lx, loop_off=%lx\n", ch_headers[ch].loop_ps, loop_off); + if (ch_headers[ch].loop_ps != (uint8_t)read_8bit(start_offset + loop_off + interleave*ch, streamFile)) goto fail; + } +#endif } + /* check first channel (implicitly all ch) agree with main sample rate */ + if (ch_headers[0].sample_rate != read_32bitBE(idsp_offset+0xc, streamFile)) goto fail; + /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag); + vgmstream = allocate_vgmstream(channel_count,ch_headers[0].loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->num_samples = ch0_header.sample_count; - vgmstream->sample_rate = ch0_header.sample_rate; + vgmstream->num_samples = ch_headers[0].sample_count; + vgmstream->sample_rate = ch_headers[0].sample_rate; /* TODO: adjust for interleave? */ - vgmstream->loop_start_sample = dsp_nibbles_to_samples( - ch0_header.loop_start_offset); - vgmstream->loop_end_sample = dsp_nibbles_to_samples( - ch0_header.loop_end_offset)+1; + vgmstream->loop_start_sample = dsp_nibbles_to_samples(ch_headers[0].loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch_headers[0].loop_end_offset) + 1; vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = channel_count == 2 ? layout_interleave : layout_none; + vgmstream->layout_type = channel_count > 1 ? layout_interleave : layout_none; vgmstream->interleave_block_size = interleave; vgmstream->meta_type = meta_3DS_IDSP; - /* coeffs */ - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; - if (channel_count == 2) - vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; - } - - /* initial history */ - /* always 0 that I've ever seen, but for completeness... */ - vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; - vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; - vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - - if (channel_count == 2) { - vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; - vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; - vgmstream->ch[1].streamfile = vgmstream->ch[0].streamfile; + /* set DSP coefs/history */ + for (ch=0; ch < channel_count; ch++) { + for (i=0;i<16;i++) { + vgmstream->ch[ch].adpcm_coef[i] = ch_headers[ch].coef[i]; + } + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[ch].adpcm_history1_16 = ch_headers[ch].initial_hist1; + vgmstream->ch[ch].adpcm_history2_16 = ch_headers[ch].initial_hist2; } - if (!vgmstream->ch[0].streamfile) goto fail; /* open the file for reading */ - for (i=0;ich[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+i*interleave; - } + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; return vgmstream; fail: - /* clean up anything we may have opened */ - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } @@ -2686,9 +2666,9 @@ VGMSTREAM * init_vgmstream_ngc_dsp_csmp(STREAMFILE *streamFile) { goto fail; if (header.loop_flag) { - off_t loop_off; +// off_t loop_off; /* check loop predictor/scale */ - loop_off = header.loop_start_offset/16*8; +// loop_off = header.loop_start_offset/16*8; /* Retro doesn't seem to abide by this */ // if (header.loop_ps != (uint8_t)read_8bit(current_offset + start_offset+loop_off,streamFile)) // goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_file.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_file.c index d29127f76..43648559f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_file.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_file.c @@ -92,14 +92,9 @@ static size_t read_func_scd(void *ptr, size_t size, size_t nmemb, void * datasou items_read = bytes_read / size; - /* first bytes are xor'd with a constant byte */ - if (ov_streamfile->offset < ov_streamfile->scd_xor_len) { - int num_crypt = ov_streamfile->scd_xor_len-ov_streamfile->offset; - int i; - - if (num_crypt > bytes_read) num_crypt=bytes_read; - for (i=0;iscd_xor; + /* may be encrypted */ + if (ov_streamfile->decryption_enabled) { + ov_streamfile->decryption_callback(ptr, size, nmemb, ov_streamfile, bytes_read); } ov_streamfile->offset += items_read * size; @@ -238,13 +233,13 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { callbacks.tell_func = tell_func; if (um3_ogg) { - inf.meta_type = meta_um3_ogg; + inf.meta_type = meta_OGG_UM3; } else if (kovs_ogg) { - inf.meta_type = meta_KOVS_ogg; + inf.meta_type = meta_OGG_KOVS; } else if (psych_ogg) { - inf.meta_type = meta_psych_ogg; + inf.meta_type = meta_OGG_PSYCH; } else { - inf.meta_type = meta_ogg_vorbis; + inf.meta_type = meta_OGG_VORBIS; } inf.layout_type = layout_ogg_vorbis; @@ -281,7 +276,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch default_callbacks.close_func = close_func; default_callbacks.tell_func = tell_func; - if (vgm_inf->scd_xor != 0) { + if (vgm_inf->decryption_enabled) { default_callbacks.read_func = read_func_scd; } @@ -292,8 +287,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch temp_streamfile.offset = 0; temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile); temp_streamfile.other_header_bytes = other_header_bytes; - temp_streamfile.scd_xor = vgm_inf->scd_xor; - temp_streamfile.scd_xor_len = vgm_inf->scd_xor_len; + temp_streamfile.decryption_enabled = vgm_inf->decryption_enabled; + temp_streamfile.decryption_callback = vgm_inf->decryption_callback; + temp_streamfile.scd_xor = vgm_inf->scd_xor; + temp_streamfile.scd_xor_length = vgm_inf->scd_xor_length; /* can we open this as a proper ogg vorbis file? */ memset(&temp_ovf, 0, sizeof(temp_ovf)); @@ -314,8 +311,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch data->ov_streamfile.offset = 0; data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile); data->ov_streamfile.other_header_bytes = other_header_bytes; - data->ov_streamfile.scd_xor = vgm_inf->scd_xor; - data->ov_streamfile.scd_xor_len = vgm_inf->scd_xor_len; + data->ov_streamfile.decryption_enabled = vgm_inf->decryption_enabled; + data->ov_streamfile.decryption_callback = vgm_inf->decryption_callback; + data->ov_streamfile.scd_xor = vgm_inf->scd_xor; + data->ov_streamfile.scd_xor_length = vgm_inf->scd_xor_length; /* open the ogg vorbis file for real */ if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2.c new file mode 100644 index 000000000..dd29f9c87 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2.c @@ -0,0 +1,48 @@ +#include "meta.h" + +/* VDS/VDM - from Grafitti Kingdom / Rakugaki Oukoku 2 */ +VGMSTREAM * init_vgmstream_ps2_vds_vdm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + + /* check extension, case insensitive */ + if ( !check_extensions(streamFile,"vds,vdm")) + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x56445320 && /* "VDS " (music)*/ + read_32bitBE(0x00,streamFile) != 0x56444D20) /* "VDM " (voices) */ + goto fail; + + loop_flag = read_8bit(0x20,streamFile); + channel_count = read_32bitLE(0x10,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = channel_count > 1 ? layout_interleave : layout_none; + vgmstream->meta_type = meta_PS2_VDS_VDM; + + start_offset = 0x800; + vgmstream->num_samples = read_32bitLE(0x04,streamFile) * 28 / 16 / channel_count; + /* 0x08: unknown, always 10 */ + vgmstream->sample_rate = read_32bitLE(0x0c,streamFile); + vgmstream->channels = channel_count; /*0x10*/ + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); + vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile) - start_offset) * 28 / 16 / channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x1c,streamFile) - start_offset) * 28 / 16 / channel_count; + vgmstream->loop_flag = loop_flag; /*0x20*/ + /*0x21: volume? */ + /*0x22: pan? */ + /*0x23: 02=VDS 04=VDM? */ + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_bmdx.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_bmdx.c index dc0e93093..a1e735af3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_bmdx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_bmdx.c @@ -33,7 +33,7 @@ VGMSTREAM * init_vgmstream_ps2_bmdx(STREAMFILE *streamFile) { /* Check for Compression Scheme */ if (read_32bitLE(0x20,streamFile) == 1) - vgmstream->coding_type = coding_invert_PSX; + vgmstream->coding_type = coding_PSX_bmdx; else vgmstream->coding_type = coding_PSX; vgmstream->num_samples = read_32bitLE(0x0c,streamFile)*28/16/channel_count; @@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_ps2_bmdx(STREAMFILE *streamFile) { start_offset = read_32bitLE(0x08,streamFile); - if (vgmstream->coding_type == coding_invert_PSX) + if (vgmstream->coding_type == coding_PSX_bmdx) { uint8_t xor = read_8bit(start_offset,streamFile); uint8_t add = (~(uint8_t)read_8bit(start_offset+2,streamFile))+1; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mib.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mib.c index a461fb7eb..3e4fff1f8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mib.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mib.c @@ -91,6 +91,8 @@ VGMSTREAM * init_vgmstream_ps2_mib(STREAMFILE *streamFile) { fileLength = get_streamfile_size(streamFile); readOffset+=(off_t)read_streamfile(mibBuffer,0,0x10,streamFile); + readOffset=0; + mibBuffer[0]=0; do { readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); @@ -106,6 +108,7 @@ VGMSTREAM * init_vgmstream_ps2_mib(STREAMFILE *streamFile) { bDoUpdateInterleave=1; } + testBuffer[0]=0; if(!memcmp(testBuffer,mibBuffer,0x10)) { gotEmptyLine=1; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c index 9bad95cac..d37ee6c12 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c @@ -1,8 +1,9 @@ #include "meta.h" #include "../util.h" -/* Sony .ADS with SShd & SSbd Headers */ - +/* NPFS - found in Namco PS2/PSP games: + * Tekken 5, Ace Combat 5, Yumeria, Venus & Braves (.nps), Ridge Racer PSP, etc + */ VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; @@ -14,7 +15,9 @@ VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile) { /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("npsf",filename_extension(filename))) goto fail; + if (strcasecmp("npsf",filename_extension(filename)) && + strcasecmp("nps",filename_extension(filename))) + goto fail; /* check NPSF Header */ if (read_32bitBE(0x00,streamFile) != 0x4E505346) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c index 7ca91519b..6f7b7eba1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c @@ -1,5 +1,4 @@ #include "meta.h" -#include "../util.h" static int vag_find_loop_offsets(STREAMFILE *streamFile, off_t start_offset, off_t * loop_start, off_t * loop_end); @@ -9,39 +8,39 @@ static int vag_find_loop_offsets(STREAMFILE *streamFile, off_t start_offset, off */ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - off_t loopStart = 0; - off_t loopEnd = 0; + off_t start_offset, loopStart = 0, loopEnd = 0; uint8_t vagID; uint32_t version = 0; - size_t filesize = 0, datasize = 0; - size_t interleave; - off_t start_offset; - - int loop_flag=0; - int loop_samples_found = 0; - int channel_count=0; - int i; + size_t filesize = 0, datasize = 0, interleave; + + int loop_flag = 0, loop_samples_found = 0; + int channel_count = 0; + int is_swag = 0; /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("vag",filename_extension(filename))) goto fail; + if ( !check_extensions(streamFile,"vag,swag") ) + goto fail; /* check VAG Header */ - if (((read_32bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700) && /* "VAG\0" */ + if (((read_32bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700) && /* "VAG" */ ((read_32bitLE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700)) goto fail; + /* Frantix VAGp .swag: some (not all) fields in LE + 2 VAGp in the same file (full interleave) */ + is_swag = check_extensions(streamFile,"swag"); + filesize = get_streamfile_size(streamFile); /* version used to create the file * ex: 00000000 = v1.8 PC, 00000002 = v1.3 Mac, 00000003 = v1.6+ Mac, 00000020 = v2.0+ PC */ version = read_32bitBE(0x04,streamFile); /* 0x08-0c: reserved */ - datasize = read_32bitBE(0x0c,streamFile); + if (is_swag) + datasize = read_32bitLE(0x0c,streamFile); + else + datasize = read_32bitBE(0x0c,streamFile); /* 0x14-20 reserved */ /* 0x20-30: name (optional) */ /* 0x30: data start (first 0x10 usually 0s to init SPU) */ @@ -66,8 +65,11 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { break; case 'p': /* "VAGp" (extended) [most common, ex Ratchet & Clank] */ - if ((version <= 0x00000004) && (datasize < filesize / 2)) { - loop_flag=(read_32bitBE(0x14,streamFile)!=0); + if ((version <= 0x00000004) && (datasize < filesize / 2)) { /* two VAGp in the same file */ + if (is_swag) + loop_flag = vag_find_loop_offsets(streamFile, 0x30, &loopStart, &loopEnd); + else + loop_flag = read_32bitBE(0x14,streamFile) != 0; channel_count=2; } else if (version == 0x00020001) { /* HEVAG */ @@ -91,7 +93,10 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { /* fill in the vital statistics */ vgmstream->coding_type = coding_PSX; - vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + if (is_swag) + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + else + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); switch(vagID) { case '1': // VAG1 @@ -121,23 +126,31 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { if ((version == 0x00000004) && (datasize < filesize / 2)) { vgmstream->channels=2; - vgmstream->num_samples = datasize; /* todo test if datasize/16*28? */ - - if(loop_flag) { - vgmstream->loop_start_sample=read_32bitBE(0x14,streamFile); - vgmstream->loop_end_sample =read_32bitBE(0x18,streamFile); - loop_samples_found = 1; - } - - start_offset=0x80; vgmstream->layout_type=layout_interleave; vgmstream->meta_type=meta_PS2_VAGs; - // Double VAG Header @ 0x0000 & 0x1000 - if(read_32bitBE(0,streamFile)==read_32bitBE(0x1000,streamFile)) { + if (is_swag) { + start_offset = 0x30; + interleave = datasize; vgmstream->num_samples = datasize / 16 * 28; - interleave=0x1000; - start_offset=0; + vgmstream->loop_start_sample = (loopStart-start_offset) / 16 * 28; + vgmstream->loop_end_sample = (loopEnd-start_offset) / 16 * 28; + loop_samples_found = 1; + + } else { + start_offset=0x80; + vgmstream->num_samples = datasize; /* todo test if datasize/16*28? */ + if(loop_flag) { + vgmstream->loop_start_sample=read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample =read_32bitBE(0x18,streamFile); + loop_samples_found = 1; + // Double VAG Header @ 0x0000 & 0x1000 + if(read_32bitBE(0,streamFile)==read_32bitBE(0x1000,streamFile)) { + vgmstream->num_samples = datasize / 16 * 28; + interleave=0x1000; + start_offset=0; + } + } } } else if (version == 0x40000000) { /* Guerilla VAG (little endian) */ @@ -150,7 +163,7 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { start_offset = 0x30; } else if (version == 0x00020001) { /* HEVAG */ - vgmstream->coding_type = coding_HEVAG_ADPCM; + vgmstream->coding_type = coding_HEVAG; vgmstream->layout_type = layout_interleave; vgmstream->meta_type = meta_PS2_VAGs; @@ -195,28 +208,14 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { } - /* open the file for reading by each channel */ - { - for (i=0;iinterleave_block_size > 0) { - vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); - } else { - vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - } - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset= - (off_t)(start_offset+vgmstream->interleave_block_size*i); - } - } + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c index 405138e6e..0951945bb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c @@ -10,8 +10,8 @@ VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE *streamFile) size_t fileLength; off_t readOffset = 0; off_t start_offset; - off_t loop_start_offset; - off_t loop_end_offset; + off_t loop_start_offset = 0; + off_t loop_end_offset = 0; uint8_t testBuffer[0x10]; int loop_flag = 0; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c index 7fbf617b8..169aab643 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c @@ -228,7 +228,7 @@ fail: #ifdef VGM_USE_FFMPEG if (ffmpeg_data) { free_ffmpeg(ffmpeg_data); - vgmstream->codec_data = NULL; + if (vgmstream) vgmstream->codec_data = NULL; } #endif if (vgmstream) close_vgmstream(vgmstream); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_sgh_sgb.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_sgh_sgb.c index ce0ec1064..164a77cb1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_sgh_sgb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_sgh_sgb.c @@ -195,7 +195,7 @@ VGMSTREAM * init_vgmstream_ps3_sgdx(STREAMFILE *streamFile) { } #endif case 0x05: /* Short VAG ADPCM */ - vgmstream->coding_type = coding_SHORT_VAG_ADPCM; + vgmstream->coding_type = coding_PSX_cfg; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x4; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_vawx.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_vawx.c index b9195e82e..28e74922d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps3_vawx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_vawx.c @@ -1,77 +1,124 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* VAWX - - No More Heroes: Heroes Paradise (PS3) -*/ -VGMSTREAM * init_vgmstream_ps3_vawx(STREAMFILE *streamFile) -{ +#define FAKE_RIFF_BUFFER_SIZE 100 + +/** + * VAWX - found in feelplus games: No More Heroes Heroes Paradise, Moon Diver + */ +VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - off_t start_offset; + off_t start_offset, datasize; - int loop_flag = 0; - int channel_count; + int loop_flag = 0, channel_count, type; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("vawx",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x56415758) // "VAWX" + /* check extensions */ + if ( !check_extensions(streamFile, "vawx,xwv") ) goto fail; - if (read_8bit(0xF,streamFile) == 2) - { - loop_flag = 1; - } + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x56415758) /* "VAWX" */ + goto fail; + loop_flag = read_8bit(0x37,streamFile); channel_count = read_8bit(0x39,streamFile);; - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->channels = channel_count; + /* 0x04: filesize */ + start_offset = 0x800; /* ? read_32bitLE(0x0c,streamFile); */ + vgmstream->channels = channel_count; + /* 0x16: file id */ + type = read_8bit(0x36,streamFile); /* could be at 0x38 too */ + vgmstream->num_samples = read_32bitBE(0x3c,streamFile); vgmstream->sample_rate = read_32bitBE(0x40,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = ((get_streamfile_size(streamFile)-start_offset)/16/channel_count*28); - - if (loop_flag) - { - vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);; - } - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_PS3_VAWX; + vgmstream->meta_type = meta_VAWX; + + switch(type) { + case 2: /* VAG */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + + vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile); + /* todo 6ch has 0x8000 blocks and must skip last 0x20 each block (or, skip 0x20 every 0x1550*6 */ + + break; + +#ifdef VGM_USE_FFMPEG + case 1: { /* XMA2 */ + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[FAKE_RIFF_BUFFER_SIZE]; + 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); + if (bytes <= 0) goto fail; + + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile); + + break; + } + + case 7: { /* ATRAC3 */ + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[FAKE_RIFF_BUFFER_SIZE]; + int32_t bytes, block_size, encoder_delay, joint_stereo, max_samples; + + datasize = read_32bitBE(0x54,streamFile); + block_size = 0x98 * vgmstream->channels; + joint_stereo = 0; + max_samples = (datasize / block_size) * 1024; + encoder_delay = 0x0; /* not used by FFmpeg */ + if (vgmstream->num_samples > max_samples) { + 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 */ + 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) + goto fail; + + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->loop_start_sample = (read_32bitBE(0x44,streamFile) / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize; + vgmstream->loop_end_sample = (read_32bitBE(0x48,streamFile) / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize; + + break; + } +#endif + default: + goto fail; + + } + /* 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;ich[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; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 95afa1161..6a41732a7 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -399,14 +399,14 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG case coding_FFmpeg: { - ffmpeg_data = init_ffmpeg_offset(streamFile, 0, streamFile->get_size(streamFile) ); - if ( !ffmpeg_data ) goto fail; - - sample_count = ffmpeg_data->totalSamples; /* fact_sample_count */ - /* the encoder introduces some garbage (usually silent) samples to skip before the stream - * loop values include the skip samples but fact_sample_count doesn't; add them back to fix some edge loops */ - if (fact_sample_skip > 0) - sample_count += fact_sample_skip; + ffmpeg_data = init_ffmpeg_offset(streamFile, 0, streamFile->get_size(streamFile) ); + if ( !ffmpeg_data ) goto fail; + + sample_count = ffmpeg_data->totalSamples; /* fact_sample_count */ + /* the encoder introduces some garbage (usually silent) samples to skip before the stream + * loop values include the skip samples but fact_sample_count doesn't; add them back to fix some edge loops */ + if (fact_sample_skip > 0) + sample_count += fact_sample_skip; } break; #endif @@ -503,7 +503,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { (long long)loop_start_ms*fmt.sample_rate/1000; vgmstream->loop_end_sample = (long long)loop_end_ms*fmt.sample_rate/1000; - vgmstream->meta_type = meta_RIFF_WAVE_labl_Marker; + vgmstream->meta_type = meta_RIFF_WAVE_labl; } else if (loop_start_offset >= 0) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c index 382a465b2..08b89c3a0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c @@ -20,12 +20,40 @@ typedef struct _SCDINTSTREAMFILE static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size); + +/* V3 decryption table found in the .exe */ +static const uint8_t scd_ogg_v3_lookuptable[256] = { /* FF XIV Heavensward */ + 0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F + 0x32, 0x52, 0x16, 0x1B, 0x3C, 0xA1, 0x54, 0x7B, 0x1B, 0x97, 0xA6, 0x93, 0x1A, 0x4B, 0xAA, 0xA6, // 10-1F + 0x7A, 0x7B, 0x1B, 0x97, 0xA6, 0xF7, 0x02, 0xBB, 0xAA, 0xA6, 0xBB, 0xF7, 0x2A, 0x51, 0xBE, 0x03, // 20-2F + 0xF4, 0x2A, 0x51, 0xBE, 0x03, 0xF4, 0x2A, 0x51, 0xBE, 0x12, 0x06, 0x56, 0x27, 0x32, 0x32, 0x36, // 30-3F + 0x32, 0xB2, 0x1A, 0x3B, 0xBC, 0x91, 0xD4, 0x7B, 0x58, 0xFC, 0x0B, 0x55, 0x2A, 0x15, 0xBC, 0x40, // 40-4F + 0x92, 0x0B, 0x5B, 0x7C, 0x0A, 0x95, 0x12, 0x35, 0xB8, 0x63, 0xD2, 0x0B, 0x3B, 0xF0, 0xC7, 0x14, // 50-5F + 0x51, 0x5C, 0x94, 0x86, 0x94, 0x59, 0x5C, 0xFC, 0x1B, 0x17, 0x3A, 0x3F, 0x6B, 0x37, 0x32, 0x32, // 60-6F + 0x30, 0x32, 0x72, 0x7A, 0x13, 0xB7, 0x26, 0x60, 0x7A, 0x13, 0xB7, 0x26, 0x50, 0xBA, 0x13, 0xB4, // 70-7F + 0x2A, 0x50, 0xBA, 0x13, 0xB5, 0x2E, 0x40, 0xFA, 0x13, 0x95, 0xAE, 0x40, 0x38, 0x18, 0x9A, 0x92, // 80-8F + 0xB0, 0x38, 0x00, 0xFA, 0x12, 0xB1, 0x7E, 0x00, 0xDB, 0x96, 0xA1, 0x7C, 0x08, 0xDB, 0x9A, 0x91, // 90-9F + 0xBC, 0x08, 0xD8, 0x1A, 0x86, 0xE2, 0x70, 0x39, 0x1F, 0x86, 0xE0, 0x78, 0x7E, 0x03, 0xE7, 0x64, // A0-AF + 0x51, 0x9C, 0x8F, 0x34, 0x6F, 0x4E, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, // B0-BF + 0x41, 0xFC, 0x3B, 0x70, 0x71, 0x64, 0x33, 0x32, 0x12, 0x32, 0x32, 0x36, 0x70, 0x34, 0x2B, 0x56, // C0-CF + 0x22, 0x70, 0x3A, 0x13, 0xB7, 0x26, 0x60, 0xBA, 0x1B, 0x94, 0xAA, 0x40, 0x38, 0x00, 0xFA, 0xB2, // D0-DF + 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x12, 0x32, 0xB2, 0x32, 0x32, 0x32, 0x32, 0x75, 0xA3, 0x26, 0x7B, // E0-EF + 0x83, 0x26, 0xF9, 0x83, 0x2E, 0xFF, 0xE3, 0x16, 0x7D, 0xC0, 0x1E, 0x63, 0x21, 0x07, 0xE3, 0x01, // F0-FF +}; + +static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read); +static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read); + + + VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - off_t start_offset, meta_offset_offset, meta_offset, post_meta_offset; + off_t start_offset, tables_offset, headers_offset, meta_offset, post_meta_offset, stream_size; + int headers_entries; int32_t loop_start, loop_end; + int target_stream = 1; /* N=Nth stream, 0=auto (first) */ int loop_flag = 0; int channel_count; int codec_id; @@ -42,62 +70,90 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { if (read_32bitBE(0,streamFile) != 0x53454442) goto fail; /* SSCF */ if (read_32bitBE(4,streamFile) != 0x53534346) goto fail; - if (read_32bitBE(8,streamFile) == 2 || - read_32bitBE(8,streamFile) == 3) { - /* version 2 BE, as seen in FFXIII demo for PS3 */ - /* version 3 BE, as seen in FFXIII for PS3 */ + + /** main header section **/ + if (read_32bitBE(8,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */ + read_32bitBE(8,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */ + read_32bit = read_32bitBE; read_16bit = read_16bitBE; //size_offset = 0x14; - meta_offset_offset = 0x40 + read_16bit(0xe,streamFile); - } else if (read_32bitLE(8,streamFile) == 3 || + } else if (read_32bitLE(8,streamFile) == 3 || /* version 2/3 LE, as seen in FFXIV for PC (and others?) */ read_32bitLE(8,streamFile) == 2) { - /* version 2/3 LE, as seen in FFXIV for ?? */ + read_32bit = read_32bitLE; read_16bit = read_16bitLE; //size_offset = 0x10; - meta_offset_offset = 0x40 + read_16bit(0xe,streamFile); } else goto fail; - /* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */ + /* 0xc: probably 00=LE, 01=BE */ + /* 0xd: unk (always 0x04) */ + tables_offset = read_16bit(0xe,streamFile); + #if 0 + /* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */ /* check file size with header value */ if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile)) goto fail; #endif - meta_offset = read_32bit(meta_offset_offset,streamFile); + /** offset tables **/ + /* 0x00: table1_unknown entries */ + /* 0x02: table2_unknown entries */ + /* 0x04: table_headers entries */ + /* 0x06: unknown (varies) */ + /* 0x08: table1_unknown start offset */ + /* 0x0c: table_headers start offset */ + /* 0x10: table2_unknown start offset */ + /* 0x14: unknown (0x0) */ + /* 0x18: unknown offset */ + /* 0x1c: unknown (0x0) */ + headers_entries = read_16bit(tables_offset+0x04,streamFile); + VGM_ASSERT(headers_entries > 1, "SCD: multiple streams found (%i entries)\n", headers_entries); + if (target_stream == 0) target_stream = 1; /* auto: default to 1 */ + if (target_stream > headers_entries) goto fail; + headers_offset = read_32bit(tables_offset+0x0c,streamFile); + + /** header table entries (each is an uint32_t offset to stream header) **/ + meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile); + + /** stream header **/ + stream_size = read_32bit(meta_offset + 0x0, streamFile); + channel_count = read_32bit(meta_offset+4,streamFile); + /* 0x8 sample rate */ + codec_id = read_32bit(meta_offset+0xc,streamFile); - /* check that chunk size equals stream size (?) */ loop_start = read_32bit(meta_offset+0x10,streamFile); loop_end = read_32bit(meta_offset+0x14,streamFile); loop_flag = (loop_end > 0); - channel_count = read_32bit(meta_offset+4,streamFile); - codec_id = read_32bit(meta_offset+0xc,streamFile); - post_meta_offset = meta_offset + 0x20; - - /* data at meta_offset is only 0x20 bytes, but there may be auxiliary chunks - before anything else */ - - aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile); - for (; aux_chunk_count > 0; aux_chunk_count --) - { - /* skip aux chunks */ - /*printf("skipping %08x\n", read_32bitBE(post_meta_offset, streamFile));*/ - post_meta_offset += read_32bit(post_meta_offset+4,streamFile); - } - start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile); + aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile); #ifdef VGM_USE_VORBIS if (codec_id == 0x6) { vgm_vorbis_info_t inf; - uint32_t seek_table_size = read_32bit(post_meta_offset+0x10, streamFile); - uint32_t vorb_header_size = read_32bit(post_meta_offset+0x14, streamFile); + uint32_t seek_table_size; + uint32_t vorb_header_size; VGMSTREAM * result = NULL; + + /* todo this skips the "MARK" chunk for FF XIV "03.scd", but without it actually the start_offset + * lands in a "OggS" though will fail in the "try skipping seek table" + * maybe this isn't needed and there is another bug, since other games with "MARK" don't need this */ + if (aux_chunk_count) { + post_meta_offset = meta_offset + 0x20; + + /* data at meta_offset is only 0x20 bytes, but there may be auxiliary chunks before anything else */ + for (; aux_chunk_count > 0; aux_chunk_count--) { + post_meta_offset += read_32bit(post_meta_offset+4,streamFile); /* skip aux chunks */ + } + start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile); + } + + seek_table_size = read_32bit(post_meta_offset+0x10, streamFile); + vorb_header_size = read_32bit(post_meta_offset+0x14, streamFile); memset(&inf, 0, sizeof(inf)); inf.loop_start = loop_start; @@ -130,18 +186,28 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { // failed with Ogg, try deobfuscating header { // skip chunks before xor_byte - unsigned char xor_byte; - - xor_byte = read_8bit(post_meta_offset+2, streamFile); + uint8_t xor_version, xor_byte; + xor_version = read_8bit(post_meta_offset + 0, streamFile); + xor_byte = read_8bit(post_meta_offset + 2, streamFile); if (xor_byte == 0) { return NULL; } - inf.scd_xor = xor_byte; - inf.scd_xor_len = vorb_header_size; + if (xor_version <= 2) { + inf.decryption_enabled = 1; + inf.decryption_callback = scd_ogg_decrypt_v2_callback; + inf.scd_xor = xor_byte; + inf.scd_xor_length = vorb_header_size; /* header is XOR'ed */ + } else if (xor_version == 3) { + inf.decryption_enabled = 1; + inf.decryption_callback = scd_ogg_decrypt_v3_callback; + inf.scd_xor = stream_size & 0xFF; /* xor_byte is not used? */ + inf.scd_xor_length = stream_size; /* full file is XOR'ed */ + } result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + /* always? */ return result; } } @@ -160,7 +226,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { /* PCM */ vgmstream->coding_type = coding_PCM16LE_int; vgmstream->layout_type = layout_none; - vgmstream->num_samples = read_32bit(meta_offset+0,streamFile) / 2 / channel_count; + vgmstream->num_samples = stream_size / 2 / channel_count; if (loop_flag) { vgmstream->loop_start_sample = loop_start / 2 / channel_count; @@ -175,6 +241,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { struct mpg123_frameinfo mi; coding_t ct; + /* Drakengard 3, some Kingdom Hearts */ if (vgmstream->sample_rate == 47999) vgmstream->sample_rate = 48000; if (vgmstream->sample_rate == 44099) @@ -189,7 +256,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->coding_type = ct; vgmstream->layout_type = layout_mpeg; if (mi.vbr != MPG123_CBR) goto fail; - vgmstream->num_samples = mpeg_bytes_to_samples(read_32bit(meta_offset+0,streamFile), &mi); + vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, &mi); vgmstream->num_samples -= vgmstream->num_samples%576; if (loop_flag) { vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, &mi); @@ -206,14 +273,16 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->coding_type = coding_MSADPCM; vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = read_16bit(post_meta_offset+0xc,streamFile); - vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bit(meta_offset+0,streamFile), vgmstream->interleave_block_size, vgmstream->channels); + vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels); if (loop_flag) { vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels); vgmstream->loop_end_sample = msadpcm_bytes_to_samples(loop_end, vgmstream->interleave_block_size, vgmstream->channels); } break; - case 0xA: + + case 0xA: /* Dragon Quest X (Wii) */ + case 0x15: /* Dragon Quest X (Wii U) (no apparent differences except higher sample rate) */ /* GC/Wii DSP ADPCM */ { STREAMFILE * file; @@ -263,6 +332,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { for (i=0;isubstreams[i] = init_vgmstream_ngc_dsp_std(intfile); data->intfiles[i] = intfile; @@ -282,38 +353,74 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { break; #ifdef VGM_USE_FFMPEG case 0xB: - /* XMA1/XMA2 */ + /* XMA1/XMA2 */ /* Lightning Returns SFX, FFXIII (X360) */ { - uint16_t codec_id = read_16bit(post_meta_offset, streamFile); - if (codec_id == 0x165 || codec_id == 0x166) - { - ffmpeg_codec_data *ffmpeg_data = init_ffmpeg_faux_riff(streamFile, post_meta_offset, start_offset, streamFile->get_size(streamFile) - start_offset, read_32bit == read_32bitBE); - if (!ffmpeg_data) goto fail; - - vgmstream->codec_data = ffmpeg_data; - - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - vgmstream->num_samples = ffmpeg_data->totalSamples; + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[200]; + int32_t bytes; - if (loop_flag) { - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - } - } - else goto fail; + /* post_meta_offset+0x00: fmt0x166 header (BE), post_meta_offset+0x34: seek table */ + + bytes = ffmpeg_make_riff_xma2_from_fmt(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1); + if (bytes <= 0) goto fail; + + ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = ffmpeg_data->totalSamples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; } break; + + case 0xE: + /* ATRAC3plus */ /* Lord of Arcana (PSP) */ + { + ffmpeg_codec_data *ffmpeg_data = NULL; + off_t chunk_offset; + size_t chunk_size, fact_sample_skip = 0; + + /* full riff header at start_offset/post_meta_offset (same) */ + ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = ffmpeg_data->totalSamples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + + /* manually find encoder_delay to adjust samples since it's not properly used by FFmpeg */ + if (!find_chunk_le(streamFile, 0x66616374,start_offset+0xc,0, &chunk_offset,&chunk_size)) goto fail; /*"fact"*/ + if (chunk_size == 0x8) { + fact_sample_skip = read_32bitLE(chunk_offset+0x4, streamFile); + } else if (chunk_size == 0xc) { + fact_sample_skip = read_32bitLE(chunk_offset+0x8, streamFile); + } + vgmstream->num_samples += fact_sample_skip; + vgmstream->loop_start_sample += fact_sample_skip; + vgmstream->loop_end_sample += fact_sample_skip; + } + break; + #endif default: + VGM_LOG("SCD: unknown codec_id 0x%x\n", codec_id); goto fail; } vgmstream->meta_type = meta_SQEX_SCD; /* open the file for reading */ - if (vgmstream->layout_type != layout_scd_int && vgmstream->coding_type != coding_FFmpeg) + if (vgmstream->layout_type != layout_scd_int +#ifdef VGM_USE_FFMPEG + && vgmstream->coding_type != coding_FFmpeg +#endif + ) { int i; STREAMFILE * file; @@ -433,8 +540,13 @@ static size_t read_scdint(SCDINTSTREAMFILE *streamfile, uint8_t *dest, off_t off /* start_offset is for *this* interleaved stream */ static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size) { - SCDINTSTREAMFILE * scd = malloc(sizeof(SCDINTSTREAMFILE)); + SCDINTSTREAMFILE * scd = NULL; + + /* _scdint funcs can't handle this case */ + if (start_offset + total_size > file->get_size(file)) + return NULL; + scd = malloc(sizeof(SCDINTSTREAMFILE)); if (!scd) return NULL; @@ -456,3 +568,43 @@ static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * fi return &scd->sf; } + + +static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read) { + ogg_vorbis_streamfile * ov_streamfile = (ogg_vorbis_streamfile*)datasource; + + /* header is XOR'd with a constant byte */ + if (ov_streamfile->offset < ov_streamfile->scd_xor_length) { + int i, num_crypt; + + num_crypt = ov_streamfile->scd_xor_length - ov_streamfile->offset; + if (num_crypt > bytes_read) + num_crypt = bytes_read; + + for (i = 0; i < num_crypt; i++) { + ((uint8_t*)ptr)[i] ^= (uint8_t)ov_streamfile->scd_xor; + } + } +} + +static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read) { + ogg_vorbis_streamfile *ov_streamfile = (ogg_vorbis_streamfile*)datasource; + + /* file is XOR'd with a table (algorithm and table by Ioncannon) */ + if (ov_streamfile->offset < ov_streamfile->scd_xor_length) { + int i, num_crypt; + uint8_t byte1, byte2, xorByte; + + num_crypt = bytes_read; + byte1 = ov_streamfile->scd_xor & 0x7F; + byte2 = ov_streamfile->scd_xor & 0x3F; + + for (i = 0; i < num_crypt; i++) { + xorByte = scd_ogg_v3_lookuptable[(byte2 + ov_streamfile->offset + i) & 0xFF]; + xorByte &= 0xFF; + xorByte ^= ((uint8_t*)ptr)[i]; + xorByte ^= byte1; + ((uint8_t*)ptr)[i] = (uint8_t)xorByte; + } + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/x360.c b/Frameworks/vgmstream/vgmstream/src/meta/x360.c new file mode 100644 index 000000000..311cdbc95 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/x360.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* CXS - found in Eternal Sonata (Xbox 360) */ +VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count; + + /* check extension, case insensitive */ + if ( !check_extensions(streamFile,"cxs")) + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x43585320) /* "CXS " */ + goto fail; + + loop_flag = read_32bitBE(0x18,streamFile) > 0; + channel_count = read_32bitBE(0x0c,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + start_offset = read_32bitBE(0x04,streamFile) + read_32bitBE(0x28,streamFile); /* assumed, seek table always at 0x800 */ + /* 0x04: data start? */ + vgmstream->sample_rate = read_32bitBE(0x08,streamFile); + vgmstream->channels = channel_count; /*0x0c*/ + vgmstream->num_samples = read_32bitBE(0x10,streamFile) + 576; /*todo add proper encoder_delay*/ + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); + /* 0x1c: below */ + + vgmstream->meta_type = meta_X360_CXS; + +#ifdef VGM_USE_FFMPEG + { + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[100]; + size_t bytes, datasize, block_size, block_count; + + block_count = read_32bitBE(0x1c,streamFile); + block_size = read_32bitBE(0x20,streamFile); + datasize = read_32bitBE(0x24,streamFile); + + bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, 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); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + 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; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xma.c b/Frameworks/vgmstream/vgmstream/src/meta/xma.c index f6e14ea0e..d3974a928 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xma.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xma.c @@ -1,487 +1,487 @@ -#include "meta.h" -#include "../util.h" - -#ifdef VGM_USE_FFMPEG - -#define ADJUST_SAMPLE_RATE 0 -#define XMA_BYTES_PER_PACKET 2048 -#define XMA_SAMPLES_PER_FRAME 512 -#define XMA_SAMPLES_PER_SUBFRAME 128 -#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 */ - - /* info */ - int loop_flag; - int32_t num_samples; - int32_t loop_start_sample; - int32_t loop_end_sample; - - int32_t xma1_loop_start_offset_b; - int32_t xma1_loop_end_offset_b; - int32_t xma1_subframe_data; -} xma_header_data; - - -static int parse_header(xma_header_data * xma, STREAMFILE *streamFile); -static void parse_xma1_sample_data(xma_header_data * xma, STREAMFILE *streamFile); -static int create_riff_header(uint8_t * buf, size_t buf_size, xma_header_data * xma, STREAMFILE *streamFile); -static int fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec); -#if ADJUST_SAMPLE_RATE -static int get_xma_sample_rate(int32_t general_rate); -#endif - -/** - * XMA 1/2 (Microsoft) - * - * Usually in RIFF headers and minor variations. - */ -VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { - char filename[PATH_LIMIT]; - VGMSTREAM * vgmstream = NULL; - ffmpeg_codec_data *data = NULL; - - xma_header_data xma; - uint8_t fake_riff[FAKE_RIFF_BUFFER_SIZE]; - int fake_riff_size = 0; - - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xma",filename_extension(filename)) - && strcasecmp("xma2",filename_extension(filename)) /* Skullgirls */ - && strcasecmp("past",filename_extension(filename)) /* SoulCalibur II HD */ - ) - goto fail; - - /* check header */ - if ( !parse_header(&xma, streamFile) ) - goto fail; - - - /* init ffmpeg (create a fake RIFF that FFmpeg can read if needed) */ - 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 */ - vgmstream = allocate_vgmstream(data->channels, xma.loop_flag); - if (!vgmstream) goto fail; - /*vgmstream->channels = data->channels;*/ - /*vgmstream->loop_flag = loop_flag;*/ - - vgmstream->codec_data = data; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_FFmpeg; - - vgmstream->sample_rate = data->sampleRate; -#if ADJUST_SAMPLE_RATE - vgmstream->sample_rate = get_xma_sample_rate(vgmstream->sample_rate); -#endif - vgmstream->num_samples = xma.num_samples; /* data->totalSamples: XMA1 = not set; XMA2 = not reliable */ - - if (vgmstream->loop_flag) { - vgmstream->loop_start_sample = xma.loop_start_sample; - vgmstream->loop_end_sample = xma.loop_end_sample; - } - - - return vgmstream; - -fail: - /* clean up */ - if (data) { - free_ffmpeg(data); - } - if (vgmstream) { - vgmstream->codec_data = NULL; - close_vgmstream(vgmstream); - } - 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 */ - off_t current_chunk = 0xc; - off_t fmt_offset = 0, xma2_offset = 0; - size_t riff_size = 0, fmt_size = 0, xma2_size = 0; - - riff_size = read_32bit(4,streamFile); - if (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 (Tekken 6, Galaga Legions DX) */ - /* custom header with a "XMA2" or "fmt " data chunk inside, most other values are unknown */ - uint32_t chunk_type = read_32bit(0xC,streamFile); - 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 */ - 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 */ - || xma->loop_end_sample; - if (xma->xma2_version == 3) { - xma->num_samples = read_32bitBE(xma->chunk_offset+0x14,streamFile); - } else { - xma->num_samples = read_32bitBE(xma->chunk_offset+0x1C,streamFile); - } - } - 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; - /* not needed but may affect looping? (sometimes these don't match loop/total samples) */ - /* 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->xma1_loop_start_offset_b = read_32bit(xma->chunk_offset+0x14,streamFile); - xma->xma1_loop_end_offset_b = read_32bit(xma->chunk_offset+0x18,streamFile); - xma->xma1_subframe_data = (uint8_t)read_8bit(xma->chunk_offset+0x1C,streamFile); - /* find samples count + loop samples since they are not in the header */ - parse_xma1_sample_data(xma, streamFile); - } - else { /* unknown chunk */ - goto fail; - } - - return 1; - -fail: - return 0; -} - - -/** - * XMA1: manually find total and loop samples - * - * A XMA1 stream is made of packets, each containing N frames of X samples, and frame is divided into subframes for looping purposes. - * FFmpeg can't get total samples without decoding, so we'll count frames+samples by reading packet headers. - */ -static void parse_xma1_sample_data(xma_header_data * xma, STREAMFILE *streamFile) { - int frames = 0, loop_frame_start = 0, loop_frame_end = 0, loop_subframe_end, loop_subframe_skip; - uint32_t header, first_frame_b, packet_skip_b, frame_size_b, packet_size_b; - uint64_t packet_offset_b, frame_offset_b; - uint32_t size; - - uint32_t packet_size = XMA_BYTES_PER_PACKET; - uint32_t offset = xma->data_offset; - uint32_t offset_b = 0; - uint32_t stream_offset_b = xma->data_offset * 8; - - size = offset + xma->data_size; - packet_size_b = packet_size*8; - - while (offset < size) { /* stream global offset*/ - /* XMA1 packet header (32b) = packet_sequence:4, unk:2: frame_offset_in_bits:15, packet_stream_skip_count:11 */ - header = read_32bitBE(offset, streamFile); - first_frame_b = (header >> 11) & 0x7FFF; - packet_skip_b = (header) & 0x7FF; - - offset_b = offset * 8; - packet_offset_b = 4*8 + first_frame_b; - while (packet_offset_b < packet_size_b && packet_skip_b!=0x7FF) { /* internal packet offset + full packet skip (needed?) */ - frame_offset_b = offset_b + packet_offset_b; /* global offset to packet, in bits for aligment stuff */ - - /* XMA1 frame header (32b) = frame_length_in_bits:15, frame_data:17+ */ - header = read_32bitBE(frame_offset_b/8, streamFile); - frame_size_b = (header >> (17 - frame_offset_b % 8)) & 0x7FFF; - - if (frame_size_b == 0) /* observed in some files */ - break; - - packet_offset_b += frame_size_b;/* including header */ - - if (frame_size_b != 0x7FFF) /* end frame marker*/ - frames++; - - if (xma->loop_flag && frame_offset_b - stream_offset_b == xma->xma1_loop_start_offset_b) - loop_frame_start = frames; - if (xma->loop_flag && frame_offset_b - stream_offset_b == xma->xma1_loop_end_offset_b) - loop_frame_end = frames; - } - - offset += packet_size; - } - - loop_subframe_end = xma->xma1_subframe_data >> 4; /* upper 4b: subframe where the loop ends, 0..3 */ - loop_subframe_skip = xma->xma1_subframe_data & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */ - - xma->num_samples = frames * XMA_SAMPLES_PER_FRAME; - if (xma->loop_flag) { - xma->loop_start_sample = loop_frame_start * XMA_SAMPLES_PER_FRAME + loop_subframe_skip * XMA_SAMPLES_PER_SUBFRAME; - xma->loop_end_sample = loop_frame_end * XMA_SAMPLES_PER_FRAME + loop_subframe_end * XMA_SAMPLES_PER_SUBFRAME; - } -} - - -/** - * 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 ( !fmt_chunk_swap_endian(chunk, 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; -} - - -/** - * Swaps endianness - * - * returns 0 on error - */ -static int fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec) { - if (codec != 0x166) - goto fail; - - put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*wFormatTag*/ - put_16bitLE(chunk + 0x02, get_16bitBE(chunk + 0x02));/*nChannels*/ - put_32bitLE(chunk + 0x04, get_32bitBE(chunk + 0x04));/*nSamplesPerSec*/ - put_32bitLE(chunk + 0x08, get_32bitBE(chunk + 0x08));/*nAvgBytesPerSec*/ - put_16bitLE(chunk + 0x0c, get_16bitBE(chunk + 0x0c));/*nBlockAlign*/ - put_16bitLE(chunk + 0x0e, get_16bitBE(chunk + 0x0e));/*wBitsPerSample*/ - put_16bitLE(chunk + 0x10, get_16bitBE(chunk + 0x10));/*cbSize*/ - put_16bitLE(chunk + 0x12, get_16bitBE(chunk + 0x12));/*NumStreams*/ - put_32bitLE(chunk + 0x14, get_32bitBE(chunk + 0x14));/*ChannelMask*/ - put_32bitLE(chunk + 0x18, get_32bitBE(chunk + 0x18));/*SamplesEncoded*/ - put_32bitLE(chunk + 0x1c, get_32bitBE(chunk + 0x1c));/*BytesPerBlock*/ - put_32bitLE(chunk + 0x20, get_32bitBE(chunk + 0x20));/*PlayBegin*/ - put_32bitLE(chunk + 0x24, get_32bitBE(chunk + 0x24));/*PlayLength*/ - put_32bitLE(chunk + 0x28, get_32bitBE(chunk + 0x28));/*LoopBegin*/ - put_32bitLE(chunk + 0x2c, get_32bitBE(chunk + 0x2c));/*LoopLength*/ - /* put_8bit(chunk + 0x30, get_8bit(chunk + 0x30));*//*LoopCount*/ - /* put_8bit(chunk + 0x31, get_8bit(chunk + 0x31));*//*EncoderVersion*/ - put_16bitLE(chunk + 0x32, get_16bitBE(chunk + 0x32));/*BlockCount*/ - - return 1; - -fail: - return 0; -} - - -#if ADJUST_SAMPLE_RATE -/** - * Get real XMA sample rate (from Microsoft docs, apparently info only and not correct for playback). - */ -static int32_t get_xma_sample_rate(int32_t general_rate) { - int32_t xma_rate = 48000; /* default XMA */ - - if (general_rate <= 24000) xma_rate = 24000; - else if (general_rate <= 32000) xma_rate = 32000; - else if (general_rate <= 44100) xma_rate = 44100; - - return xma_rate; -} -#endif - -#endif - +#include "meta.h" +#include "../util.h" + +#ifdef VGM_USE_FFMPEG + +#define ADJUST_SAMPLE_RATE 0 +#define XMA_BYTES_PER_PACKET 2048 +#define XMA_SAMPLES_PER_FRAME 512 +#define XMA_SAMPLES_PER_SUBFRAME 128 +#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 */ + + /* info */ + int loop_flag; + int32_t num_samples; + int32_t loop_start_sample; + int32_t loop_end_sample; + + int32_t xma1_loop_start_offset_b; + int32_t xma1_loop_end_offset_b; + int32_t xma1_subframe_data; +} xma_header_data; + + +static int parse_header(xma_header_data * xma, STREAMFILE *streamFile); +static void parse_xma1_sample_data(xma_header_data * xma, STREAMFILE *streamFile); +static int create_riff_header(uint8_t * buf, size_t buf_size, xma_header_data * xma, STREAMFILE *streamFile); +static int fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec); +#if ADJUST_SAMPLE_RATE +static int get_xma_sample_rate(int32_t general_rate); +#endif + +/** + * XMA 1/2 (Microsoft) + * + * Usually in RIFF headers and minor variations. + */ +VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { + char filename[PATH_LIMIT]; + VGMSTREAM * vgmstream = NULL; + ffmpeg_codec_data *data = NULL; + + xma_header_data xma; + uint8_t fake_riff[FAKE_RIFF_BUFFER_SIZE]; + int fake_riff_size = 0; + + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xma",filename_extension(filename)) + && strcasecmp("xma2",filename_extension(filename)) /* Skullgirls */ + && strcasecmp("nps",filename_extension(filename)) /* Beautiful Katamari */ + && strcasecmp("past",filename_extension(filename)) /* SoulCalibur II HD */ + ) + goto fail; + + /* check header */ + if ( !parse_header(&xma, streamFile) ) + goto fail; + + + /* init ffmpeg (create a fake RIFF that FFmpeg can read if needed) */ + 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 */ + vgmstream = allocate_vgmstream(data->channels, xma.loop_flag); + if (!vgmstream) goto fail; + /*vgmstream->channels = data->channels;*/ + /*vgmstream->loop_flag = loop_flag;*/ + + vgmstream->codec_data = data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_FFmpeg; + + vgmstream->sample_rate = data->sampleRate; +#if ADJUST_SAMPLE_RATE + vgmstream->sample_rate = get_xma_sample_rate(vgmstream->sample_rate); +#endif + vgmstream->num_samples = xma.num_samples; /* data->totalSamples: XMA1 = not set; XMA2 = not reliable */ + + if (vgmstream->loop_flag) { + vgmstream->loop_start_sample = xma.loop_start_sample; + vgmstream->loop_end_sample = xma.loop_end_sample; + } + + + return vgmstream; + +fail: + /* clean up */ + if (data) { + free_ffmpeg(data); + } + if (vgmstream) { + vgmstream->codec_data = NULL; + close_vgmstream(vgmstream); + } + 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 */ + off_t current_chunk = 0xc; + off_t fmt_offset = 0, xma2_offset = 0; + size_t riff_size = 0, fmt_size = 0, xma2_size = 0; + + riff_size = read_32bit(4,streamFile); + if (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 (Tekken 6, Galaga Legions DX) */ + /* custom header with a "XMA2" or "fmt " data chunk inside, most other values are unknown */ + uint32_t chunk_type = read_32bit(0xC,streamFile); + 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 */ + 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 */ + || xma->loop_end_sample; + if (xma->xma2_version == 3) { + xma->num_samples = read_32bitBE(xma->chunk_offset+0x14,streamFile); + } else { + xma->num_samples = read_32bitBE(xma->chunk_offset+0x1C,streamFile); + } + } + 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; + /* not needed but may affect looping? (sometimes these don't match loop/total samples) */ + /* 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->xma1_loop_start_offset_b = read_32bit(xma->chunk_offset+0x14,streamFile); + xma->xma1_loop_end_offset_b = read_32bit(xma->chunk_offset+0x18,streamFile); + xma->xma1_subframe_data = (uint8_t)read_8bit(xma->chunk_offset+0x1C,streamFile); + /* find samples count + loop samples since they are not in the header */ + parse_xma1_sample_data(xma, streamFile); + } + else { /* unknown chunk */ + goto fail; + } + + return 1; + +fail: + return 0; +} + + +/** + * XMA1: manually find total and loop samples + * + * A XMA1 stream is made of packets, each containing N frames of X samples, and frame is divided into subframes for looping purposes. + * FFmpeg can't get total samples without decoding, so we'll count frames+samples by reading packet headers. + */ +static void parse_xma1_sample_data(xma_header_data * xma, STREAMFILE *streamFile) { + int frames = 0, loop_frame_start = 0, loop_frame_end = 0, loop_subframe_end, loop_subframe_skip; + uint32_t header, first_frame_b, packet_skip_b, frame_size_b, packet_size_b; + uint64_t packet_offset_b, frame_offset_b; + uint32_t size; + + uint32_t packet_size = XMA_BYTES_PER_PACKET; + uint32_t offset = xma->data_offset; + uint32_t offset_b = 0; + uint32_t stream_offset_b = xma->data_offset * 8; + + size = offset + xma->data_size; + packet_size_b = packet_size*8; + + while (offset < size) { /* stream global offset*/ + /* XMA1 packet header (32b) = packet_sequence:4, unk:2: frame_offset_in_bits:15, packet_stream_skip_count:11 */ + header = read_32bitBE(offset, streamFile); + first_frame_b = (header >> 11) & 0x7FFF; + packet_skip_b = (header) & 0x7FF; + + offset_b = offset * 8; + packet_offset_b = 4*8 + first_frame_b; + while (packet_offset_b < packet_size_b && packet_skip_b!=0x7FF) { /* internal packet offset + full packet skip (needed?) */ + frame_offset_b = offset_b + packet_offset_b; /* global offset to packet, in bits for aligment stuff */ + + /* XMA1 frame header (32b) = frame_length_in_bits:15, frame_data:17+ */ + header = read_32bitBE(frame_offset_b/8, streamFile); + frame_size_b = (header >> (17 - frame_offset_b % 8)) & 0x7FFF; + + if (frame_size_b == 0) /* observed in some files */ + break; + + packet_offset_b += frame_size_b;/* including header */ + + if (frame_size_b != 0x7FFF) /* end frame marker*/ + frames++; + + if (xma->loop_flag && frame_offset_b - stream_offset_b == xma->xma1_loop_start_offset_b) + loop_frame_start = frames; + if (xma->loop_flag && frame_offset_b - stream_offset_b == xma->xma1_loop_end_offset_b) + loop_frame_end = frames; + } + + offset += packet_size; + } + + loop_subframe_end = xma->xma1_subframe_data >> 4; /* upper 4b: subframe where the loop ends, 0..3 */ + loop_subframe_skip = xma->xma1_subframe_data & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */ + + xma->num_samples = frames * XMA_SAMPLES_PER_FRAME; + if (xma->loop_flag) { + xma->loop_start_sample = loop_frame_start * XMA_SAMPLES_PER_FRAME + loop_subframe_skip * XMA_SAMPLES_PER_SUBFRAME; + xma->loop_end_sample = loop_frame_end * XMA_SAMPLES_PER_FRAME + loop_subframe_end * XMA_SAMPLES_PER_SUBFRAME; + } +} + + +/** + * 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 ( !fmt_chunk_swap_endian(chunk, 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; +} + + +/** + * Swaps endianness + * + * returns 0 on error + */ +static int fmt_chunk_swap_endian(uint8_t * chunk, uint16_t codec) { + if (codec != 0x166) + goto fail; + + put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*wFormatTag*/ + put_16bitLE(chunk + 0x02, get_16bitBE(chunk + 0x02));/*nChannels*/ + put_32bitLE(chunk + 0x04, get_32bitBE(chunk + 0x04));/*nSamplesPerSec*/ + put_32bitLE(chunk + 0x08, get_32bitBE(chunk + 0x08));/*nAvgBytesPerSec*/ + put_16bitLE(chunk + 0x0c, get_16bitBE(chunk + 0x0c));/*nBlockAlign*/ + put_16bitLE(chunk + 0x0e, get_16bitBE(chunk + 0x0e));/*wBitsPerSample*/ + put_16bitLE(chunk + 0x10, get_16bitBE(chunk + 0x10));/*cbSize*/ + put_16bitLE(chunk + 0x12, get_16bitBE(chunk + 0x12));/*NumStreams*/ + put_32bitLE(chunk + 0x14, get_32bitBE(chunk + 0x14));/*ChannelMask*/ + put_32bitLE(chunk + 0x18, get_32bitBE(chunk + 0x18));/*SamplesEncoded*/ + put_32bitLE(chunk + 0x1c, get_32bitBE(chunk + 0x1c));/*BytesPerBlock*/ + put_32bitLE(chunk + 0x20, get_32bitBE(chunk + 0x20));/*PlayBegin*/ + put_32bitLE(chunk + 0x24, get_32bitBE(chunk + 0x24));/*PlayLength*/ + put_32bitLE(chunk + 0x28, get_32bitBE(chunk + 0x28));/*LoopBegin*/ + put_32bitLE(chunk + 0x2c, get_32bitBE(chunk + 0x2c));/*LoopLength*/ + /* put_8bit(chunk + 0x30, get_8bit(chunk + 0x30));*//*LoopCount*/ + /* put_8bit(chunk + 0x31, get_8bit(chunk + 0x31));*//*EncoderVersion*/ + put_16bitLE(chunk + 0x32, get_16bitBE(chunk + 0x32));/*BlockCount*/ + + return 1; + +fail: + return 0; +} + + +#if ADJUST_SAMPLE_RATE +/** + * Get real XMA sample rate (from Microsoft docs, apparently info only and not correct for playback). + */ +static int32_t get_xma_sample_rate(int32_t general_rate) { + int32_t xma_rate = 48000; /* default XMA */ + + if (general_rate <= 24000) xma_rate = 24000; + else if (general_rate <= 32000) xma_rate = 32000; + else if (general_rate <= 44100) xma_rate = 44100; + + return xma_rate; +} +#endif + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.c b/Frameworks/vgmstream/vgmstream/src/streamfile.c index 0e5f1e688..522515d60 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.c +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.c @@ -1,18 +1,22 @@ #ifndef _MSC_VER #include #endif -#include "vgmstream.h" #include "streamfile.h" #include "util.h" +#include "vgmstream.h" typedef struct { STREAMFILE sf; FILE * infile; + char name[PATH_LIMIT]; off_t offset; size_t validsize; uint8_t * buffer; size_t buffersize; - char name[PATH_LIMIT]; + size_t filesize; +#ifdef VGM_DEBUG_OUTPUT + int error_notified; +#endif #ifdef PROFILE_STREAMFILE size_t bytes_read; int error_count; @@ -47,9 +51,31 @@ static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOST /* read as much of the beginning of the request as possible, proceed */ while (length>0) { size_t length_to_read; - size_t length_read=0; + size_t length_read; streamfile->validsize=0; - if (fseeko(streamfile->infile,offset,SEEK_SET)) return length_read; + + /* request outside file: ignore to avoid seek/read */ + if (offset > streamfile->filesize) { + #ifdef VGM_DEBUG_OUTPUT + if (!streamfile->error_notified) { + VGM_LOG("ERROR: reading outside filesize, at offset 0x%lx + 0x%x (buggy meta?)\n", offset, length); + streamfile->error_notified = 1; + } + #endif + streamfile->offset = streamfile->filesize; + memset(dest,0,length); + return length; /* return partially-read buffer and 0-set the rest */ + } + + /* position to new offset */ + if (fseeko(streamfile->infile,offset,SEEK_SET)) { + streamfile->offset = streamfile->filesize; +#ifdef PROFILE_STREAMFILE + streamfile->error_count++; +#endif + return 0; //fail miserably + } + streamfile->offset=offset; /* decide how much must be read this time */ @@ -87,9 +113,8 @@ static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOST return length_read_total; } -static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offset, size_t length) -{ - // read +static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offset, size_t length) { + if (!streamfile || !dest || length<=0) return 0; /* if entire request is within the buffer */ @@ -98,6 +123,21 @@ static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offse return length; } + /* request outside file: ignore to avoid seek/read in read_the_rest() */ + if (offset > streamfile->filesize) { +#ifdef VGM_DEBUG_OUTPUT + if (!streamfile->error_notified) { + VGM_LOG("ERROR: reading outside filesize, at offset over 0x%lx (buggy meta?)\n", offset); + streamfile->error_notified = 1; + } +#endif + + streamfile->offset = streamfile->filesize; + memset(dest,0,length); + return length; + } + + /* request outside buffer: new fread */ { size_t length_read = read_the_rest(dest,offset,length,streamfile); #if PROFILE_STREAMFILE @@ -115,8 +155,7 @@ static void close_stdio(STDIOSTREAMFILE * streamfile) { } static size_t get_size_stdio(STDIOSTREAMFILE * streamfile) { - fseeko(streamfile->infile,0,SEEK_END); - return ftello(streamfile->infile); + return streamfile->filesize; } static off_t get_offset_stdio(STDIOSTREAMFILE *streamFile) { @@ -195,6 +234,10 @@ static STREAMFILE * open_stdio_streamfile_buffer_by_FILE(FILE *infile,const char strncpy(streamfile->name,filename,sizeof(streamfile->name)); streamfile->name[sizeof(streamfile->name)-1] = '\0'; + /* cache filesize */ + fseeko(streamfile->infile,0,SEEK_END); + streamfile->filesize = ftello(streamfile->infile); + return &streamfile->sf; } @@ -273,6 +316,18 @@ size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, } +/** + * Opens an stream using the base streamFile name plus a new extension (ex. for headers in a separate file) + */ +STREAMFILE * open_stream_ext(STREAMFILE *streamFile, const char * ext) { + char filename_ext[PATH_LIMIT]; + + streamFile->get_name(streamFile,filename_ext,sizeof(filename_ext)); + strcpy(filename_ext + strlen(filename_ext) - strlen(filename_extension(filename_ext)), ext); + + return streamFile->open(streamFile,filename_ext,STREAMFILE_DEFAULT_BUFFER_SIZE); +} + /** * open file containing decryption keys and copy to buffer * tries combinations of keynames based on the original filename @@ -391,3 +446,72 @@ fail: return 0; } + + +/** + * checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix") + * + * returns 0 on failure + */ +int check_extensions(STREAMFILE *streamFile, const char * cmp_exts) { + char filename[PATH_LIMIT]; + const char * ext = NULL; + const char * cmp_ext = NULL; + size_t ext_len; + + streamFile->get_name(streamFile,filename,sizeof(filename)); + ext = filename_extension(filename); + ext_len = strlen(ext); + + cmp_ext = cmp_exts; + do { + if (strncasecmp(ext,cmp_ext, ext_len)==0 ) + return 1; + cmp_ext = strstr(cmp_ext, ","); + if (cmp_ext != NULL) + cmp_ext = cmp_ext + 1; /* skip comma */ + } while (cmp_ext != NULL); + + return 0; +} + + +/** + * Find a chunk starting from an offset, and save its offset/size (if not NULL), with offset after id/size. + * Works for chunked headers in the form of "chunk_id chunk_size (data)"xN (ex. RIFF). + * The start_offset should be the first actual chunk (not "RIFF" or "WAVE" but "fmt "). + * "full_chunk_size" signals chunk_size includes 4+4+data. + * + * returns 0 on failure + */ +static int find_chunk(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, int size_big_endian, off_t *out_chunk_offset, size_t *out_chunk_size); +int find_chunk_be(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) { + return find_chunk(streamFile, chunk_id, start_offset, full_chunk_size, 1, out_chunk_offset, out_chunk_size); +} +int find_chunk_le(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) { + return find_chunk(streamFile, chunk_id, start_offset, full_chunk_size, 0, out_chunk_offset, out_chunk_size); +} +int find_chunk(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, int size_big_endian, off_t *out_chunk_offset, size_t *out_chunk_size) { + size_t filesize; + off_t current_chunk = start_offset; + + filesize = get_streamfile_size(streamFile); + /* read chunks */ + while (current_chunk < filesize) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = size_big_endian ? + read_32bitBE(current_chunk+4,streamFile) : + read_32bitLE(current_chunk+4,streamFile); + + if (chunk_type == chunk_id) { + if (out_chunk_offset) *out_chunk_offset = current_chunk+8; + if (out_chunk_size) *out_chunk_size = chunk_size; + return 1; + } + + current_chunk += full_chunk_size ? chunk_size : 4+4+chunk_size; + } + + return 0; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.h b/Frameworks/vgmstream/vgmstream/src/streamfile.h index f0347744a..bc2693319 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.h @@ -32,7 +32,7 @@ #define fseeko fseek #endif -#define STREAMFILE_DEFAULT_BUFFER_SIZE 0x400 +#define STREAMFILE_DEFAULT_BUFFER_SIZE 0x8000 #ifndef DIR_SEPARATOR #if defined (_WIN32) || defined (WIN32) @@ -146,11 +146,17 @@ static inline STREAMFILE * open_stdio_streamfile(const char * const filename) { return open_stdio_streamfile_buffer(filename,STREAMFILE_DEFAULT_BUFFER_SIZE); } -size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, - STREAMFILE * infile, int *line_done_ptr); +size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, STREAMFILE * infile, int *line_done_ptr); + +STREAMFILE * open_stream_ext(STREAMFILE *streamFile, const char * ext); int read_key_file(uint8_t * buf, size_t bufsize, STREAMFILE *streamFile); int read_pos_file(uint8_t * buf, size_t bufsize, STREAMFILE *streamFile); +int check_extensions(STREAMFILE *streamFile, const char * cmp_exts); + +int find_chunk_be(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size); +int find_chunk_le(STREAMFILE *streamFile, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size); + #endif diff --git a/Frameworks/vgmstream/vgmstream/src/streamtypes.h b/Frameworks/vgmstream/vgmstream/src/streamtypes.h index e87e4d393..3b2cca352 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamtypes.h +++ b/Frameworks/vgmstream/vgmstream/src/streamtypes.h @@ -7,13 +7,24 @@ #define _STREAMTYPES_H #ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#include +#else #include +#endif /* (_MSC_VER >= 1600) */ + #define inline _inline #define strcasecmp _stricmp +#define strncasecmp _strnicmp + +#if (_MSC_VER < 1900) #define snprintf _snprintf +#endif /* (_MSC_VER < 1900) */ + #else #include -#endif +#endif /* _MSC_VER */ typedef int16_t sample; diff --git a/Frameworks/vgmstream/vgmstream/src/util.c b/Frameworks/vgmstream/vgmstream/src/util.c index a413206ef..0ffec15fb 100644 --- a/Frameworks/vgmstream/vgmstream/src/util.c +++ b/Frameworks/vgmstream/vgmstream/src/util.c @@ -85,75 +85,6 @@ void put_32bitBE(uint8_t * buf, int32_t i) { buf[3] = (uint8_t)(i & 0xFF); } -/* make a header for PCM .wav */ -/* buffer must be 0x2c bytes */ -void make_wav_header(uint8_t * buf, int32_t sample_count, int32_t sample_rate, int channels) { - size_t bytecount; - - bytecount = sample_count*channels*sizeof(sample); - - /* RIFF header */ - memcpy(buf+0, "RIFF", 4); - /* size of RIFF */ - put_32bitLE(buf+4, (int32_t)(bytecount+0x2c-8)); - - /* WAVE header */ - memcpy(buf+8, "WAVE", 4); - - /* WAVE fmt chunk */ - memcpy(buf+0xc, "fmt ", 4); - /* size of WAVE fmt chunk */ - put_32bitLE(buf+0x10, 0x10); - - /* compression code 1=PCM */ - put_16bitLE(buf+0x14, 1); - - /* channel count */ - put_16bitLE(buf+0x16, channels); - - /* sample rate */ - put_32bitLE(buf+0x18, sample_rate); - - /* bytes per second */ - put_32bitLE(buf+0x1c, sample_rate*channels*sizeof(sample)); - - /* block align */ - put_16bitLE(buf+0x20, (int16_t)(channels*sizeof(sample))); - - /* significant bits per sample */ - put_16bitLE(buf+0x22, sizeof(sample)*8); - - /* PCM has no extra format bytes, so we don't even need to specify a count */ - - /* WAVE data chunk */ - memcpy(buf+0x24, "data", 4); - /* size of WAVE data chunk */ - put_32bitLE(buf+0x28, (int32_t)bytecount); -} - -void make_smpl_chunk(uint8_t * buf, int32_t loop_start, int32_t loop_end) { - int i; - /* RIFF header */ - memcpy(buf+0, "smpl", 4); - /* size of RIFF */ - put_32bitLE(buf+4, 0x3c); - - for (i = 0; i < 7; i++) - put_32bitLE(buf+8 + i * 4, 0); - - put_32bitLE(buf+36, 1); - - for (i = 0; i < 3; i++) - put_32bitLE(buf+40 + i * 4, 0); - - put_32bitLE(buf+52, loop_start); - put_32bitLE(buf+56, loop_end); - put_32bitLE(buf+60, 0); - put_32bitLE(buf+64, 0); - - -} - void swap_samples_le(sample *buf, int count) { int i; for (i=0;i 1 */ -void concatn_doublenull(int length, char * dst, const char * src) { - int i,j; - if (length <= 1) return; - for (i=0;i0) i++; - for (j=0;i 1, if src won't fit, truncate */ -void concatn_fitting_doublenull(int length, char * dst, const char * src) { - int i,j,k; - if (length <= 1) return; - for (i=0;i0) i++; - k = i; - for (j=0;i #include #include +#include "formats.h" #include "vgmstream.h" #include "meta/meta.h" #include "layout/layout.h" @@ -30,7 +31,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_halpst, init_vgmstream_rs03, init_vgmstream_ngc_dsp_std, - init_vgmstream_ngc_dsp_csmp, + init_vgmstream_ngc_dsp_csmp, init_vgmstream_Cstr, init_vgmstream_gcsw, init_vgmstream_ps2_ads, @@ -92,10 +93,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_hgc1, init_vgmstream_aus, init_vgmstream_rws, - init_vgmstream_fsb1, - // init_vgmstream_fsb2, - init_vgmstream_fsb3, - init_vgmstream_fsb4, + init_vgmstream_fsb, init_vgmstream_fsb4_wav, init_vgmstream_fsb5, init_vgmstream_rwx, @@ -122,7 +120,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_dxh, init_vgmstream_ps2_psh, init_vgmstream_pcm_scd, - init_vgmstream_pcm_ps2, + init_vgmstream_pcm_ps2, init_vgmstream_ps2_rkv, init_vgmstream_ps2_psw, init_vgmstream_ps2_vas, @@ -166,7 +164,6 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_wii_mus, init_vgmstream_dc_asd, init_vgmstream_naomi_spsd, - init_vgmstream_rsd2vag, init_vgmstream_rsd2pcmb, init_vgmstream_rsd2xadp, @@ -231,19 +228,19 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_sps, init_vgmstream_ps2_xa2_rrp, init_vgmstream_nds_hwas, - init_vgmstream_ngc_lps, + init_vgmstream_ngc_lps, init_vgmstream_ps2_snd, init_vgmstream_naomi_adpcm, - init_vgmstream_sd9, - init_vgmstream_2dx9, - init_vgmstream_dsp_ygo, + init_vgmstream_sd9, + init_vgmstream_2dx9, + init_vgmstream_dsp_ygo, init_vgmstream_ps2_vgv, init_vgmstream_ngc_gcub, init_vgmstream_maxis_xa, init_vgmstream_ngc_sck_dsp, init_vgmstream_apple_caff, - init_vgmstream_pc_mxst, - init_vgmstream_sab, + init_vgmstream_pc_mxst, + init_vgmstream_sab, init_vgmstream_exakt_sc, init_vgmstream_wii_bns, init_vgmstream_wii_was, @@ -254,8 +251,8 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_stm, init_vgmstream_myspd, init_vgmstream_his, - init_vgmstream_ps2_ast, - init_vgmstream_dmsg, + init_vgmstream_ps2_ast, + init_vgmstream_dmsg, init_vgmstream_ngc_dsp_aaap, init_vgmstream_ngc_dsp_konami, init_vgmstream_ps2_ster, @@ -286,21 +283,20 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_dsp_xiii, init_vgmstream_dsp_cabelas, init_vgmstream_ps2_adm, - init_vgmstream_ps2_lpcm, + init_vgmstream_ps2_lpcm, init_vgmstream_dsp_bdsp, - init_vgmstream_ps2_vms, - init_vgmstream_ps2_xau, + init_vgmstream_ps2_vms, + init_vgmstream_ps2_xau, init_vgmstream_gh3_bar, init_vgmstream_ffw, init_vgmstream_dsp_dspw, init_vgmstream_ps2_jstm, init_vgmstream_ps3_xvag, - init_vgmstream_ps3_cps, + init_vgmstream_ps3_cps, init_vgmstream_sqex_scd, init_vgmstream_ngc_nst_dsp, init_vgmstream_baf, init_vgmstream_ps3_msf, - init_vgmstream_fsb_mpeg, init_vgmstream_nub_vag, init_vgmstream_ps3_past, init_vgmstream_ps3_sgdx, @@ -311,7 +307,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_iab, init_vgmstream_ps2_strlr, init_vgmstream_lsf_n1nj4n, - init_vgmstream_ps3_vawx, + init_vgmstream_vawx, init_vgmstream_pc_snds, init_vgmstream_ps2_wmus, init_vgmstream_hyperscan_kvag, @@ -335,27 +331,32 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { init_vgmstream_otm, init_vgmstream_bcstm, init_vgmstream_3ds_idsp, - init_vgmstream_g1l, + init_vgmstream_kt_g1l, + init_vgmstream_kt_wiibgm, init_vgmstream_hca, init_vgmstream_ps2_svag_snk, + init_vgmstream_ps2_vds_vdm, + init_vgmstream_x360_cxs, #ifdef VGM_USE_FFMPEG init_vgmstream_xma, init_vgmstream_mp4_aac_ffmpeg, - init_vgmstream_ffmpeg, + + init_vgmstream_ffmpeg, /* should go at the end */ #endif }; -#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0])) /* internal version with all parameters */ VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) { - int i; + int i, fcns_size; if (!streamFile) return NULL; + fcns_size = (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0])); /* try a series of formats, see which works */ - for (i=0;imeta_type == meta_KRAW) || (vgmstream->meta_type == meta_PS2_MIB) || (vgmstream->meta_type == meta_NGC_LPS) || - (vgmstream->meta_type == meta_DSP_YGO) || + (vgmstream->meta_type == meta_DSP_YGO) || (vgmstream->meta_type == meta_DSP_AGSC) || - (vgmstream->meta_type == meta_PS2_SMPL) || - (vgmstream->meta_type == meta_NGCA) || + (vgmstream->meta_type == meta_PS2_SMPL) || + (vgmstream->meta_type == meta_NGCA) || (vgmstream->meta_type == meta_NUB_VAG) || (vgmstream->meta_type == meta_SPT_SPD) || (vgmstream->meta_type == meta_EB_SFX) || @@ -455,7 +456,7 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { #endif if (vgmstream->coding_type==coding_CRI_HCA) { hca_codec_data *data = vgmstream->codec_data; - clHCA *hca = (clHCA *)(data + 1); + /*clHCA *hca = (clHCA *)(data + 1);*/ data->curblock = 0; data->sample_ptr = clHCA_samplesPerBlock; data->samples_discard = 0; @@ -860,7 +861,7 @@ void close_vgmstream(VGMSTREAM * vgmstream) { * but deallocate itself, there is only one open file and * that is in vgmstream->ch[0].streamfile */ close_vgmstream(data->substreams[i]); - close_streamfile(data->intfiles[i]); + if(data->intfiles[i]) close_streamfile(data->intfiles[i]); } free(data->substreams); free(data->intfiles); @@ -916,7 +917,6 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre case layout_fake_mpeg: case layout_mpeg: #endif - case layout_dtk_interleave: case layout_none: render_vgmstream_nolayout(buffer,sample_count,vgmstream); break; @@ -1028,21 +1028,19 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_AICA: return 2; case coding_NGC_AFC: - case coding_FFXI: return 16; case coding_PSX: case coding_PSX_badflags: - case coding_invert_PSX: - case coding_HEVAG_ADPCM: + case coding_PSX_bmdx: + case coding_HEVAG: case coding_XA: return 28; - case coding_SHORT_VAG_ADPCM: - return 6; + case coding_PSX_cfg: + return (vgmstream->interleave_block_size - 1) * 2; /* decodes 1 byte into 2 bytes */ case coding_XBOX: case coding_INT_XBOX: - case coding_BAF_ADPCM: return 64; - case coding_EAXA: + case coding_EA_XA: return 28; case coding_MAXIS_ADPCM: case coding_EA_ADPCM: @@ -1159,16 +1157,15 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { case coding_SNDS_IMA: return 0; case coding_NGC_AFC: - case coding_FFXI: return 9; case coding_PSX: case coding_PSX_badflags: - case coding_HEVAG_ADPCM: - case coding_invert_PSX: + case coding_PSX_bmdx: + case coding_HEVAG: case coding_NDS_PROCYON: return 16; - case coding_SHORT_VAG_ADPCM: - return 4; + case coding_PSX_cfg: + return vgmstream->interleave_block_size; case coding_XA: return 14*vgmstream->channels; case coding_XBOX: @@ -1178,7 +1175,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return 15*vgmstream->channels; case coding_EA_ADPCM: return 30; - case coding_EAXA: + case coding_EA_XA: return 1; // the frame is variant in size case coding_WS: return vgmstream->current_block_size; @@ -1188,15 +1185,13 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return 1; case coding_APPLE_IMA4: return 34; - case coding_BAF_ADPCM: - return 33; case coding_LSF: return 28; #ifdef VGM_USE_G7221 case coding_G7221C: case coding_G7221: #endif -#ifdef VGM_USE_G719: +#ifdef VGM_USE_G719 case coding_G719: #endif #ifdef VGM_USE_MAIATRAC3PLUS @@ -1399,19 +1394,9 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to break; case coding_PSX: for (chan=0;chanchannels;chan++) { - if(vgmstream->skip_last_channel) - { - if(chan!=vgmstream->channels-1) { - decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, - vgmstream->channels,vgmstream->samples_into_block, - samples_to_do); - } - - } else { - decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, samples_to_do); - } } break; case coding_PSX_badflags: @@ -1421,39 +1406,25 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; - case coding_invert_PSX: + case coding_PSX_bmdx: for (chan=0;chanchannels;chan++) { - decode_invert_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + decode_psx_bmdx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, samples_to_do); } break; - case coding_FFXI: + case coding_HEVAG: for (chan=0;chanchannels;chan++) { - decode_ffxi_adpcm(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + decode_hevag(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, samples_to_do); } break; - case coding_BAF_ADPCM: + case coding_PSX_cfg: for (chan=0;chanchannels;chan++) { - decode_baf_adpcm(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + decode_psx_configurable(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, - samples_to_do); - } - break; - case coding_HEVAG_ADPCM: - for (chan=0;chanchannels;chan++) { - decode_hevag_adpcm(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, - vgmstream->channels,vgmstream->samples_into_block, - samples_to_do); - } - break; - case coding_SHORT_VAG_ADPCM: - for (chan=0;chanchannels;chan++) { - decode_short_vag_adpcm(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, - vgmstream->channels,vgmstream->samples_into_block, - samples_to_do); + samples_to_do, vgmstream->interleave_block_size); } break; case coding_XA: @@ -1463,9 +1434,9 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do,chan); } break; - case coding_EAXA: + case coding_EA_XA: for (chan=0;chanchannels;chan++) { - decode_eaxa(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + decode_ea_xa(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, vgmstream->channels,vgmstream->samples_into_block, samples_to_do,chan); } @@ -1583,6 +1554,7 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + #ifdef VGM_USE_MPEG case coding_fake_MPEG2_L2: decode_fake_mpeg2_l2( @@ -1757,7 +1729,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { vgmstream->meta_type == meta_DSP_RS03 || vgmstream->meta_type == meta_DSP_CSTR || vgmstream->coding_type == coding_PSX || - vgmstream->coding_type == coding_invert_PSX || + vgmstream->coding_type == coding_PSX_bmdx || vgmstream->coding_type == coding_PSX_badflags) { int i; for (i=0;ichannels;i++) { @@ -1767,21 +1739,14 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { vgmstream->loop_ch[i].adpcm_history2_32 = vgmstream->ch[i].adpcm_history2_32; } } - /* todo preserve hevag, baf_adpcm, etc history? */ + /* todo preserve ADPCM (ex hevag) history? */ -#ifdef DEBUG - { - int i; - for (i=0;ichannels;i++) { - fprintf(stderr,"ch%d hist: %04x %04x loop hist: %04x %04x\n",i, - vgmstream->ch[i].adpcm_history1_16,vgmstream->ch[i].adpcm_history2_16, - vgmstream->loop_ch[i].adpcm_history1_16,vgmstream->loop_ch[i].adpcm_history2_16); - fprintf(stderr,"ch%d offset: %x loop offset: %x\n",i, - vgmstream->ch[i].offset, - vgmstream->loop_ch[i].offset); - } + if (vgmstream->coding_type==coding_CRI_HCA) { + hca_codec_data *data = (hca_codec_data *)(vgmstream->codec_data); + data->curblock = data->info.loopStart; + data->sample_ptr = clHCA_samplesPerBlock; + data->samples_discard = 0; } -#endif #ifdef VGM_USE_VORBIS if (vgmstream->coding_type==coding_ogg_vorbis) { @@ -1792,17 +1757,13 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { ov_pcm_seek_lap(ogg_vorbis_file, vgmstream->loop_sample); } #endif - if (vgmstream->coding_type==coding_CRI_HCA) { - hca_codec_data *data = (hca_codec_data *)(vgmstream->codec_data); - data->curblock = data->info.loopStart; - data->sample_ptr = clHCA_samplesPerBlock; - data->samples_discard = 0; - } + #ifdef VGM_USE_FFMPEG if (vgmstream->coding_type==coding_FFmpeg) { seek_ffmpeg(vgmstream, vgmstream->loop_start_sample); } -#endif /* VGM_USE_FFMPEG */ +#endif + #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) if (vgmstream->coding_type==coding_MP4_AAC) { mp4_aac_codec_data *data = (mp4_aac_codec_data *)(vgmstream->codec_data); @@ -1811,6 +1772,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { data->samples_discard = vgmstream->loop_sample; } #endif + #ifdef VGM_USE_MAIATRAC3PLUS if (vgmstream->coding_type==coding_AT3plus) { int blocks_to_skip = vgmstream->loop_sample / 2048; @@ -1822,6 +1784,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { data->samples_discard = samples_to_discard; } #endif + #ifdef VGM_USE_MPEG /* won't work for fake MPEG */ if (vgmstream->layout_type==layout_mpeg) { @@ -1880,6 +1843,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { #define TEMPSIZE 256 char temp[TEMPSIZE]; + const char* description; if (!vgmstream) { snprintf(temp,TEMPSIZE,"NULL VGMSTREAM"); @@ -1909,404 +1873,51 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { snprintf(temp,TEMPSIZE,"encoding: "); concatn(length,desc,temp); - switch (vgmstream->coding_type) { - case coding_PCM16BE: - snprintf(temp,TEMPSIZE,"Big Endian 16-bit PCM"); - break; - case coding_PCM16LE: - snprintf(temp,TEMPSIZE,"Little Endian 16-bit PCM"); - break; - case coding_PCM16LE_int: - snprintf(temp,TEMPSIZE,"Little Endian 16-bit PCM with 2 byte interleave"); - break; - case coding_PCM16LE_XOR_int: - snprintf(temp,TEMPSIZE,"Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"); - break; - case coding_PCM8: - snprintf(temp,TEMPSIZE,"8-bit PCM"); - break; - case coding_PCM8_U: - snprintf(temp,TEMPSIZE,"8-bit unsigned PCM"); - break; - case coding_PCM8_U_int: - snprintf(temp,TEMPSIZE,"8-bit unsigned PCM with 1 byte interleave"); - break; - case coding_PCM8_int: - snprintf(temp,TEMPSIZE,"8-bit PCM with 1 byte interleave"); - break; - case coding_PCM8_SB_int: - snprintf(temp,TEMPSIZE,"8-bit PCM with sign bit, 1 byte interleave"); - break; - case coding_NGC_DSP: - snprintf(temp,TEMPSIZE,"Gamecube \"DSP\" 4-bit ADPCM"); - break; - case coding_CRI_ADX: - snprintf(temp,TEMPSIZE,"CRI ADX 4-bit ADPCM"); - break; - case coding_CRI_ADX_enc_8: - snprintf(temp,TEMPSIZE,"encrypted (type 8) CRI ADX 4-bit ADPCM"); - break; - case coding_CRI_ADX_enc_9: - snprintf(temp,TEMPSIZE,"encrypted (type 9) CRI ADX 4-bit ADPCM"); - break; - case coding_NDS_IMA: - snprintf(temp,TEMPSIZE,"NDS-style 4-bit IMA ADPCM"); - break; - case coding_DAT4_IMA: - snprintf(temp,TEMPSIZE,"Eurocom DAT4 4-bit IMA ADPCM"); - break; - case coding_NGC_DTK: - snprintf(temp,TEMPSIZE,"Gamecube \"ADP\"/\"DTK\" 4-bit ADPCM"); - break; - case coding_G721: - snprintf(temp,TEMPSIZE,"CCITT G.721 4-bit ADPCM"); - break; - case coding_NGC_AFC: - snprintf(temp,TEMPSIZE,"Gamecube \"AFC\" 4-bit ADPCM"); - break; - case coding_PSX: - snprintf(temp,TEMPSIZE,"Playstation 4-bit ADPCM"); - break; - case coding_PSX_badflags: - snprintf(temp,TEMPSIZE,"Playstation 4-bit ADPCM with bad flags"); - break; - case coding_invert_PSX: - snprintf(temp,TEMPSIZE,"BMDX \"encrypted\" Playstation 4-bit ADPCM"); - break; - case coding_FFXI: - snprintf(temp,TEMPSIZE,"FFXI Playstation-ish 4-bit ADPCM"); - break; - case coding_BAF_ADPCM: - snprintf(temp,TEMPSIZE,"Bizarre Creations Playstation-ish 4-bit ADPCM"); - break; - case coding_HEVAG_ADPCM: - snprintf(temp,TEMPSIZE,"PSVita HEVAG ADPCM"); - break; - case coding_SHORT_VAG_ADPCM: - snprintf(temp,TEMPSIZE,"Short VAG (SGXD type 5) ADPCM"); - break; - case coding_XA: - snprintf(temp,TEMPSIZE,"CD-ROM XA 4-bit ADPCM"); - break; - case coding_XBOX: - snprintf(temp,TEMPSIZE,"XBOX 4-bit IMA ADPCM"); - break; - case coding_INT_XBOX: - snprintf(temp,TEMPSIZE,"XBOX Interleaved 4-bit IMA ADPCM"); - break; - case coding_EAXA: - snprintf(temp,TEMPSIZE,"Electronic Arts XA Based 4-bit ADPCM"); - break; - case coding_EA_ADPCM: - snprintf(temp,TEMPSIZE,"Electronic Arts XA Based (R1) 4-bit ADPCM"); - break; -#ifdef VGM_USE_VORBIS - case coding_ogg_vorbis: - snprintf(temp,TEMPSIZE,"Vorbis"); - break; -#endif - case coding_SDX2: - snprintf(temp,TEMPSIZE,"Squareroot-delta-exact (SDX2) 8-bit DPCM"); - break; - case coding_SDX2_int: - snprintf(temp,TEMPSIZE,"Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"); - break; - case coding_CBD2: - snprintf(temp,TEMPSIZE,"Cuberoot-delta-exact (CBD2) 8-bit DPCM"); - break; - case coding_CBD2_int: - snprintf(temp,TEMPSIZE,"Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"); - break; - case coding_DVI_IMA: - snprintf(temp,TEMPSIZE,"Intel DVI 4-bit IMA ADPCM"); - break; - case coding_INT_DVI_IMA: - snprintf(temp,TEMPSIZE,"Interleaved Intel DVI 4-bit IMA ADPCM"); - break; - case coding_EACS_IMA: - snprintf(temp,TEMPSIZE,"EACS 4-bit IMA ADPCM"); - break; - case coding_MAXIS_ADPCM: - snprintf(temp,TEMPSIZE,"Maxis XA (EA ADPCM Variant)"); - break; - case coding_INT_IMA: - snprintf(temp,TEMPSIZE,"Interleaved 4-bit IMA ADPCM"); - break; - case coding_IMA: - snprintf(temp,TEMPSIZE,"4-bit IMA ADPCM"); - break; - case coding_MS_IMA: - snprintf(temp,TEMPSIZE,"Microsoft 4-bit IMA ADPCM"); - break; - case coding_RAD_IMA: - snprintf(temp,TEMPSIZE,"\"Radical\" 4-bit IMA ADPCM"); - break; - case coding_RAD_IMA_mono: - snprintf(temp,TEMPSIZE,"\"Radical\" 4-bit IMA ADPCM (mono)"); - break; - case coding_APPLE_IMA4: - snprintf(temp,TEMPSIZE,"Apple Quicktime 4-bit IMA ADPCM"); - break; - case coding_SNDS_IMA: - snprintf(temp,TEMPSIZE,"Heavy Iron .snds 4-bit IMA ADPCM"); - break; - case coding_WS: - snprintf(temp,TEMPSIZE,"Westwood Studios DPCM"); - break; -#ifdef VGM_USE_MPEG - case coding_fake_MPEG2_L2: - snprintf(temp,TEMPSIZE,"MPEG-2 Layer II Audio"); - break; - case coding_MPEG1_L1: - snprintf(temp,TEMPSIZE,"MPEG-1 Layer I Audio"); - break; - case coding_MPEG1_L2: - snprintf(temp,TEMPSIZE,"MPEG-1 Layer II Audio"); - break; - case coding_MPEG1_L3: - snprintf(temp,TEMPSIZE,"MPEG-1 Layer III Audio (MP3)"); - break; - case coding_MPEG2_L1: - snprintf(temp,TEMPSIZE,"MPEG-2 Layer I Audio"); - break; - case coding_MPEG2_L2: - snprintf(temp,TEMPSIZE,"MPEG-2 Layer II Audio"); - break; - case coding_MPEG2_L3: - snprintf(temp,TEMPSIZE,"MPEG-2 Layer III Audio (MP3)"); - break; - case coding_MPEG25_L1: - snprintf(temp,TEMPSIZE,"MPEG-2.5 Layer I Audio"); - break; - case coding_MPEG25_L2: - snprintf(temp,TEMPSIZE,"MPEG-2.5 Layer II Audio"); - break; - case coding_MPEG25_L3: - snprintf(temp,TEMPSIZE,"MPEG-2.5 Layer III Audio (MP3)"); - break; -#endif -#ifdef VGM_USE_G7221 - case coding_G7221: - snprintf(temp,TEMPSIZE,"ITU G.722.1 (Polycom Siren 7)"); - break; - case coding_G7221C: - snprintf(temp,TEMPSIZE,"ITU G.722.1 annex C (Polycom Siren 14)"); - break; -#endif -#ifdef VGM_USE_G719 - case coding_G719: - snprintf(temp,TEMPSIZE,"ITU G.719 annex B (Polycom Siren 22)"); - break; -#endif -#ifdef VGM_USE_MAIATRAC3PLUS - case coding_AT3plus: - snprintf(temp,TEMPSIZE,"ATRAC3plus"); - break; -#endif #ifdef VGM_USE_FFMPEG - case coding_FFmpeg: - { - ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; - if (vgmstream->codec_data) { - if (data->codec && data->codec->long_name) { - snprintf(temp,TEMPSIZE,data->codec->long_name); - } - else if (data->codec && data->codec->name) { - snprintf(temp,TEMPSIZE,data->codec->name); - } - else { - snprintf(temp,TEMPSIZE,"FFmpeg (unknown codec)"); - } - } - else { - snprintf(temp,TEMPSIZE,"FFmpeg"); + case coding_FFmpeg: { + ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; + if (vgmstream->codec_data) { + if (data->codec && data->codec->long_name) { + snprintf(temp,TEMPSIZE,data->codec->long_name); + } else if (data->codec && data->codec->name) { + snprintf(temp,TEMPSIZE,data->codec->name); + } else { + snprintf(temp,TEMPSIZE,"FFmpeg (unknown codec)"); } + } else { + snprintf(temp,TEMPSIZE,"FFmpeg"); } break; + } #endif - - case coding_ACM: - snprintf(temp,TEMPSIZE,"InterPlay ACM"); - break; - case coding_NWA0: - snprintf(temp,TEMPSIZE,"NWA DPCM Level 0"); - break; - case coding_NWA1: - snprintf(temp,TEMPSIZE,"NWA DPCM Level 1"); - break; - case coding_NWA2: - snprintf(temp,TEMPSIZE,"NWA DPCM Level 2"); - break; - case coding_NWA3: - snprintf(temp,TEMPSIZE,"NWA DPCM Level 3"); - break; - case coding_NWA4: - snprintf(temp,TEMPSIZE,"NWA DPCM Level 4"); - break; - case coding_NWA5: - snprintf(temp,TEMPSIZE,"NWA DPCM Level 5"); - break; - case coding_MSADPCM: - snprintf(temp,TEMPSIZE,"Microsoft 4-bit ADPCM"); - break; - case coding_AICA: - snprintf(temp,TEMPSIZE,"Yamaha AICA 4-bit ADPCM"); - break; - case coding_NDS_PROCYON: - snprintf(temp,TEMPSIZE,"Procyon Studio Digital Sound Elements NDS 4-bit APDCM"); - break; - case coding_L5_555: - snprintf(temp,TEMPSIZE,"Level-5 0x555 4-bit ADPCM"); - break; - case coding_SASSC: - snprintf(temp,TEMPSIZE,"Activision / EXAKT SASSC 8-bit DPCM"); - break; - case coding_LSF: - snprintf(temp,TEMPSIZE,"lsf 4-bit ADPCM"); - break; - case coding_MTAF: - snprintf(temp,TEMPSIZE,"Konami MTAF 4-bit ADPCM"); - break; default: - snprintf(temp,TEMPSIZE,"CANNOT DECODE"); + description = get_vgmstream_coding_description(vgmstream->coding_type); + if (!description) + description = "CANNOT DECODE"; + strncpy(temp,description,TEMPSIZE); + break; } concatn(length,desc,temp); snprintf(temp,TEMPSIZE,"\nlayout: "); concatn(length,desc,temp); - switch (vgmstream->layout_type) { - case layout_none: - snprintf(temp,TEMPSIZE,"flat (no layout)"); - break; - case layout_interleave: - snprintf(temp,TEMPSIZE,"interleave"); - break; - case layout_interleave_shortblock: - snprintf(temp,TEMPSIZE,"interleave with short last block"); - break; - case layout_interleave_byte: - snprintf(temp,TEMPSIZE,"sub-frame interleave"); - break; - case layout_dtk_interleave: - snprintf(temp,TEMPSIZE,"ADP/DTK nibble interleave"); - break; - case layout_mxch_blocked: - snprintf(temp,TEMPSIZE,"MxCh blocked"); - break; - case layout_ast_blocked: - snprintf(temp,TEMPSIZE,"AST blocked"); - break; - case layout_halpst_blocked: - snprintf(temp,TEMPSIZE,"HALPST blocked"); - break; - case layout_xa_blocked: - snprintf(temp,TEMPSIZE,"CD-ROM XA"); - break; - case layout_ea_blocked: - snprintf(temp,TEMPSIZE,"Electronic Arts Audio Blocks"); - break; - case layout_eacs_blocked: - snprintf(temp,TEMPSIZE,"Electronic Arts (Old Version) Audio Blocks"); - break; - case layout_caf_blocked: - snprintf(temp,TEMPSIZE,"CAF blocked"); - break; - case layout_wsi_blocked: - snprintf(temp,TEMPSIZE,".wsi blocked"); - break; - case layout_xvas_blocked: - snprintf(temp,TEMPSIZE,".xvas blocked"); - break; -#ifdef VGM_USE_VORBIS - case layout_ogg_vorbis: - snprintf(temp,TEMPSIZE,"Ogg"); - break; -#endif - case layout_str_snds_blocked: - snprintf(temp,TEMPSIZE,".str SNDS blocked"); - break; - case layout_ws_aud_blocked: - snprintf(temp,TEMPSIZE,"Westwood Studios .aud blocked"); - break; - case layout_matx_blocked: - snprintf(temp,TEMPSIZE,"Matrix .matx blocked"); - break; - case layout_de2_blocked: - snprintf(temp,TEMPSIZE,"de2 blocked"); - break; - case layout_vs_blocked: - snprintf(temp,TEMPSIZE,"vs blocked"); - break; - case layout_emff_ps2_blocked: - snprintf(temp,TEMPSIZE,"EMFF (PS2) blocked"); - break; - case layout_emff_ngc_blocked: - snprintf(temp,TEMPSIZE,"EMFF (NGC/WII) blocked"); - break; - case layout_gsb_blocked: - snprintf(temp,TEMPSIZE,"GSB blocked"); - break; - case layout_thp_blocked: - snprintf(temp,TEMPSIZE,"THP Movie Audio blocked"); - break; - case layout_filp_blocked: - snprintf(temp,TEMPSIZE,"FILp blocked"); - break; - case layout_psx_mgav_blocked: - snprintf(temp,TEMPSIZE,"MGAV blocked"); - break; - case layout_ps2_adm_blocked: - snprintf(temp,TEMPSIZE,"ADM blocked"); - break; - case layout_dsp_bdsp_blocked: - snprintf(temp,TEMPSIZE,"DSP blocked"); - break; -#ifdef VGM_USE_MPEG - case layout_fake_mpeg: - snprintf(temp,TEMPSIZE,"MPEG Audio stream with incorrect frame headers"); - break; - case layout_mpeg: - snprintf(temp,TEMPSIZE,"MPEG Audio stream"); - break; -#endif - case layout_acm: - snprintf(temp,TEMPSIZE,"ACM blocked"); - break; - case layout_mus_acm: - snprintf(temp,TEMPSIZE,"multiple ACM files, ACM blocked"); - break; - case layout_aix: - snprintf(temp,TEMPSIZE,"AIX interleave, internally 18-byte interleaved"); - break; - case layout_aax: - snprintf(temp,TEMPSIZE,"AAX blocked, 18-byte interleaved"); - break; - case layout_ivaud_blocked: - snprintf(temp,TEMPSIZE,"GTA IV blocked"); - break; - case layout_ps2_iab_blocked: - snprintf(temp,TEMPSIZE,"IAB blocked"); - break; - case layout_ps2_strlr_blocked: - snprintf(temp,TEMPSIZE,"The Bouncer STR blocked"); - break; - case layout_tra_blocked: - snprintf(temp,TEMPSIZE,"TRA blocked"); - break; - case layout_scd_int: - snprintf(temp,TEMPSIZE,"SCD multistream interleave"); - break; default: - snprintf(temp,TEMPSIZE,"INCONCEIVABLE"); + description = get_vgmstream_layout_description(vgmstream->layout_type); + if (!description) + description = "INCONCEIVABLE"; + strncpy(temp,description,TEMPSIZE); + break; } concatn(length,desc,temp); snprintf(temp,TEMPSIZE,"\n"); concatn(length,desc,temp); - if (vgmstream->layout_type == layout_interleave || vgmstream->layout_type == layout_interleave_shortblock || vgmstream->layout_type == layout_interleave_byte) { + if (vgmstream->layout_type == layout_interleave + || vgmstream->layout_type == layout_interleave_shortblock + || vgmstream->layout_type == layout_interleave_byte) { snprintf(temp,TEMPSIZE,"interleave: %#x bytes\n", (int32_t)vgmstream->interleave_block_size); concatn(length,desc,temp); @@ -2322,993 +1933,17 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { concatn(length,desc,temp); switch (vgmstream->meta_type) { - case meta_RSTM: - snprintf(temp,TEMPSIZE,"Nintendo RSTM header"); + default: + description = get_vgmstream_meta_description(vgmstream->meta_type); + if (!description) + description = "THEY SHOULD HAVE SENT A POET"; + strncpy(temp,description,TEMPSIZE); break; - case meta_STRM: - snprintf(temp,TEMPSIZE,"Nintendo STRM header"); - break; - case meta_ADX_03: - snprintf(temp,TEMPSIZE,"CRI ADX header type 03"); - break; - case meta_ADX_04: - snprintf(temp,TEMPSIZE,"CRI ADX header type 04"); - break; - case meta_ADX_05: - snprintf(temp,TEMPSIZE,"CRI ADX header type 05"); - break; - case meta_AIX: - snprintf(temp,TEMPSIZE,"CRI AIX header"); - break; - case meta_AAX: - snprintf(temp,TEMPSIZE,"CRI AAX header"); - break; - case meta_UTF_DSP: - snprintf(temp,TEMPSIZE,"CRI ADPCM_WII header"); - break; - case meta_DSP_AGSC: - snprintf(temp,TEMPSIZE,"Retro Studios AGSC header"); - break; - case meta_DSP_CSMP: - snprintf(temp,TEMPSIZE,"Retro Studios CSMP header"); - break; - case meta_NGC_ADPDTK: - snprintf(temp,TEMPSIZE,"assumed Nintendo ADP by .adp extension and valid first frame"); - break; - case meta_RSF: - snprintf(temp,TEMPSIZE,"assumed Retro Studios RSF by .rsf extension and valid first bytes"); - break; - case meta_AFC: - snprintf(temp,TEMPSIZE,"Nintendo AFC header"); - break; - case meta_AST: - snprintf(temp,TEMPSIZE,"Nintendo AST header"); - break; - case meta_HALPST: - snprintf(temp,TEMPSIZE,"HAL Laboratory HALPST header"); - break; - case meta_DSP_RS03: - snprintf(temp,TEMPSIZE,"Retro Studios RS03 header"); - break; - case meta_DSP_STD: - snprintf(temp,TEMPSIZE,"Standard Nintendo DSP header"); - break; - case meta_DSP_CSTR: - snprintf(temp,TEMPSIZE,"Namco Cstr header"); - break; - case meta_GCSW: - snprintf(temp,TEMPSIZE,"GCSW header"); - break; - case meta_PS2_SShd: - snprintf(temp,TEMPSIZE,"SShd header"); - break; - case meta_PS2_NPSF: - snprintf(temp,TEMPSIZE,"Namco Production Sound File (NPSF) header"); - break; - case meta_RWSD: - snprintf(temp,TEMPSIZE,"Nintendo RWSD header (single stream)"); - break; - case meta_RWAR: - snprintf(temp,TEMPSIZE,"Nintendo RWAR header (single RWAV stream)"); - break; - case meta_RWAV: - snprintf(temp,TEMPSIZE,"Nintendo RWAV header"); - break; - case meta_CWAV: - snprintf(temp,TEMPSIZE,"Nintendo CWAV header"); - break; - case meta_FWAV: - snprintf(temp,TEMPSIZE,"Nintendo FWAV header"); - break; - case meta_PSX_XA: - snprintf(temp,TEMPSIZE,"RIFF/CDXA header"); - break; - case meta_PS2_RXW: - snprintf(temp,TEMPSIZE,"RXWS header)"); - break; - case meta_PS2_RAW: - snprintf(temp,TEMPSIZE,"assumed RAW Interleaved PCM by .int extension"); - break; - case meta_PS2_OMU: - snprintf(temp,TEMPSIZE,"Alter Echo OMU Header"); - break; - case meta_DSP_STM: - snprintf(temp,TEMPSIZE,"Nintendo STM header"); - break; - case meta_PS2_EXST: - snprintf(temp,TEMPSIZE,"EXST header"); - break; - case meta_PS2_SVAG: - snprintf(temp,TEMPSIZE,"Konami SVAG header"); - break; - case meta_PS2_MIB: - snprintf(temp,TEMPSIZE,"assumed MIB Interleaved file by .mib extension"); - break; - case meta_PS2_MIB_MIH: - snprintf(temp,TEMPSIZE,"assumed MIB with MIH Info Header file by .mib+.mih extension"); - break; - case meta_DSP_MPDSP: - snprintf(temp,TEMPSIZE,"Single DSP header stereo by .mpdsp extension"); - break; - case meta_PS2_MIC: - snprintf(temp,TEMPSIZE,"assume KOEI MIC file by .mic extension"); - break; - case meta_DSP_JETTERS: - snprintf(temp,TEMPSIZE,"Double DSP header stereo by _lr.dsp extension"); - break; - case meta_DSP_MSS: - snprintf(temp,TEMPSIZE,"Double DSP header stereo by .mss extension"); - break; - case meta_DSP_GCM: - snprintf(temp,TEMPSIZE,"Double DSP header stereo by .gcm extension"); - break; - case meta_DSP_WII_IDSP: - snprintf(temp,TEMPSIZE,"Wii IDSP Double DSP header"); - break; - case meta_RSTM_SPM: - snprintf(temp,TEMPSIZE,"Nintendo RSTM header and .brstmspm extension"); - break; - case meta_RAW: - snprintf(temp,TEMPSIZE,"assumed RAW PCM file by .raw extension"); - break; - case meta_PS2_VAGi: - snprintf(temp,TEMPSIZE,"Sony VAG Interleaved header (VAGi)"); - break; - case meta_PS2_VAGp: - snprintf(temp,TEMPSIZE,"Sony VAG Mono header (VAGp)"); - break; - case meta_PS2_VAGs: - snprintf(temp,TEMPSIZE,"Sony VAG Stereo header (VAGp)"); - break; - case meta_PS2_VAGm: - snprintf(temp,TEMPSIZE,"Sony VAG Mono header (VAGm)"); - break; - case meta_PS2_pGAV: - snprintf(temp,TEMPSIZE,"Sony VAG Stereo Little Endian header (pGAV)"); - break; - case meta_PSX_GMS: - snprintf(temp,TEMPSIZE,"assumed Grandia GMS file by .gms extension"); - break; - case meta_PS2_STR: - snprintf(temp,TEMPSIZE,"assumed STR + STH File by .str & .sth extension"); - break; - case meta_PS2_ILD: - snprintf(temp,TEMPSIZE,"ILD header"); - break; - case meta_PS2_PNB: - snprintf(temp,TEMPSIZE,"assumed PNB (PsychoNauts Bgm File) by .pnb extension"); - break; - case meta_XBOX_WAVM: - snprintf(temp,TEMPSIZE,"assumed Xbox WAVM file by .wavm extension"); - break; - case meta_XBOX_RIFF: - snprintf(temp,TEMPSIZE,"Xbox RIFF/WAVE file with 0x0069 Codec ID"); - break; - case meta_DSP_STR: - snprintf(temp,TEMPSIZE,"assumed Conan Gamecube STR File by .str extension"); - break; - case meta_EAXA_R2: - snprintf(temp,TEMPSIZE,"Electronic Arts XA R2"); - break; - case meta_EAXA_R3: - snprintf(temp,TEMPSIZE,"Electronic Arts XA R3"); - break; - case meta_EA_ADPCM: - snprintf(temp,TEMPSIZE,"Electronic Arts XA R1"); - break; - case meta_EA_IMA: - snprintf(temp,TEMPSIZE,"Electronic Arts container with IMA blocks"); - break; - case meta_EAXA_PSX: - snprintf(temp,TEMPSIZE,"Electronic Arts With PSX ADPCM"); - break; - case meta_EA_PCM: - snprintf(temp,TEMPSIZE,"Electronic Arts With PCM"); - break; - case meta_CFN: - snprintf(temp,TEMPSIZE,"Namco CAF Header"); - break; - case meta_PS2_VPK: - snprintf(temp,TEMPSIZE,"VPK Header"); - break; - case meta_GENH: - snprintf(temp,TEMPSIZE,"GENH Generic Header"); - break; -#ifdef VGM_USE_VORBIS - case meta_ogg_vorbis: - snprintf(temp,TEMPSIZE,"Ogg Vorbis"); - break; - case meta_OGG_SLI: - snprintf(temp,TEMPSIZE,"Ogg Vorbis with .sli (start,length) for looping"); - break; - case meta_OGG_SLI2: - snprintf(temp,TEMPSIZE,"Ogg Vorbis with .sli (from,to) for looping"); - break; - case meta_OGG_SFL: - snprintf(temp,TEMPSIZE,"Ogg Vorbis with SFPL for looping"); - break; - case meta_um3_ogg: - snprintf(temp,TEMPSIZE,"Ogg Vorbis, Ultramarine3 \"encryption\""); - break; - case meta_KOVS_ogg: - snprintf(temp,TEMPSIZE,"Ogg Vorbis, KOVS header"); - break; - case meta_psych_ogg: - snprintf(temp,TEMPSIZE,"Ogg Vorbis, Psychic Software obfuscation"); - break; -#endif - case meta_DSP_SADB: - snprintf(temp,TEMPSIZE,"sadb header"); - break; - case meta_SADL: - snprintf(temp,TEMPSIZE,"sadl header"); - break; - case meta_PS2_BMDX: - snprintf(temp,TEMPSIZE,"Beatmania .bmdx header"); - break; - case meta_DSP_WSI: - snprintf(temp,TEMPSIZE,".wsi header"); - break; - case meta_AIFC: - snprintf(temp,TEMPSIZE,"Audio Interchange File Format AIFF-C"); - break; - case meta_AIFF: - snprintf(temp,TEMPSIZE,"Audio Interchange File Format"); - break; - case meta_STR_SNDS: - snprintf(temp,TEMPSIZE,".str SNDS SHDR chunk"); - break; - case meta_WS_AUD: - snprintf(temp,TEMPSIZE,"Westwood Studios .aud header"); - break; - case meta_WS_AUD_old: - snprintf(temp,TEMPSIZE,"Westwood Studios .aud (old) header"); - break; -#ifdef VGM_USE_MPEG - case meta_AHX: - snprintf(temp,TEMPSIZE,"CRI AHX header"); - break; -#endif - case meta_PS2_IVB: - snprintf(temp,TEMPSIZE,"IVB/BVII header"); - break; - case meta_PS2_SVS: - snprintf(temp,TEMPSIZE,"Square SVS header"); - break; - case meta_RIFF_WAVE: - snprintf(temp,TEMPSIZE,"RIFF WAVE header"); - break; - case meta_RIFF_WAVE_POS: - snprintf(temp,TEMPSIZE,"RIFF WAVE header and .pos for looping"); - break; - case meta_NWA: - snprintf(temp,TEMPSIZE,"Visual Art's NWA header"); - break; - case meta_NWA_NWAINFOINI: - snprintf(temp,TEMPSIZE,"Visual Art's NWA header and NWAINFO.INI for looping"); - break; - case meta_NWA_GAMEEXEINI: - snprintf(temp,TEMPSIZE,"Visual Art's NWA header and Gameexe.ini for looping"); - break; - case meta_XSS: - snprintf(temp,TEMPSIZE,"Dino Crisis 3 XSS File"); - break; - case meta_HGC1: - snprintf(temp,TEMPSIZE,"Knights of the Temple 2 hgC1 Header"); - break; - case meta_AUS: - snprintf(temp,TEMPSIZE,"Capcom AUS Header"); - break; - case meta_RWS: - snprintf(temp,TEMPSIZE,"RWS Header"); - break; - case meta_EACS_PC: - snprintf(temp,TEMPSIZE,"EACS Header (PC)"); - break; - case meta_EACS_PSX: - snprintf(temp,TEMPSIZE,"EACS Header (PSX)"); - break; - case meta_EACS_SAT: - snprintf(temp,TEMPSIZE,"EACS Header (SATURN)"); - break; - case meta_SL3: - snprintf(temp,TEMPSIZE,"SL3 Header"); - break; - case meta_FSB1: - snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB1) Header"); - break; - case meta_FSB3_0: - snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB3.0) Header"); - break; - case meta_FSB3_1: - snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB3.1) Header"); - break; - case meta_FSB4: - snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB4) Header"); - break; - case meta_FSB4_WAV: - snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB4) with additional 'WAV' Header"); - break; - case meta_FSB5: - snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB5) Header"); - break; - case meta_RWX: - snprintf(temp,TEMPSIZE,"RWX Header"); - break; - case meta_XWB: - snprintf(temp,TEMPSIZE,"XWB WBND Header"); - break; - case meta_XA30: - snprintf(temp,TEMPSIZE,"XA30 Header"); - break; - case meta_MUSC: - snprintf(temp,TEMPSIZE,"MUSC Header"); - break; - case meta_MUSX_V004: - snprintf(temp,TEMPSIZE,"MUSX / Version 004 Header"); - break; - case meta_MUSX_V005: - snprintf(temp,TEMPSIZE,"MUSX / Version 005 Header"); - break; - case meta_MUSX_V006: - snprintf(temp,TEMPSIZE,"MUSX / Version 006 Header"); - break; - case meta_MUSX_V010: - snprintf(temp,TEMPSIZE,"MUSX / Version 010 Header"); - break; - case meta_MUSX_V201: - snprintf(temp,TEMPSIZE,"MUSX / Version 201 Header"); - break; - case meta_LEG: - snprintf(temp,TEMPSIZE,"Legaia 2 - Duel Saga LEG Header"); - break; - case meta_FILP: - snprintf(temp,TEMPSIZE,"Bio Hazard - Gun Survivor FILp Header"); - break; - case meta_IKM: - snprintf(temp,TEMPSIZE,"Zwei!! IKM Header"); - break; - case meta_SFS: - snprintf(temp,TEMPSIZE,"Baroque SFS Header"); - break; - case meta_DVI: - snprintf(temp,TEMPSIZE,"DVI Header"); - break; - case meta_KCEY: - snprintf(temp,TEMPSIZE,"KCEYCOMP Header"); - break; - case meta_BG00: - snprintf(temp,TEMPSIZE,"Falcom BG00 Header"); - break; - case meta_PS2_RSTM: - snprintf(temp,TEMPSIZE,"Rockstar Games RSTM Header"); - break; - case meta_ACM: - snprintf(temp,TEMPSIZE,"InterPlay ACM Header"); - break; - case meta_MUS_ACM: - snprintf(temp,TEMPSIZE,"MUS playlist and multiple InterPlay ACM Headered files"); - break; - case meta_PS2_KCES: - snprintf(temp,TEMPSIZE,"Konami KCES Header"); - break; - case meta_PS2_DXH: - snprintf(temp,TEMPSIZE,"Tokobot Plus DXH Header"); - break; - case meta_PS2_PSH: - snprintf(temp,TEMPSIZE,"Dawn of Mana - Seiken Densetsu 4 PSH Header"); - break; - case meta_RIFF_WAVE_labl_Marker: - snprintf(temp,TEMPSIZE,"RIFF WAVE header with loop markers"); - break; - case meta_RIFF_WAVE_smpl: - snprintf(temp,TEMPSIZE,"RIFF WAVE header with sample looping info"); - break; - case meta_RIFX_WAVE: - snprintf(temp,TEMPSIZE,"RIFX WAVE header"); - break; - case meta_RIFX_WAVE_smpl: - snprintf(temp,TEMPSIZE,"RIFX WAVE header with sample looping info"); - break; - case meta_XNBm: - snprintf(temp,TEMPSIZE,"XNBm header"); - break; - case meta_PCM_SCD: - snprintf(temp,TEMPSIZE,"PCM file with custom header (SCD)"); - break; - case meta_PCM_PS2: - snprintf(temp,TEMPSIZE,"PCM file with custom header (PS2)"); - break; - case meta_PS2_RKV: - snprintf(temp,TEMPSIZE,"Legacy of Kain - Blood Omen 2 RKV Header"); - break; - case meta_PS2_PSW: - snprintf(temp,TEMPSIZE,"Rayman Raving Rabbids Riff Container File"); - break; - case meta_PS2_VAS: - snprintf(temp,TEMPSIZE,"Pro Baseball Spirits 5 VAS Header"); - break; - case meta_PS2_TEC: - snprintf(temp,TEMPSIZE,"assumed TECMO badflagged stream by .tec extension"); - break; - case meta_XBOX_WVS: - snprintf(temp,TEMPSIZE,"Metal Arms WVS Header (XBOX)"); - break; - case meta_NGC_WVS: - snprintf(temp,TEMPSIZE,"Metal Arms WVS Header (GameCube)"); - break; - case meta_XBOX_STMA: - snprintf(temp,TEMPSIZE,"Midnight Club 2 STMA Header"); - break; - case meta_XBOX_MATX: - snprintf(temp,TEMPSIZE,"assumed Matrix file by .matx extension"); - break; - case meta_DE2: - snprintf(temp,TEMPSIZE,"gurumin .de2 with embedded funky RIFF"); - break; - case meta_VS: - snprintf(temp,TEMPSIZE,"Men in Black VS Header"); - break; - case meta_DC_STR: - snprintf(temp,TEMPSIZE,"Sega Stream Asset Builder header"); - break; - case meta_DC_STR_V2: - snprintf(temp,TEMPSIZE,"variant of Sega Stream Asset Builder header"); - break; - case meta_XBOX_XMU: - snprintf(temp,TEMPSIZE,"XMU header"); - break; - case meta_XBOX_XVAS: - snprintf(temp,TEMPSIZE,"assumed TMNT file by .xvas extension"); - break; - case meta_PS2_XA2: - snprintf(temp,TEMPSIZE,"Acclaim XA2 Header"); - break; - case meta_DC_IDVI: - snprintf(temp,TEMPSIZE,"IDVI Header"); - break; - case meta_NGC_YMF: - snprintf(temp,TEMPSIZE,"YMF DSP Header"); - break; - case meta_PS2_CCC: - snprintf(temp,TEMPSIZE,"CCC Header"); - break; - case meta_PSX_FAG: - snprintf(temp,TEMPSIZE,"FAG Header"); - break; - case meta_PS2_MIHB: - snprintf(temp,TEMPSIZE,"Merged MIH+MIB"); - break; - case meta_DSP_WII_MUS: - snprintf(temp,TEMPSIZE,"mus header"); - break; - case meta_WII_SNG: - snprintf(temp,TEMPSIZE,"SNG DSP Header"); - break; - case meta_RSD2VAG: - snprintf(temp,TEMPSIZE,"RSD2/VAG Header"); - break; - case meta_RSD2PCMB: - snprintf(temp,TEMPSIZE,"RSD2/PCMB Header"); - break; - case meta_RSD2XADP: - snprintf(temp,TEMPSIZE,"RSD2/XADP Header"); - break; - case meta_RSD3VAG: - snprintf(temp,TEMPSIZE,"RSD3/VAG Header"); - break; - case meta_RSD3GADP: - snprintf(temp,TEMPSIZE,"RSD3/GADP Header"); - break; - case meta_RSD3PCM: - snprintf(temp,TEMPSIZE,"RSD3/PCM Header"); - break; - case meta_RSD3PCMB: - snprintf(temp,TEMPSIZE,"RSD3/PCMB Header"); - break; - case meta_RSD4PCMB: - snprintf(temp,TEMPSIZE,"RSD4/PCMB Header"); - break; - case meta_RSD4PCM: - snprintf(temp,TEMPSIZE,"RSD4/PCM Header"); - break; - case meta_RSD4RADP: - snprintf(temp,TEMPSIZE,"RSD4/RADP Header"); - break; - case meta_RSD4VAG: - snprintf(temp,TEMPSIZE,"RSD4/VAG Header"); - break; - case meta_RSD6XADP: - snprintf(temp,TEMPSIZE,"RSD6/XADP Header"); - break; - case meta_RSD6VAG: - snprintf(temp,TEMPSIZE,"RSD6/VAG Header"); - break; - case meta_RSD6WADP: - snprintf(temp,TEMPSIZE,"RSD6/WADP Header"); - break; - case meta_RSD6RADP: - snprintf(temp,TEMPSIZE,"RSD6/RADP Header"); - break; - case meta_DC_ASD: - snprintf(temp,TEMPSIZE,"ASD Header"); - break; - case meta_NAOMI_SPSD: - snprintf(temp,TEMPSIZE,"SPSD Header"); - break; - case meta_FFXI_BGW: - snprintf(temp,TEMPSIZE,"BGW BGMStream header"); - break; - case meta_FFXI_SPW: - snprintf(temp,TEMPSIZE,"SPW SeWave header"); - break; - case meta_PS2_ASS: - snprintf(temp,TEMPSIZE,"ASS Header"); - break; - case meta_IDSP: - snprintf(temp,TEMPSIZE,"IDSP Header"); - break; - case meta_WAA_WAC_WAD_WAM: - snprintf(temp,TEMPSIZE,"WAA/WAC/WAD/WAM RIFF Header"); - break; - case meta_PS2_SEG: - snprintf(temp,TEMPSIZE,"SEG (PS2) Header"); - break; - case meta_XBOX_SEG: - snprintf(temp,TEMPSIZE,"SEG (XBOX) Header"); - break; - case meta_NDS_STRM_FFTA2: - snprintf(temp,TEMPSIZE,"Final Fantasy Tactics A2 RIFF Header"); - break; - case meta_STR_ASR: - snprintf(temp,TEMPSIZE,"Donkey Kong Jet Race KNON/WII Header"); - break; - case meta_ZWDSP: - snprintf(temp,TEMPSIZE,"Zack and Wiki custom DSP Header"); - break; - case meta_GCA: - snprintf(temp,TEMPSIZE,"GCA DSP Header"); - break; - case meta_SPT_SPD: - snprintf(temp,TEMPSIZE,"SPT+SPD DSP Header"); - break; - case meta_ISH_ISD: - snprintf(temp,TEMPSIZE,"ISH+ISD DSP Header"); - break; - case meta_YDSP: - snprintf(temp,TEMPSIZE,"Yuke's DSP (YDSP) Header"); - break; - case meta_MSVP: - snprintf(temp,TEMPSIZE,"MSVP Header"); - break; - case meta_NGC_SSM: - snprintf(temp,TEMPSIZE,"SSM DSP Header"); - break; - case meta_PS2_JOE: - snprintf(temp,TEMPSIZE,"Disney/Pixar JOE Header"); - break; - case meta_VGS: - snprintf(temp,TEMPSIZE,"Guitar Hero Encore Rocks the 80's Header"); - break; - case meta_DC_DCSW_DCS: - snprintf(temp,TEMPSIZE,"Evil Twin DCS file with helper"); - break; - case meta_WII_SMP: - snprintf(temp,TEMPSIZE,"SMP DSP Header"); - break; - case meta_EMFF_PS2: - case meta_EMFF_NGC: - snprintf(temp,TEMPSIZE,"Eidos Music File Format Header"); - break; - case meta_THP: - snprintf(temp,TEMPSIZE,"THP Movie File Format Header"); - break; - case meta_STS_WII: - snprintf(temp,TEMPSIZE,"Shikigami no Shiro (WII) Header"); - break; - case meta_PS2_P2BT: - snprintf(temp,TEMPSIZE,"Pop'n'Music 7 Header"); - break; - case meta_PS2_GBTS: - snprintf(temp,TEMPSIZE,"Pop'n'Music 9 Header"); - break; - case meta_NGC_DSP_IADP: - snprintf(temp,TEMPSIZE,"IADP Header"); - break; - case meta_RSTM_shrunken: - snprintf(temp,TEMPSIZE,"Nintendo RSTM header, corrupted by Atlus"); - break; - case meta_RIFF_WAVE_MWV: - snprintf(temp,TEMPSIZE,"RIFF WAVE header with .mwv flavoring"); - break; - case meta_RIFF_WAVE_SNS: - snprintf(temp,TEMPSIZE,"RIFF WAVE header with .sns flavoring"); - break; - case meta_FFCC_STR: - snprintf(temp,TEMPSIZE,"Final Fantasy: Crystal Chronicles STR header"); - break; - case meta_SAT_BAKA: - snprintf(temp,TEMPSIZE,"BAKA header from Crypt Killer"); - break; - case meta_NDS_SWAV: - snprintf(temp,TEMPSIZE,"SWAV Header"); - break; - case meta_PS2_VSF: - snprintf(temp,TEMPSIZE,"Musashi: Samurai Legend VSF Header"); - break; - case meta_NDS_RRDS: - snprintf(temp,TEMPSIZE,"Ridger Racer DS Header"); - break; - case meta_PS2_TK5: - snprintf(temp,TEMPSIZE,"Tekken 5 Stream Header"); - break; - case meta_PS2_SND: - snprintf(temp,TEMPSIZE,"Might and Magic SSND Header"); - break; - case meta_PS2_VSF_TTA: - snprintf(temp,TEMPSIZE,"VSF with SMSS Header"); - break; - case meta_ADS: - snprintf(temp,TEMPSIZE,"dhSS Header"); - break; - case meta_WII_STR: - snprintf(temp,TEMPSIZE,"HOTD Overkill - STR+STH WII Header"); - break; - case meta_PS2_MCG: - snprintf(temp,TEMPSIZE,"Gunvari MCG Header"); - break; - case meta_ZSD: - snprintf(temp,TEMPSIZE,"ZSD Header"); - break; - case meta_RedSpark: - snprintf(temp,TEMPSIZE,"RedSpark Header"); - break; - case meta_PC_IVAUD: - snprintf(temp,TEMPSIZE,"assumed GTA IV Audio file by .ivaud extension"); - break; - case meta_DSP_WII_WSD: - snprintf(temp,TEMPSIZE,"Standard Nintendo DSP headers in .wsd"); - break; - case meta_WII_NDP: - snprintf(temp,TEMPSIZE,"Vertigo NDP Header"); - break; - case meta_PS2_SPS: - snprintf(temp,TEMPSIZE,"Ape Escape 2 SPS Header"); - break; - case meta_PS2_XA2_RRP: - snprintf(temp,TEMPSIZE,"Acclaim XA2 Header"); - break; - case meta_NDS_HWAS: - snprintf(temp,TEMPSIZE,"NDS 'HWAS' Header"); - break; - case meta_NGC_LPS: - snprintf(temp,TEMPSIZE,"Rave Master LPS Header"); - break; - case meta_NAOMI_ADPCM: - snprintf(temp,TEMPSIZE,"NAOMI/NAOMI2 Arcade games ADPCM header"); - break; - case meta_SD9: - snprintf(temp,TEMPSIZE,"beatmania IIDX SD9 header"); - break; - case meta_2DX9: - snprintf(temp,TEMPSIZE,"beatmania IIDX 2DX9 header"); - break; - case meta_DSP_YGO: - snprintf(temp,TEMPSIZE,"Konami custom DSP Header"); - break; - case meta_PS2_VGV: - snprintf(temp,TEMPSIZE,"Rune: Viking Warlord VGV Header"); - break; - case meta_NGC_GCUB: - snprintf(temp,TEMPSIZE,"GCub Header"); - break; - case meta_NGC_SCK_DSP: - snprintf(temp,TEMPSIZE,"The Scorpion King SCK Header"); - break; - case meta_NGC_SWD: - snprintf(temp,TEMPSIZE,"PSF + Standard DSP Headers"); - break; - case meta_CAFF: - snprintf(temp,TEMPSIZE,"Apple Core Audio Format Header"); - break; - case meta_PC_MXST: - snprintf(temp,TEMPSIZE,"Lego Island MxSt Header"); - break; - case meta_PC_SOB_SAB: - snprintf(temp,TEMPSIZE,"Worms 4: Mayhem SOB/SAB Header"); - break; - case meta_MAXIS_XA: - snprintf(temp,TEMPSIZE,"Maxis XAI/XAJ Header"); - break; - case meta_EXAKT_SC: - snprintf(temp,TEMPSIZE,"assumed Activision / EXAKT SC by extension"); - break; - case meta_WII_BNS: - snprintf(temp,TEMPSIZE,"Nintendo BNS header"); - break; - case meta_WII_WAS: - snprintf(temp,TEMPSIZE,"WAS (iSWS) DSP header"); - break; - case meta_XBOX_HLWAV: - snprintf(temp,TEMPSIZE,"Half Life 2 bgm header"); - break; - case meta_STX: - snprintf(temp,TEMPSIZE,"Nintendo .stx header"); - break; - case meta_PS2_STM: - snprintf(temp,TEMPSIZE,"Red Dead Revolver .stm (.ps2stm)"); - break; - case meta_MYSPD: - snprintf(temp,TEMPSIZE,"U-Sing .myspd header"); - break; - case meta_HIS: - snprintf(temp,TEMPSIZE,"Her Interactive Sound header"); - break; - case meta_PS2_AST: - snprintf(temp,TEMPSIZE,"KOEI AST header"); - break; - case meta_CAPDSP: - snprintf(temp,TEMPSIZE,"Capcom custom DSP header"); - break; - case meta_DMSG: - snprintf(temp,TEMPSIZE,"RIFF/DMSGsegh header"); - break; - case meta_PONA_3DO: - case meta_PONA_PSX: - snprintf(temp,TEMPSIZE,"Policenauts BGM header"); - break; - case meta_NGC_DSP_AAAP: - snprintf(temp,TEMPSIZE,"Double standard dsp header in 'AAAp'"); - break; - case meta_NGC_DSP_KONAMI: - snprintf(temp,TEMPSIZE,"Konami dsp header"); - break; - case meta_PS2_STER: - snprintf(temp,TEMPSIZE,"STER Header"); - break; - case meta_BNSF: - snprintf(temp,TEMPSIZE,"Namco Bandai BNSF header"); - break; - case meta_PS2_WB: - snprintf(temp,TEMPSIZE,"Shooting Love. ~TRIZEAL~ WB header"); - break; - case meta_S14: - snprintf(temp,TEMPSIZE,"assumed Polycom Siren 14 by .s14 extension"); - break; - case meta_SSS: - snprintf(temp,TEMPSIZE,"assumed Polycom Siren 14 by .sss extension"); - break; - case meta_PS2_GCM: - snprintf(temp,TEMPSIZE,"GCM 'MCG' Header"); - break; - case meta_PS2_SMPL: - snprintf(temp,TEMPSIZE,"Homura 'SMPL' Header"); - break; - case meta_PS2_MSA: - snprintf(temp,TEMPSIZE,"Psyvariar -Complete Edition- MSA header"); - break; - case meta_PC_SMP: - snprintf(temp,TEMPSIZE,"Ghostbusters .smp Header"); - break; - case meta_NGC_PDT: - snprintf(temp,TEMPSIZE,"PDT DSP header"); - break; - case meta_NGC_BO2: - snprintf(temp,TEMPSIZE,"Blood Omen 2 DSP header"); - break; - case meta_P3D: - snprintf(temp,TEMPSIZE,"Prototype P3D Header"); - break; - case meta_PS2_TK1: - snprintf(temp,TEMPSIZE,"Tekken TK5STRM1 Header"); - break; - case meta_PS2_ADSC: - snprintf(temp,TEMPSIZE,"ADSC Header"); - break; - case meta_NGC_DSP_MPDS: - snprintf(temp,TEMPSIZE,"MPDS DSP header"); - break; - case meta_DSP_STR_IG: - snprintf(temp,TEMPSIZE,"Infogrames dual dsp header"); - break; - case meta_PSX_MGAV: - snprintf(temp,TEMPSIZE,"Electronic Arts RVWS header"); - break; - case meta_PS2_B1S: - snprintf(temp,TEMPSIZE,"B1S header"); - break; - case meta_PS2_WAD: - snprintf(temp,TEMPSIZE,"WAD header"); - break; - case meta_DSP_XIII: - snprintf(temp,TEMPSIZE,"XIII dsp header"); - break; - case meta_NGC_DSP_STH_STR: - snprintf(temp,TEMPSIZE,"STH dsp header"); - break; - case meta_DSP_CABELAS: - snprintf(temp,TEMPSIZE,"Cabelas games dsp header"); - break; - case meta_PS2_LPCM: - snprintf(temp,TEMPSIZE,"LPCM header"); - break; - case meta_PS2_VMS: - snprintf(temp,TEMPSIZE,"VMS Header"); - break; - case meta_PS2_XAU: - snprintf(temp,TEMPSIZE,"XAU Header"); - break; - case meta_GH3_BAR: - snprintf(temp,TEMPSIZE,"Guitar Hero III Mobile .bar"); - break; - case meta_FFW: - snprintf(temp,TEMPSIZE,"Freedom Fighters BGM header"); - break; - case meta_DSP_DSPW: - snprintf(temp,TEMPSIZE,"DSPW dsp header"); - break; - case meta_PS2_JSTM: - snprintf(temp,TEMPSIZE,"JSTM Header"); - break; - case meta_PS3_XVAG: - snprintf(temp,TEMPSIZE,"XVAG Header"); - break; - case meta_PS3_CPS: - snprintf(temp,TEMPSIZE,"CPS Header"); - break; - case meta_SQEX_SCD: - snprintf(temp,TEMPSIZE,"Square-Enix SCD"); - break; - case meta_NGC_NST_DSP: - snprintf(temp,TEMPSIZE,"Animaniacs NST header"); - break; - case meta_BAF: - snprintf(temp,TEMPSIZE,".baf WAVE header"); - break; - case meta_PS3_MSF: - snprintf(temp,TEMPSIZE,"PS3 MSF header"); - break; - case meta_FSB_MPEG: - snprintf(temp,TEMPSIZE,"FSB MPEG header"); - break; - case meta_NUB_VAG: - snprintf(temp,TEMPSIZE,"VAG (NUB) header"); - break; - case meta_PS3_PAST: - snprintf(temp,TEMPSIZE,"SNDP header"); - break; - case meta_PS3_SGDX: - snprintf(temp,TEMPSIZE,"SGXD header"); - break; - case meta_NGCA: - snprintf(temp,TEMPSIZE,"NGCA header"); - break; - case meta_WII_RAS: - snprintf(temp,TEMPSIZE,"RAS header"); - break; - case meta_PS2_SPM: - snprintf(temp,TEMPSIZE,"SPM header"); - break; - case meta_X360_TRA: - snprintf(temp,TEMPSIZE,"assumed DefJam Rapstar Audio File by .tra extension"); - break; - case meta_PS2_VGS: - snprintf(temp,TEMPSIZE,"Princess Soft VGS header"); - break; - case meta_PS2_IAB: - snprintf(temp,TEMPSIZE,"IAB header"); - break; - case meta_PS2_STRLR: - snprintf(temp,TEMPSIZE,"STR L/R header"); - break; - case meta_LSF_N1NJ4N: - snprintf(temp,TEMPSIZE,".lsf !n1nj4n header"); - break; - case meta_PS3_VAWX: - snprintf(temp,TEMPSIZE,"VAWX header"); - break; - case meta_PC_SNDS: - snprintf(temp,TEMPSIZE,"assumed Heavy Iron IMA by .snds extension"); - break; - case meta_PS2_WMUS: - snprintf(temp,TEMPSIZE,"assumed The Warriors Sony ADPCM by .wmus extension"); - break; - case meta_HYPERSCAN_KVAG: - snprintf(temp,TEMPSIZE,"Mattel Hyperscan KVAG"); - break; - case meta_IOS_PSND: - snprintf(temp,TEMPSIZE,"PSND Header"); - break; - case meta_BOS_ADP: - snprintf(temp,TEMPSIZE,"ADP! header"); - break; - case meta_EB_SFX: - snprintf(temp,TEMPSIZE,"Excitebots .sfx header"); - break; - case meta_EB_SF0: - snprintf(temp,TEMPSIZE,"assumed Excitebots .sf0 by extension"); - break; - case meta_PS3_KLBS: - snprintf(temp,TEMPSIZE,"klBS Header"); - break; - case meta_PS2_MTAF: - snprintf(temp,TEMPSIZE,"Konami MTAF header"); - break; - case meta_PS2_VAG1: - snprintf(temp,TEMPSIZE,"Konami VAG Mono header (VAG1)"); - break; - case meta_PS2_VAG2: - snprintf(temp,TEMPSIZE,"Konami VAG Stereo header (VAG2)"); - break; - case meta_TUN: - snprintf(temp,TEMPSIZE,"TUN 'ALP' header"); - break; - case meta_WPD: - snprintf(temp,TEMPSIZE,"WPD 'DPW' header"); - break; - case meta_MN_STR: - snprintf(temp,TEMPSIZE,"Mini Ninjas 'STR' header"); - break; - case meta_PS2_MSS: - snprintf(temp,TEMPSIZE,"Guerilla MSCC header"); - break; - case meta_PS2_HSF: - snprintf(temp,TEMPSIZE,"Lowrider 'HSF' header"); - break; - case meta_PS3_IVAG: - snprintf(temp,TEMPSIZE,"PS3 'IVAG' Header"); - break; - case meta_PS2_2PFS: - snprintf(temp,TEMPSIZE,"PS2 '2PFS' Header"); - break; - case meta_RSD6OOGV: - snprintf(temp,TEMPSIZE,"RSD6/OOGV Header"); - break; - case meta_UBI_CKD: - snprintf(temp,TEMPSIZE,"CKD 'RIFF' Header"); - break; - case meta_PS2_VBK: - snprintf(temp,TEMPSIZE,"PS2 VBK Header"); - break; - case meta_OTM: - snprintf(temp,TEMPSIZE,"Otomedius OTM Header"); - break; - case meta_CSTM: - snprintf(temp,TEMPSIZE,"Nintendo 3DS CSTM Header"); - break; - case meta_FSTM: - snprintf(temp,TEMPSIZE,"Nintendo Wii U FSTM Header"); - break; - case meta_G1L: - snprintf(temp,TEMPSIZE,"Tecmo Koei G1L Header"); - break; - case meta_3DS_IDSP: - snprintf(temp,TEMPSIZE,"Nintendo 3DS IDSP Header"); - break; - case meta_WIIU_BTSND: - snprintf(temp,TEMPSIZE,"Wii U Menu Boot Sound"); - break; - case meta_MCA: - snprintf(temp,TEMPSIZE,"Capcom MCA Header"); - break; - case meta_XB3D_ADX: - snprintf(temp, TEMPSIZE,"Xenoblade 3D ADX Header"); - break; - case meta_HCA: - snprintf(temp, TEMPSIZE,"CRI MiddleWare HCA Header"); - break; -#ifdef VGM_USE_FFMPEG - case meta_FFmpeg: - snprintf(temp, TEMPSIZE,"FFmpeg supported file format"); - break; -#endif - default: - snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET"); } concatn(length,desc,temp); } -/* */ +/* filename search pairs for dual file stereo */ const char * const dfs_pairs[][2] = { {"L","R"}, {"l","r"}, @@ -3574,7 +2209,7 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) if (!sample_rate || !channels || !length_samples) return 0; - + if (channels >= 1) { streamFile = get_vgmstream_streamfile(vgmstream, 0); if (streamFile) { @@ -3603,3 +2238,72 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) return bitrate; } + + +int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset) { + STREAMFILE * file; + char filename[PATH_LIMIT]; + int ch; + int use_streamfile_per_channel = 0; + int use_same_offset_per_channel = 0; + +#ifdef VGM_USE_FFMPEG + if (vgmstream->coding_type == coding_FFmpeg) /* stream not needed, FFmpeg manages itself */ + return 1; +#endif + + /* if interleave is big enough keep a buffer per channel */ + if (vgmstream->interleave_block_size >= STREAMFILE_DEFAULT_BUFFER_SIZE) { + use_streamfile_per_channel = 1; + } + + if (vgmstream->layout_type == layout_none + //#ifdef VGM_USE_MPEG || (vgmstream->layout_type == layout_mpeg) #endif //no appreciable difference + ) { + /* for some codecs like IMA where channels work with the same bytes *///todo which ones? + use_same_offset_per_channel = 1; + } + + + streamFile->get_name(streamFile,filename,sizeof(filename)); + /* open the file for reading by each channel */ + { + if (!use_streamfile_per_channel) { + file = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + } + + for (ch=0; ch < vgmstream->channels; ch++) { + off_t offset; + if (use_same_offset_per_channel) { + offset = start_offset; + } else { + offset = start_offset + vgmstream->interleave_block_size*ch; + } + + /* open new one if needed */ + if (use_streamfile_per_channel) { + file = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + } + + vgmstream->ch[ch].streamfile = file; + vgmstream->ch[ch].channel_start_offset = + vgmstream->ch[ch].offset = offset; + } + } + + return 1; + +fail: + if (!use_streamfile_per_channel) { + streamFile->close(file); /* only one file was ever open */ + } else { + for (ch=0; ch < vgmstream->channels; ch++) { + if (vgmstream->ch[ch].streamfile) + streamFile->close(vgmstream->ch[ch].streamfile); /* close all open files */ + } + } + + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 7ca003f8e..3aa31556b 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -7,11 +7,12 @@ enum { PATH_LIMIT = 32768 }; -/* Due mostly to licensing issues, Vorbis, MPEG, and G.722.1 decoding are +#include "streamfile.h" + +/* Due mostly to licensing issues, Vorbis, MPEG, G.722.1, etc decoding is * done by external libraries. * If someone wants to do a standalone build, they can do it by simply - * removing these defines (and the references to the libraries in the - * Makefile) */ + * removing these defines (and the references to the libraries in the Makefile) */ #define VGM_USE_VORBIS /* can be disabled to decode with FFmpeg instead */ @@ -19,27 +20,25 @@ enum { PATH_LIMIT = 32768 }; #define VGM_USE_MPEG #endif -/* disabled by default, defined for builds that support it */ +/* disabled by default, defined on compile-time for builds that support it*/ #define VGM_USE_G7221 #define VGM_USE_G719 +//#define VGM_USE_MP4V2 +//#define VGM_USE_FDKAAC +//#define VGM_USE_MAIATRAC3PLUS #define VGM_USE_FFMPEG -#define VGM_USE_FFMPEG_ACCURATE_LOOPING -#include "streamfile.h" -#ifdef BUILD_VGMSTREAM -#include "coding/g72x_state.h" -#else -#include "g72x_state.h" -#endif #ifdef VGM_USE_VORBIS #ifdef __APPLE__ #define __MACOSX__ #endif #include #endif + #ifdef VGM_USE_MPEG #include #endif + #ifdef VGM_USE_G7221 #include #endif @@ -60,86 +59,105 @@ enum { PATH_LIMIT = 32768 }; #include "maiatrac3plus.h" #endif -#include "clHCA.h" - #ifdef VGM_USE_FFMPEG #include #include #endif #ifdef BUILD_VGMSTREAM +#include "coding/g72x_state.h" #include "coding/acm_decoder.h" #include "coding/nwa_decoder.h" #else +#include "g72x_state.h" #include "acm_decoder.h" #include "nwa_decoder.h" #endif +#include "clHCA.h" + /* The encoding type specifies the format the sound data itself takes */ typedef enum { /* 16-bit PCM */ - coding_PCM16BE, /* big endian 16-bit PCM */ coding_PCM16LE, /* little endian 16-bit PCM */ - coding_PCM16LE_int, /* little endian 16-bit PCM with sample-level - interleave handled by the decoder */ + coding_PCM16LE_int, /* little endian 16-bit PCM with sample-level interleave */ + coding_PCM16LE_XOR_int, /* little endian 16-bit PCM with sample-level xor */ + coding_PCM16BE, /* big endian 16-bit PCM */ /* 8-bit PCM */ coding_PCM8, /* 8-bit PCM */ + coding_PCM8_int, /* 8-Bit PCM with sample-level interleave */ coding_PCM8_U, /* 8-bit PCM, unsigned (0x80 = 0) */ - coding_PCM8_int, /* 8-Bit PCM with sample-level interleave handled - by the decoder */ - coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement), - sample-level interleave */ - coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0), sample-level - interleave */ + coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0) with sample-level interleave */ + coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement) with sample-level interleave */ /* 4-bit ADPCM */ - coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ coding_CRI_ADX, /* CRI ADX */ - coding_CRI_ADX_enc_8, /* encrypted CRI ADX, type 8 (God Hand) */ - coding_CRI_ADX_enc_9, /* encrypted CRI ADX, type 9 (PSO2) */ - coding_NGC_DSP, /* NGC ADPCM, called DSP */ - coding_NGC_DTK, /* NGC hardware disc ADPCM, called DTK, TRK or ADP */ - coding_G721, /* CCITT G.721 ADPCM */ - coding_NGC_AFC, /* NGC ADPCM, called AFC */ - coding_PSX, /* PSX & PS2 ADPCM */ - coding_invert_PSX, /* PSX ADPCM with some weirdness */ - coding_PSX_badflags, /* with garbage in the flags byte */ - coding_FFXI, /* FF XI PSX-ish ADPCM */ - coding_BAF_ADPCM, /* Bizarre Creations PSX-ish ADPCM */ - coding_HEVAG_ADPCM, /* PSVita games */ - coding_SHORT_VAG_ADPCM, /* SGXD type 5 (PS3 Afrika) */ - coding_XA, /* PSX CD-XA */ - coding_XBOX, /* XBOX IMA */ - coding_INT_XBOX, /* XBOX 'real interleaved' IMA */ - coding_EAXA, /* EA/XA ADPCM */ - coding_EA_ADPCM, /* EA ADPCM */ - coding_MAXIS_ADPCM, /* MAXIS ADPCM */ - coding_NDS_PROCYON, /* NDS Procyon Studio ADPCM */ + coding_CRI_ADX_enc_8, /* CRI ADX, type 8 encryption (God Hand) */ + coding_CRI_ADX_enc_9, /* CRI ADX, type 9 encryption (PSO2) */ -#ifdef VGM_USE_VORBIS - coding_ogg_vorbis, /* vorbis */ -#endif - coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */ - coding_SDX2_int, /* SDX2 2:1 Squareroot-Delta-Exact compression, - with smaple-level interleave handled by the - decoder */ - coding_CBD2, /* CBD2 2:1 Cuberoot-Delta-Exact compression */ - coding_CBD2_int, /* CBD2 2:1 Cuberoot-Delta-Exact compression, - with sample-level interleave handled by the - decoder */ - coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */ - coding_INT_DVI_IMA, /* Interleaved DVI */ + coding_NGC_DSP, /* Nintendo DSP ADPCM */ + coding_NGC_DTK, /* Nintendo DTK ADPCM (hardware disc), also called TRK or ADP */ + coding_NGC_AFC, /* Nintendo AFC ADPCM */ + + coding_G721, /* CCITT G.721 */ + + coding_XA, /* CD-ROM XA */ + coding_PSX, /* Sony PS ADPCM (VAG) */ + coding_PSX_badflags, /* Sony PS ADPCM with garbage in the flag byte */ + coding_PSX_bmdx, /* Sony PS ADPCM with BMDX encryption */ + coding_PSX_cfg, /* Sony PS ADPCM with configurable frame size (FF XI, SGXD type 5, Bizarre Creations) */ + coding_HEVAG, /* Sony PSVita ADPCM */ + + coding_EA_XA, /* Electronic Arts XA ADPCM */ + coding_EA_ADPCM, /* Electronic Arts R1 ADPCM */ + coding_MAXIS_ADPCM, /* Maxis ADPCM */ + coding_NDS_PROCYON, /* Procyon Studio ADPCM */ + + coding_XBOX, /* XBOX IMA ADPCM */ + coding_INT_XBOX, /* XBOX IMA ADPCM (interleaved) */ + coding_IMA, /* IMA ADPCM (low nibble first) */ + coding_INT_IMA, /* IMA ADPCM (interleaved) */ + coding_DVI_IMA, /* DVI IMA ADPCM (high nibble first), aka ADP4 */ + coding_INT_DVI_IMA, /* DVI IMA ADPCM (Interleaved) */ + coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ coding_EACS_IMA, - coding_IMA, /* bare IMA, low nibble first */ - coding_INT_IMA, /* */ coding_MS_IMA, /* Microsoft IMA */ coding_RAD_IMA, /* "Radical ADPCM" IMA */ coding_RAD_IMA_mono, /* "Radical ADPCM" IMA, mono (for interleave) */ coding_APPLE_IMA4, /* Apple Quicktime IMA4 */ coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */ coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */ - coding_WS, /* Westwood Studios' custom VBR ADPCM */ + + coding_WS, /* Westwood Studios VBR ADPCM */ + coding_MSADPCM, /* Microsoft ADPCM */ + coding_AICA, /* Yamaha AICA ADPCM */ + coding_L5_555, /* Level-5 0x555 ADPCM */ + coding_SASSC, /* Activision EXAKT SASSC DPCM */ + coding_LSF, /* lsf ADPCM (Fastlane Street Racing iPhone)*/ + coding_MTAF, /* Konami MTAF ADPCM (IMA-derived) */ + + /* others */ + coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression DPCM */ + coding_SDX2_int, /* SDX2 2:1 Squareroot-Delta-Exact compression with sample-level interleave */ + coding_CBD2, /* CBD2 2:1 Cuberoot-Delta-Exact compression DPCM */ + coding_CBD2_int, /* CBD2 2:1 Cuberoot-Delta-Exact compression, with sample-level interleave */ + + coding_ACM, /* InterPlay ACM */ + + coding_NWA0, /* Visual Art's NWA (compressed at various levels) */ + coding_NWA1, + coding_NWA2, + coding_NWA3, + coding_NWA4, + coding_NWA5, + + coding_CRI_HCA, /* CRI High Compression Audio (MDCT-based) */ + +#ifdef VGM_USE_VORBIS + coding_ogg_vorbis, /* Xiph Vorbis (MDCT-based) */ +#endif + #ifdef VGM_USE_MPEG coding_fake_MPEG2_L2, /* MPEG-2 Layer 2 (AHX), with lying headers */ /* I don't even know offhand if all these combinations exist... */ @@ -153,43 +171,26 @@ typedef enum { coding_MPEG25_L2, coding_MPEG25_L3, #endif + #ifdef VGM_USE_G7221 - coding_G7221, /* G.722.1 (Polycom Siren 7) */ - coding_G7221C, /* G.722.1 with Annex C extension (Polycom Siren 14) */ + coding_G7221, /* ITU G.722.1 (Polycom Siren 7) */ + coding_G7221C, /* ITU G.722.1 annex C (Polycom Siren 14) */ #endif + #ifdef VGM_USE_G719 - coding_G719, -#endif - - coding_ACM, /* InterPlay ACM */ - /* compressed NWA at various levels */ - coding_NWA0, - coding_NWA1, - coding_NWA2, - coding_NWA3, - coding_NWA4, - coding_NWA5, - - coding_MSADPCM, /* Microsoft ADPCM */ - coding_AICA, /* Yamaha AICA ADPCM */ - coding_L5_555, /* Level-5 0x555 */ - coding_SASSC, /* Activision EXAKT SASSC DPCM */ - coding_PCM16LE_XOR_int, /* sample-level xor */ - coding_LSF, /* lsf ADPCM */ - coding_MTAF, /* Konami IMA-derived MTAF ADPCM */ - - coding_CRI_HCA, /* CRI High Compression Audio */ - -#ifdef VGM_USE_FFMPEG - coding_FFmpeg, + coding_G719, /* ITU G.719 annex B (Polycom Siren 22) */ #endif #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) - coding_MP4_AAC, + coding_MP4_AAC, /* AAC (MDCT-based) */ #endif #ifdef VGM_USE_MAIATRAC3PLUS - coding_AT3plus, + coding_AT3plus, /* Sony ATRAC3plus (MDCT-based) */ +#endif + +#ifdef VGM_USE_FFMPEG + coding_FFmpeg, /* Formats handled by FFmpeg (ATRAC3, XMA, AC3, etc) */ #endif } coding_t; @@ -197,15 +198,15 @@ typedef enum { typedef enum { /* generic */ layout_none, /* straight data */ + /* interleave */ layout_interleave, /* equal interleave throughout the stream */ layout_interleave_shortblock, /* interleave with a short last block */ - layout_interleave_byte, /* full byte interleave */ /* headered blocks */ - layout_ast_blocked, /* .ast STRM with BLCK blocks*/ - layout_halpst_blocked, /* blocks with HALPST-format header */ + layout_ast_blocked, + layout_halpst_blocked, layout_xa_blocked, layout_ea_blocked, layout_eacs_blocked, @@ -226,12 +227,18 @@ typedef enum { layout_ps2_adm_blocked, layout_dsp_bdsp_blocked, layout_mxch_blocked, + layout_ivaud_blocked, /* GTA IV .ivaud blocks */ + layout_tra_blocked, /* DefJam Rapstar .tra blocks */ + layout_ps2_iab_blocked, + layout_ps2_strlr_blocked, -#if 0 - layout_strm_blocked, /* */ -#endif /* otherwise odd */ - layout_dtk_interleave, /* dtk interleaves channels by nibble */ + layout_acm, /* libacm layout */ + layout_mus_acm, /* mus has multi-files to deal with */ + layout_aix, /* CRI AIX's wheels within wheels */ + layout_aax, /* CRI AAX's wheels within databases */ + layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */ + #ifdef VGM_USE_VORBIS layout_ogg_vorbis, /* ogg vorbis file */ #endif @@ -239,31 +246,22 @@ typedef enum { layout_fake_mpeg, /* MPEG audio stream with bad frame headers (AHX) */ layout_mpeg, /* proper MPEG audio stream */ #endif - layout_acm, /* dummy, let libacm handle layout */ - layout_mus_acm, /* mus has multi-files to deal with */ - layout_aix, /* CRI AIX's wheels within wheels */ - layout_aax, /* CRI AAX's wheels within databases */ - layout_ivaud_blocked, /* GTA IV .ivaud blocks */ - layout_tra_blocked, /* DefJam Rapstar .tra blocks */ - layout_ps2_iab_blocked, - layout_ps2_strlr_blocked, - layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */ } layout_t; -/* The meta type specifies how we know what we know about the file. We may know because of a header we read, some of it may have been guessed from filenames, etc. */ +/* The meta type specifies how we know what we know about the file. + * We may know because of a header we read, some of it may have been guessed from filenames, etc. */ typedef enum { /* DSP-specific */ - meta_DSP_STD, /* standard GC ADPCM (DSP) header */ - meta_DSP_CSMP, /* Metroid Prime 3, Donkey Kong Country Returns */ + meta_DSP_STD, /* Nintendo standard GC ADPCM (DSP) header */ + meta_DSP_CSMP, /* Retro: Metroid Prime 3, Donkey Kong Country Returns */ meta_DSP_CSTR, /* Star Fox Assault "Cstr" */ - meta_DSP_RS03, /* Metroid Prime 2 "RS03" */ + meta_DSP_RS03, /* Retro: Metroid Prime 2 "RS03" */ meta_DSP_STM, /* Paper Mario 2 STM */ - meta_DSP_HALP, /* SSB:M "HALPST" */ - meta_DSP_AGSC, /* Metroid Prime 2 title */ + meta_DSP_AGSC, /* Retro: Metroid Prime 2 title */ meta_DSP_MPDSP, /* Monopoly Party single header stereo */ meta_DSP_JETTERS, /* Bomberman Jetters .dsp */ - meta_DSP_MSS, - meta_DSP_GCM, + meta_DSP_MSS, /* ? */ + meta_DSP_GCM, /* ? */ meta_DSP_STR, /* Conan .str files */ meta_DSP_SADB, /* .sad */ meta_DSP_WSI, /* .wsi */ @@ -271,12 +269,12 @@ typedef enum { meta_DSP_WII_IDSP, /* .gcm with IDSP header */ meta_DSP_WII_MUS, /* .mus */ meta_DSP_WII_WSD, /* Phantom Brave (WII) */ - meta_WII_NDP, /* Vertigo (Wii) */ - meta_DSP_YGO, /* Yu-Gi-Oh! The Falsebound Kingdom (NGC), Hikaru no Go 3 (NGC) */ + meta_WII_NDP, /* Vertigo (Wii) */ + meta_DSP_YGO, /* Konami: Yu-Gi-Oh! The Falsebound Kingdom (NGC), Hikaru no Go 3 (NGC) */ /* Nintendo */ - meta_STRM, /* STRM */ - meta_RSTM, /* RSTM (similar to STRM) */ + meta_STRM, /* Nintendo STRM */ + meta_RSTM, /* Nintendo RSTM (similar to STRM) */ meta_AFC, /* AFC */ meta_AST, /* AST */ meta_RWSD, /* single-stream RWSD */ @@ -285,7 +283,7 @@ typedef enum { meta_CWAV, /* contents of CWAR */ meta_FWAV, /* contents of FWAR */ meta_RSTM_SPM, /* RSTM with 44->22khz hack */ - meta_THP, + meta_THP, /* THP movie files */ meta_RSTM_shrunken, /* Atlus' mutant shortened RSTM */ meta_NDS_SWAV, /* Asphalt Urban GT 1 & 2 */ meta_NDS_RRDS, /* Ridge Racer DS */ @@ -293,18 +291,16 @@ typedef enum { meta_STX, /* Pikmin .stx */ meta_WIIU_BTSND, /* Wii U Boot Sound */ - /* CRI ADX */ - meta_ADX_03, /* ADX "type 03" */ - meta_ADX_04, /* ADX "type 04" */ - meta_ADX_05, /* ADX "type 05" */ + meta_ADX_03, /* CRI ADX "type 03" */ + meta_ADX_04, /* CRI ADX "type 04" */ + meta_ADX_05, /* CRI ADX "type 05" */ meta_AIX, /* CRI AIX */ meta_AAX, /* CRI AAX */ meta_UTF_DSP, /* CRI ADPCM_WII, like AAX with DSP */ - /* etc */ - meta_NGC_ADPDTK, /* NGC DTK/ADP, no header (.adp) */ + meta_NGC_ADPDTK, /* NGC DTK/ADP (.adp/dkt DTK) [no header_id] */ meta_kRAW, /* almost headerless PCM */ - meta_RSF, /* Retro Studios RSF, no header (.rsf) */ + meta_RSF, /* Retro Studios RSF (Metroid Prime .rsf) [no header_id] */ meta_HALPST, /* HAL Labs HALPST */ meta_GCSW, /* GCSW (PCM) */ meta_CFN, /* Namco CAF Audio File */ @@ -312,6 +308,7 @@ typedef enum { meta_HIS, /* Her Ineractive .his */ meta_BNSF, /* Bandai Namco Sound Format */ + meta_PSX_XA, /* CD-ROM XA with RIFF header */ meta_PS2_SShd, /* .ADS with SShd header */ meta_PS2_NPSF, /* Namco Production Sound File */ meta_PS2_RXW, /* Sony Arc The Lad Sound File */ @@ -325,11 +322,10 @@ typedef enum { meta_PS2_VAGp, /* VAGp Mono File */ meta_PS2_VAGm, /* VAGp Mono File */ meta_PS2_pGAV, /* VAGp with Little Endian Header */ - meta_PSX_GMS, /* GMS File (used in PS1 & PS2) */ + meta_PSX_GMS, /* GMS File (used in PS1 & PS2) [no header_id] */ meta_PS2_STR, /* Pacman STR+STH files */ meta_PS2_ILD, /* ILD File */ meta_PS2_PNB, /* PsychoNauts Bgm File */ - meta_PSX_XA, /* CD-XA with RIFF header */ meta_PS2_VAGs, /* VAG Stereo from Kingdom Hearts */ meta_PS2_VPK, /* VPK Audio File */ meta_PS2_BMDX, /* Beatmania thing */ @@ -339,14 +335,12 @@ typedef enum { meta_XSS, /* Dino Crisis 3 */ meta_SL3, /* Test Drive Unlimited */ meta_HGC1, /* Knights of the Temple 2 */ - meta_AUS, /* Variuos Capcom Games */ - meta_RWS, /* Variuos Konami Games */ + meta_AUS, /* Various Capcom games */ + meta_RWS, /* Various Konami games */ meta_FSB1, /* FMOD Sample Bank, version 1 */ - meta_FSB3_0, /* FMOD Sample Bank, version 3.0 */ - meta_FSB3_1, /* FMOD Sample Bank, version 3.1 */ + meta_FSB2, /* FMOD Sample Bank, version 2 */ + meta_FSB3, /* FMOD Sample Bank, version 3.0/3.1 */ meta_FSB4, /* FMOD Sample Bank, version 4 */ - meta_FSB_MPEG, /* Just Test */ - meta_FSB4_WAV, /* FMOD Sample Bank, version 4 with "WAV" Header */ meta_FSB5, /* FMOD Sample Bank, version 5 */ meta_RWX, /* Air Force Delta Storm (XBOX) */ meta_XWB, /* King of Fighters (XBOX) */ @@ -357,7 +351,7 @@ typedef enum { meta_MUSX_V006, /* Spyro Games, possibly more */ meta_MUSX_V010, /* Spyro Games, possibly more */ meta_MUSX_V201, /* Sphinx and the cursed Mummy */ - meta_LEG, /* Legaia 2 */ + meta_LEG, /* Legaia 2 [no header_id] */ meta_FILP, /* Resident Evil - Dead Aim */ meta_IKM, /* Zwei! */ meta_SFS, /* Baroque */ @@ -366,8 +360,8 @@ typedef enum { meta_PS2_KCES, /* Dance Dance Revolution */ meta_PS2_DXH, /* Tokobot Plus - Myteries of the Karakuri */ meta_PS2_PSH, /* Dawn of Mana - Seiken Densetsu 4 */ - meta_PCM_SCD, /* Ephemeral Fantasia */ - meta_PCM_PS2, /* Lunar - Eternal Blue */ + meta_PCM_SCD, /* Lunar - Eternal Blue */ + meta_PCM_PS2, /* Konami: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses */ meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 */ meta_PS2_PSW, /* Rayman Raving Rabbids */ meta_PS2_VAS, /* Pro Baseball Spirits 5 */ @@ -376,7 +370,7 @@ typedef enum { meta_SDT, /* Baldur's Gate - Dark Alliance */ meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */ meta_NGC_SWD, /* Conflict - Desert Storm 1 & 2 */ - meta_CAPDSP, /* Capcom DSP Header */ + meta_CAPDSP, /* Capcom DSP Header [no header_id] */ meta_DC_STR, /* SEGA Stream Asset Builder */ meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */ meta_NGC_BH2PCM, /* Bio Hazard 2 */ @@ -386,40 +380,39 @@ typedef enum { meta_PS2_OMU, /* PS2 Int file with Header */ meta_PS2_XA2, /* XG3 Extreme-G Racing */ meta_IDSP, /* Chronicles of Narnia, Soul Calibur Legends, Mario Strikers Charged */ - meta_SPT_SPD, /* Variouis */ - meta_ISH_ISD, /* Various */ - meta_GSP_GSB, /* Various */ + meta_SPT_SPD, /* Various (SPT+SPT DSP) */ + meta_ISH_ISD, /* Various (ISH+ISD DSP) */ + meta_GSP_GSB, /* Tecmo games (Super Swing Golf 1 & 2, Quamtum Theory) */ meta_YDSP, /* WWE Day of Reckoning */ - meta_FFCC_STR, /* Final Fantasy: Crystal Chronicles */ - + meta_FFCC_STR, /* Final Fantasy: Crystal Chronicles */ meta_WAA_WAC_WAD_WAM, /* Beyond Good & Evil */ - meta_GCA, /* Metal Slug Anthology */ - meta_MSVP, /* Popcap Hits */ - meta_NGC_SSM, /* Golden Gashbell Full Power */ - meta_PS2_JOE, /* Wall-E / Pixar games */ + meta_GCA, /* Metal Slug Anthology */ + meta_MSVP, /* Popcap Hits */ + meta_NGC_SSM, /* Golden Gashbell Full Power */ + meta_PS2_JOE, /* Wall-E / Pixar games */ - meta_NGC_YMF, /* WWE WrestleMania X8 */ - meta_SADL, /* .sad */ - meta_PS2_CCC, /* Tokyo Xtreme Racer DRIFT 2 */ - meta_PSX_FAG, /* Jackie Chan - Stuntmaster */ - meta_PS2_MIHB, /* Merged MIH+MIB */ - meta_NGC_PDT, /* Mario Party 6 */ - meta_DC_ASD, /* Miss Moonligh */ - meta_NAOMI_SPSD, /* Guilty Gear X */ + meta_NGC_YMF, /* WWE WrestleMania X8 */ + meta_SADL, /* .sad */ + meta_PS2_CCC, /* Tokyo Xtreme Racer DRIFT 2 */ + meta_PSX_FAG, /* Jackie Chan - Stuntmaster */ + meta_PS2_MIHB, /* Merged MIH+MIB */ + meta_NGC_PDT, /* Mario Party 6 */ + meta_DC_ASD, /* Miss Moonligh */ + meta_NAOMI_SPSD, /* Guilty Gear X */ - meta_RSD2VAG, /* RSD2VAG */ + meta_RSD2VAG, /* RSD2VAG */ meta_RSD2PCMB, /* RSD2PCMB */ meta_RSD2XADP, /* RSD2XADP */ - meta_RSD3VAG, /* RSD3VAG */ - meta_RSD3GADP, /* RSD3GADP */ + meta_RSD3VAG, /* RSD3VAG */ + meta_RSD3GADP, /* RSD3GADP */ meta_RSD3PCM, /* RSD3PCM */ meta_RSD3PCMB, /* RSD3PCMB */ meta_RSD4PCMB, /* RSD4PCMB */ - meta_RSD4PCM, /* RSD4PCM */ + meta_RSD4PCM, /* RSD4PCM */ meta_RSD4RADP, /* RSD4RADP */ - meta_RSD4VAG, /* RSD4VAG */ - meta_RSD6VAG, /* RSD6VAG */ + meta_RSD4VAG, /* RSD4VAG */ + meta_RSD6VAG, /* RSD6VAG */ meta_RSD6WADP, /* RSD6WADP */ meta_RSD6XADP, /* RSD6XADP */ meta_RSD6RADP, /* RSD6RADP */ @@ -427,7 +420,7 @@ typedef enum { meta_PS2_ASS, /* ASS */ meta_PS2_SEG, /* Eragon */ - meta_XBOX_SEG, + meta_XBOX_SEG, /* Eragon */ meta_NDS_STRM_FFTA2, /* Final Fantasy Tactics A2 */ meta_STR_ASR, /* Donkey Kong Jet Race */ meta_ZWDSP, /* Zack and Wiki */ @@ -438,19 +431,19 @@ typedef enum { meta_EMFF_PS2, /* Eidos Music File Format for PS2*/ meta_EMFF_NGC, /* Eidos Music File Format for NGC/WII */ meta_SAT_BAKA, /* Crypt Killer */ - meta_PS2_VSF, /* Musashi: Samurai Legend */ - meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */ - meta_ADS, /* Gauntlet Dark Legends (GC) */ - meta_PS2_SPS, /* Ape Escape 2 */ - meta_PS2_XA2_RRP, /* RC Revenge Pro */ - meta_PS2_STM, /* Red Dead Revolver .stm, renamed .ps2stm */ - meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */ - meta_UBI_CKD, /* Ubisoft CKD RIFF header from Rayman Origins */ + meta_PS2_VSF, /* Musashi: Samurai Legend */ + meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */ + meta_ADS, /* Gauntlet Dark Legends (GC) */ + meta_PS2_SPS, /* Ape Escape 2 */ + meta_PS2_XA2_RRP, /* RC Revenge Pro */ + meta_PS2_STM, /* Red Dead Revolver .stm, renamed .ps2stm */ + meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */ + meta_UBI_CKD, /* Ubisoft CKD RIFF header from Rayman Origins */ meta_XBOX_WAVM, /* XBOX WAVM File */ meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */ meta_XBOX_WVS, /* XBOX WVS */ - meta_NGC_WVS, /* NGC WVS */ + meta_NGC_WVS, /* Metal Arms - Glitch in the System */ meta_XBOX_STMA, /* XBOX STMA */ meta_XBOX_MATX, /* XBOX MATX */ meta_XBOX_XMU, /* XBOX XMU */ @@ -462,69 +455,56 @@ typedef enum { meta_EACS_PC, /* EACS PC */ meta_EACS_PSX, /* EACS PSX */ meta_EACS_SAT, /* EACS SATURN */ - meta_EA_ADPCM, /* EA XA ADPCM */ - meta_EA_IMA, /* EA IMA */ - meta_EA_PCM, /* EA PCM */ + meta_EA_ADPCM, /* EA header using XA ADPCM */ + meta_EA_IMA, /* EA header using IMA */ + meta_EA_PCM, /* EA header using PCM */ meta_RAW, /* RAW PCM file */ meta_GENH, /* generic header */ -#ifdef VGM_USE_VORBIS - meta_ogg_vorbis, /* ogg vorbis */ - meta_OGG_SLI, /* Ogg Vorbis file w/ companion .sli for looping */ - meta_OGG_SLI2, /* Ogg Vorbis file w/ different styled .sli for looping */ - meta_OGG_SFL, /* Ogg Vorbis file w/ .sfl (RIFF SFPL) for looping */ - meta_um3_ogg, /* Ogg Vorbis with first 0x800 bytes XOR 0xFF */ - meta_KOVS_ogg, /* Ogg Vorbis with exta header and 0x100 bytes XOR */ - meta_psych_ogg, /* Ogg Vorbis with all bytes -0x23*/ -#endif - meta_AIFC, /* Audio Interchange File Format AIFF-C */ meta_AIFF, /* Audio Interchange File Format */ meta_STR_SNDS, /* .str with SNDS blocks and SHDR header */ meta_WS_AUD, /* Westwood Studios .aud */ meta_WS_AUD_old, /* Westwood Studios .aud, old style */ -#ifdef VGM_USE_MPEG - meta_AHX, /* CRI AHX header (same structure as ADX) */ -#endif meta_RIFF_WAVE, /* RIFF, for WAVs */ meta_RIFF_WAVE_POS, /* .wav + .pos for looping */ - meta_RIFF_WAVE_labl_Marker, /* RIFF w/ loop Markers in LIST-adtl-labl */ + meta_RIFF_WAVE_labl, /* RIFF w/ loop Markers in LIST-adtl-labl */ meta_RIFF_WAVE_smpl, /* RIFF w/ loop data in smpl chunk */ meta_RIFF_WAVE_MWV, /* .mwv RIFF w/ loop data in ctrl chunk pflt */ meta_RIFF_WAVE_SNS, /* .sns RIFF */ meta_RIFX_WAVE, /* RIFX, for big-endian WAVs */ meta_RIFX_WAVE_smpl, /* RIFX w/ loop data in smpl chunk */ meta_XNBm, /* XNBm, which has a RIFF fmt chunk */ - meta_PC_MXST, /* Lego Island MxSt */ - meta_PC_SOB_SAB, /* Worms 4 Mayhem SOB+SAB file */ + meta_PC_MXST, /* Lego Island MxSt */ + meta_PC_SOB_SAB, /* Worms 4 Mayhem SOB+SAB file */ meta_NWA, /* Visual Art's NWA */ - meta_NWA_NWAINFOINI, /* NWA w/ NWAINFO.INI for looping */ - meta_NWA_GAMEEXEINI, /* NWA w/ Gameexe.ini for looping */ - meta_DVI, /* DVI Interleaved */ - meta_KCEY, /* KCEYCOMP */ + meta_NWA_NWAINFOINI, /* Visual Art's NWA w/ NWAINFO.INI for looping */ + meta_NWA_GAMEEXEINI, /* Visual Art's NWA w/ Gameexe.ini for looping */ + meta_DVI, /* DVI Interleaved */ + meta_KCEY, /* KCEYCOMP */ meta_ACM, /* InterPlay ACM header */ meta_MUS_ACM, /* MUS playlist of InterPlay ACM files */ meta_DE2, /* Falcom (Gurumin) .de2 */ - meta_VS, /* Men in Black .vs */ + meta_VS, /* Men in Black .vs */ meta_FFXI_BGW, /* FFXI BGW */ meta_FFXI_SPW, /* FFXI SPW */ - meta_STS_WII, /* Shikigami No Shiro 3 STS Audio File */ - meta_PS2_P2BT, /* Pop'n'Music 7 Audio File */ - meta_PS2_GBTS, /* Pop'n'Music 9 Audio File */ + meta_STS_WII, /* Shikigami No Shiro 3 STS Audio File */ + meta_PS2_P2BT, /* Pop'n'Music 7 Audio File */ + meta_PS2_GBTS, /* Pop'n'Music 9 Audio File */ meta_NGC_DSP_IADP, /* Gamecube Interleave DSP */ - meta_PS2_TK5, /* Tekken 5 Stream Files */ - meta_WII_STR, /* House of The Dead Overkill STR+STH */ - meta_PS2_MCG, /* Gunvari MCG Files (was name .GCM on disk) */ + meta_PS2_TK5, /* Tekken 5 Stream Files */ + meta_WII_STR, /* House of The Dead Overkill STR+STH */ + meta_PS2_MCG, /* Gunvari MCG Files (was name .GCM on disk) */ meta_ZSD, /* Dragon Booster ZSD */ meta_RedSpark, /* "RedSpark" RSD (MadWorld) */ - meta_PC_IVAUD, /* .ivaud GTA IV */ - meta_NDS_HWAS, /* Spider-Man 3, Tony Hawk's Downhill Jam, possibly more... */ - meta_NGC_LPS, /* Rave Master (Groove Adventure Rave)(GC) */ - meta_NAOMI_ADPCM, /* NAOMI/NAOMI2 ARcade games */ - meta_SD9, /* beatmaniaIIDX16 - EMPRESS (Arcade) */ - meta_2DX9, /* beatmaniaIIDX16 - EMPRESS (Arcade) */ + meta_PC_IVAUD, /* .ivaud GTA IV */ + meta_NDS_HWAS, /* Spider-Man 3, Tony Hawk's Downhill Jam, possibly more... */ + meta_NGC_LPS, /* Rave Master (Groove Adventure Rave)(GC) */ + meta_NAOMI_ADPCM, /* NAOMI/NAOMI2 ARcade games */ + meta_SD9, /* beatmaniaIIDX16 - EMPRESS (Arcade) */ + meta_2DX9, /* beatmaniaIIDX16 - EMPRESS (Arcade) */ meta_PS2_VGV, /* Rune: Viking Warlord */ meta_NGC_GCUB, /* Sega Soccer Slam */ meta_MAXIS_XA, /* Sim City 3000 (PC) */ @@ -535,9 +515,9 @@ typedef enum { meta_PONA_3DO, /* Policenauts (3DO) */ meta_PONA_PSX, /* Policenauts (PSX) */ meta_XBOX_HLWAV, /* Half Life 2 (XBOX) */ - meta_PS2_AST, /* Some KOEI game (PS2) */ - meta_DMSG, /* Nightcaster II - Equinox (XBOX) */ - meta_NGC_DSP_AAAP, /* Turok: Evolution (NGC), Vexx (NGC) */ + meta_PS2_AST, /* Some KOEI game (PS2) */ + meta_DMSG, /* Nightcaster II - Equinox (XBOX) */ + meta_NGC_DSP_AAAP, /* Turok: Evolution (NGC), Vexx (NGC) */ meta_PS2_STER, /* Juuni Kokuki: Kakukaku Taru Ou Michi Beni Midori no Uka */ meta_PS2_WB, /* Shooting Love. ~TRIZEAL~ */ meta_S14, /* raw Siren 14, 24kbit mono */ @@ -549,7 +529,7 @@ typedef enum { meta_PS2_KHV, /* Kingdom Hearts 2 VAG streams */ meta_PC_SMP, /* Ghostbusters PC .smp */ meta_P3D, /* Prototype P3D */ - meta_PS2_TK1, /* Tekken (NamCollection) */ + meta_PS2_TK1, /* Tekken (NamCollection) */ meta_PS2_ADSC, /* Kenka Bancho 2: Full Throttle */ meta_NGC_BO2, /* Blood Omen 2 (NGC) */ meta_DSP_DDSP, /* Various (2 dsp files stuck together */ @@ -562,17 +542,17 @@ typedef enum { meta_DSP_XIII, /* XIII, possibly more (Ubisoft header???) */ meta_DSP_CABELAS, /* Cabelas games */ meta_PS2_ADM, /* Dragon Quest 5 */ - meta_PS2_LPCM, /* Ah! My Goddess */ + meta_PS2_LPCM, /* Ah! My Goddess */ meta_DSP_BDSP, /* Ah! My Goddess */ - meta_PS2_VMS, /* Autobahn Raser - Police Madness */ - meta_PS2_XAU, // Spectral Force Chronicle + meta_PS2_VMS, /* Autobahn Raser - Police Madness */ + meta_PS2_XAU, /* Spectral Force Chronicle */ meta_GH3_BAR, /* Guitar Hero III Mobile .bar */ meta_FFW, /* Freedom Fighters [NGC] */ meta_DSP_DSPW, /* Sengoku Basara 3 [WII] */ meta_PS2_JSTM, /* Tantei Jinguji Saburo - Kind of Blue (PS2) */ - meta_SQEX_SCD, /* Square-Enix SCD */ + meta_SQEX_SCD, /* Square-Enix SCD */ meta_NGC_NST_DSP, /* Animaniacs [NGC] */ - meta_BAF, /* .baf (Blur) */ + meta_BAF, /* Bizarre Creations (Blur, James Bond) */ meta_PS3_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */ meta_PS3_CPS, /* Eternal Sonata (PS3) */ meta_PS3_MSF, /* MSF header */ @@ -581,13 +561,13 @@ typedef enum { meta_PS3_SGDX, /* Folklore, Genji, Tokyo Jungle (PS3), Brave Story, Kurohyo (PSP) */ meta_NGCA, /* GoldenEye 007 (Wii) */ meta_WII_RAS, /* Donkey Kong Country Returns (Wii) */ - meta_PS2_SPM, /* Lethal Skies Elite Pilot: Team SW */ + meta_PS2_SPM, /* Lethal Skies Elite Pilot: Team SW */ meta_X360_TRA, /* Def Jam Rapstar */ - meta_PS2_VGS, // Princess Soft PS2 games - meta_PS2_IAB, // Ueki no Housoku - Taosu ze Robert Juudan!! (PS2) - meta_PS2_STRLR, + meta_PS2_VGS, /* Princess Soft PS2 games */ + meta_PS2_IAB, /* Ueki no Housoku - Taosu ze Robert Juudan!! (PS2) */ + meta_PS2_STRLR, /* The Bouncer */ meta_LSF_N1NJ4N, /* .lsf n1nj4n Fastlane Street Racing (iPhone) */ - meta_PS3_VAWX, // No More Heroes: Heroes Paradise (PS3) + meta_VAWX, /* feelplus: No More Heroes Heroes Paradise, Moon Diver */ meta_PC_SNDS, // Incredibles PC .snds meta_PS2_WMUS, // The Warriors (PS2) meta_HYPERSCAN_KVAG, // Hyperscan KVAG/BVG @@ -602,28 +582,45 @@ typedef enum { meta_TUN, // LEGO Racers (PC) meta_WPD, // Shuffle! (PC) meta_MN_STR, // Mini Ninjas (PC/PS3/WII) - meta_PS2_MSS, // ShellShock Nam '67 (PS2) + meta_PS2_MSS, // Guerilla: ShellShock Nam '67, Killzone (PS2) meta_PS2_HSF, // Lowrider (PS2) meta_PS3_IVAG, // Interleaved VAG files (PS3) - meta_PS2_2PFS, // Mahoromatic: Moetto - KiraKira Maid-San (PS2) - meta_PS2_VBK, - meta_OTM, // Otomedius (Arcade) - meta_CSTM, // Nintendo 3DS CSTM - meta_FSTM, // Nintendo Wii U FSTM - meta_3DS_IDSP, // Nintendo 3DS IDSP - meta_G1L, // Tecmo Koei G1L - meta_MCA, // Capcom MCA "MADP" - meta_XB3D_ADX, // Xenoblade Chronicles 3D ADX - meta_HCA, - meta_PS2_SVAG_SNK, /* SNK PS2 SVAG */ -#ifdef VGM_USE_FFMPEG - meta_FFmpeg, + meta_PS2_2PFS, // Konami: Mahoromatic: Moetto - KiraKira Maid-San, GANTZ (PS2) + meta_PS2_VBK, // Disney's Stitch - Experiment 626 + meta_OTM, // Otomedius (Arcade) + meta_CSTM, // Nintendo 3DS CSTM + meta_FSTM, // Nintendo Wii U FSTM + meta_3DS_IDSP, // Nintendo 3DS/Wii U IDSP + meta_KT_WIIBGM, // Koei Tecmo WiiBGM + meta_MCA, // Capcom MCA "MADP" + meta_XB3D_ADX, // Xenoblade Chronicles 3D ADX + meta_HCA, /* CRI HCA */ + meta_PS2_SVAG_SNK, /* SNK PS2 SVAG */ + meta_PS2_VDS_VDM, /* Graffiti Kingdom */ + meta_X360_CXS, /* Eternal Sonata (Xbox 360) */ + +#ifdef VGM_USE_VORBIS + meta_OGG_VORBIS, /* Ogg Vorbis */ + meta_OGG_SLI, /* Ogg Vorbis file w/ companion .sli for looping */ + meta_OGG_SLI2, /* Ogg Vorbis file w/ different styled .sli for looping */ + meta_OGG_SFL, /* Ogg Vorbis file w/ .sfl (RIFF SFPL) for looping */ + meta_OGG_UM3, /* Ogg Vorbis with first 0x800 bytes XOR 0xFF */ + meta_OGG_KOVS, /* Ogg Vorbis with exta header and 0x100 bytes XOR */ + meta_OGG_PSYCH, /* Ogg Vorbis with all bytes -0x23*/ +#endif +#ifdef VGM_USE_MPEG + meta_AHX, /* CRI AHX header (same structure as ADX) */ #endif #ifdef VGM_USE_MP4V2 - meta_MP4, + meta_MP4, /* AAC (iOS) */ +#endif +#ifdef VGM_USE_FFMPEG + meta_FFmpeg, #endif } meta_t; + +/* info for a single vgmstream channel */ typedef struct { STREAMFILE * streamfile; /* file used by this channel */ off_t channel_start_offset; /* where data for this channel begins */ @@ -660,13 +657,8 @@ typedef struct { int adpcm_step_index; /* for IMA */ int adpcm_scale; /* for MS ADPCM */ - struct g72x_state g72x_state; /* state for G.721 decoder, sort of big but we - might as well keep it around */ - -#ifdef DEBUG - int samples_done; - int16_t loop_history1,loop_history2; -#endif + /* state for G.721 decoder, sort of big but we might as well keep it around */ + struct g72x_state g72x_state; /* ADX encryption */ int adx_channels; @@ -682,6 +674,7 @@ typedef struct { uint16_t key_xor; } VGMSTREAMCHANNEL; +/* main vgmstream info */ typedef struct { /* basics */ int32_t num_samples; /* the actual number of samples in this stream */ @@ -719,28 +712,28 @@ typedef struct { /* loop layout (saved values) */ int32_t loop_sample; /* saved from current_sample, should be loop_start_sample... */ - int32_t loop_samples_into_block; /* saved from samples_into_block */ + int32_t loop_samples_into_block;/* saved from samples_into_block */ off_t loop_block_offset; /* saved from current_block_offset */ size_t loop_block_size; /* saved from current_block_size */ off_t loop_next_block_offset; /* saved from next_block_offset */ - uint8_t xa_channel; /* Selected XA Channel */ - int32_t xa_sector_length; /* XA block */ - uint8_t xa_headerless; /* headerless XA block */ - int8_t get_high_nibble; + /* decoder specific */ + uint8_t xa_channel; /* XA ADPCM: selected channel */ + int32_t xa_sector_length; /* XA ADPCM: XA block */ + uint8_t xa_headerless; /* XA ADPCM: headerless XA block */ - uint8_t ea_big_endian; /* Big Endian ? */ - uint8_t ea_compression_type; - uint8_t ea_compression_version; + int8_t get_high_nibble; /* ADPCM: which nibble (XA, IMA, EA) */ + + uint8_t ea_big_endian; /* EA ADPCM stuff */ + uint8_t ea_compression_type; + uint8_t ea_compression_version; uint8_t ea_platform; - int32_t ws_output_size; /* output bytes for this block */ + int32_t ws_output_size; /* WS ADPCM: output bytes for this block */ - void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */ + int32_t thpNextFrameSize; /* THP */ - int32_t thpNextFrameSize; - - int skip_last_channel; + void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream (for AAX/AIX/SCD) */ /* Data the codec needs for the whole stream. This is for codecs too * different from vgmstream's structure to be reasonably shoehorned into @@ -757,9 +750,11 @@ typedef struct { ogg_int64_t size; ogg_int64_t other_header_bytes; - // XOR setup with a single byte (SCD) - unsigned char scd_xor; - ogg_int64_t scd_xor_len; + /* XOR setup (SCD) */ + int decryption_enabled; + void (*decryption_callback)(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read); + uint8_t scd_xor; + off_t scd_xor_length; } ogg_vorbis_streamfile; typedef struct { @@ -774,6 +769,7 @@ typedef struct { #define AHX_EXPECTED_FRAME_SIZE 0x414 /* MPEG_BUFFER_SIZE should be >= AHX_EXPECTED_FRAME_SIZE */ #define MPEG_BUFFER_SIZE 0x1000 + typedef struct { uint8_t buffer[MPEG_BUFFER_SIZE]; int buffer_used; @@ -806,8 +802,7 @@ typedef struct { } maiatrac3plus_codec_data; #endif -/* with one file this is also used for just - ACM */ +/* with one file this is also used for just ACM */ typedef struct { int file_count; int current_file; @@ -850,6 +845,7 @@ typedef struct { NWAData *nwa; } nwa_codec_data; +/* SQEX SCD interleaved */ typedef struct { int substream_count; VGMSTREAM **substreams; @@ -942,6 +938,11 @@ typedef struct { #endif #endif + +/* -------------------------------------------------------------------------*/ +/* vgmstream "public" API */ +/* -------------------------------------------------------------------------*/ + /* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */ VGMSTREAM * init_vgmstream(const char * const filename); @@ -950,10 +951,7 @@ VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile); /* reset a VGMSTREAM to start of stream */ void reset_vgmstream(VGMSTREAM * vgmstream); -/* allocate a VGMSTREAM and channel stuff */ -VGMSTREAM * allocate_vgmstream(int channel_count, int looped); - -/* deallocate, close, etc. */ +/* close an open vgmstream */ void close_vgmstream(VGMSTREAM * vgmstream); /* calculate the number of samples to be played based on looping parameters */ @@ -962,6 +960,21 @@ int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double /* render! */ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); +/* Write a description of the stream into array pointed by desc, + * which must be length bytes long. Will always be null-terminated if length > 0 */ +void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length); + +/* Return the average bitrate in bps of all unique files contained within this + * stream. Compares files by absolute paths. */ +int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream); + +/* -------------------------------------------------------------------------*/ +/* vgmstream "private" API */ +/* -------------------------------------------------------------------------*/ + +/* allocate a VGMSTREAM and channel stuff */ +VGMSTREAM * allocate_vgmstream(int channel_count, int looped); + /* smallest self-contained group of samples is a frame */ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream); /* number of bytes per frame */ @@ -985,19 +998,14 @@ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMST * Returns 1 if loop was done. */ int vgmstream_do_loop(VGMSTREAM * vgmstream); -/* Write a description of the stream into array pointed by desc, - * which must be length bytes long. Will always be null-terminated if length > 0 - */ -void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length); - /* 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. */ + * 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); -/* Return the average bitrate in bps of all unique files contained within this - * stream. Compares files by absolute paths. */ -int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream); + +/* Open the stream for reading at offset (standarized taking into account layouts, channels and so on). + * returns 0 on failure */ +int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset); #endif diff --git a/Scripts/ffmpeg-build.sh b/Scripts/ffmpeg-build.sh index d379f61a7..1018c028e 100755 --- a/Scripts/ffmpeg-build.sh +++ b/Scripts/ffmpeg-build.sh @@ -6,7 +6,7 @@ --disable-postproc --disable-swresample --disable-avfilter\ --disable-swscale --disable-network --disable-swscale-alpha --disable-vdpau\ --disable-dxva2 --disable-everything --enable-hwaccels\ - --enable-parser=ac3,mpegaudio\ + --enable-parser=ac3,mpegaudio,xma\ --enable-demuxer=ac3,asf,xwma,mov,oma,ogg,tak,dsf,wav,aac,dts,dtshd,mp3\ --enable-demuxer=bink,flac,msf,xmv\ --enable-decoder=ac3,wmapro,wmav1,wmav2,wmavoice,wmalossless,xma1,xma2\ diff --git a/ThirdParty/ffmpeg/include/libavcodec/avcodec.h b/ThirdParty/ffmpeg/include/libavcodec/avcodec.h index e5e7f4225..1e681e989 100644 --- a/ThirdParty/ffmpeg/include/libavcodec/avcodec.h +++ b/ThirdParty/ffmpeg/include/libavcodec/avcodec.h @@ -89,7 +89,7 @@ * - Send valid input: * - For decoding, call avcodec_send_packet() to give the decoder raw * compressed data in an AVPacket. - * - For encoding, call avcodec_send_frame() to give the decoder an AVFrame + * - For encoding, call avcodec_send_frame() to give the encoder an AVFrame * containing uncompressed audio or video. * In both cases, it is recommended that AVPackets and AVFrames are * refcounted, or libavcodec might have to copy the input data. (libavformat @@ -411,6 +411,9 @@ enum AVCodecID { AV_CODEC_ID_MAGICYUV, AV_CODEC_ID_SHEERVIDEO, AV_CODEC_ID_YLC, + AV_CODEC_ID_PSD, + AV_CODEC_ID_PIXLET, + AV_CODEC_ID_SPEEDHQ, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs @@ -448,6 +451,8 @@ enum AVCodecID { AV_CODEC_ID_PCM_S64LE = 0x10800, AV_CODEC_ID_PCM_S64BE, + AV_CODEC_ID_PCM_F16LE, + AV_CODEC_ID_PCM_F24LE, /* various ADPCM codecs */ AV_CODEC_ID_ADPCM_IMA_QT = 0x11000, @@ -1536,7 +1541,13 @@ enum AVPacketSideDataType { * should be associated with a video stream and containts data in the form * of the AVMasteringDisplayMetadata struct. */ - AV_PKT_DATA_MASTERING_DISPLAY_METADATA + AV_PKT_DATA_MASTERING_DISPLAY_METADATA, + + /** + * This side data should be associated with a video stream and corresponds + * to the AVSphericalMapping structure. + */ + AV_PKT_DATA_SPHERICAL, }; #define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED @@ -3564,6 +3575,14 @@ typedef struct AVCodecContext { */ int trailing_padding; + /** + * The number of pixels per image to maximally accept. + * + * - decoding: set by user + * - encoding: set by user + */ + int64_t max_pixels; + } AVCodecContext; AVRational av_codec_get_pkt_timebase (const AVCodecContext *avctx); diff --git a/ThirdParty/ffmpeg/include/libavcodec/vaapi.h b/ThirdParty/ffmpeg/include/libavcodec/vaapi.h index 7a29f6f88..e68912d93 100644 --- a/ThirdParty/ffmpeg/include/libavcodec/vaapi.h +++ b/ThirdParty/ffmpeg/include/libavcodec/vaapi.h @@ -34,6 +34,8 @@ #include "libavutil/attributes.h" #include "version.h" +#if FF_API_STRUCT_VAAPI_CONTEXT + /** * @defgroup lavc_codec_hwaccel_vaapi VA API Decoding * @ingroup lavc_codec_hwaccel @@ -48,7 +50,10 @@ * during initialization or through each AVCodecContext.get_buffer() * function call. In any case, they must be valid prior to calling * decoding functions. + * + * Deprecated: use AVCodecContext.hw_frames_ctx instead. */ +attribute_deprecated struct vaapi_context { /** * Window system dependent data @@ -186,4 +191,6 @@ struct vaapi_context { /* @} */ +#endif /* FF_API_STRUCT_VAAPI_CONTEXT */ + #endif /* AVCODEC_VAAPI_H */ diff --git a/ThirdParty/ffmpeg/include/libavcodec/version.h b/ThirdParty/ffmpeg/include/libavcodec/version.h index ec8837a4e..c038e4b09 100644 --- a/ThirdParty/ffmpeg/include/libavcodec/version.h +++ b/ThirdParty/ffmpeg/include/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 64 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 75 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ @@ -226,5 +226,8 @@ #ifndef FF_API_NVENC_OLD_NAME #define FF_API_NVENC_OLD_NAME (LIBAVCODEC_VERSION_MAJOR < 59) #endif +#ifndef FF_API_STRUCT_VAAPI_CONTEXT +#define FF_API_STRUCT_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 59) +#endif #endif /* AVCODEC_VERSION_H */ diff --git a/ThirdParty/ffmpeg/include/libavformat/avformat.h b/ThirdParty/ffmpeg/include/libavformat/avformat.h index f9f4d725f..ebb0e05c0 100644 --- a/ThirdParty/ffmpeg/include/libavformat/avformat.h +++ b/ThirdParty/ffmpeg/include/libavformat/avformat.h @@ -930,6 +930,9 @@ typedef struct AVStream { * Decoding: duration of the stream, in stream time base. * If a source file does not specify a duration, but does specify * a bitrate, this value will be estimated from bitrate and file size. + * + * Encoding: May be set by the caller before avformat_write_header() to + * provide a hint to the muxer about the estimated duration. */ int64_t duration; @@ -1007,7 +1010,7 @@ typedef struct AVStream { */ /** - * Stream information used internally by av_find_stream_info() + * Stream information used internally by avformat_find_stream_info() */ #define MAX_STD_TIMEBASES (30*12+30+3+6) struct { @@ -1059,7 +1062,7 @@ typedef struct AVStream { int probe_packets; /** - * Number of frames that have been demuxed during av_find_stream_info() + * Number of frames that have been demuxed during avformat_find_stream_info() */ int codec_info_nb_frames; @@ -1899,6 +1902,13 @@ typedef struct AVFormatContext { * - decoding: set by user through AVOptions (NO direct access) */ char *protocol_blacklist; + + /** + * The maximum number of streams. + * - encoding: unused + * - decoding: set by user through AVOptions (NO direct access) + */ + int max_streams; } AVFormatContext; int av_format_get_probe_score(const AVFormatContext *s); @@ -2048,6 +2058,21 @@ const AVClass *avformat_get_class(void); */ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c); +/** + * Wrap an existing array as stream side data. + * + * @param st stream + * @param type side information type + * @param data the side data array. It must be allocated with the av_malloc() + * family of functions. The ownership of the data is transferred to + * st. + * @param size side information size + * @return zero on success, a negative AVERROR code on failure. On failure, + * the stream is unchanged and the data remains owned by the caller. + */ +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size); + /** * Allocate new information from stream. * diff --git a/ThirdParty/ffmpeg/include/libavformat/avio.h b/ThirdParty/ffmpeg/include/libavformat/avio.h index b1ce1d1c7..e2cb4af7a 100644 --- a/ThirdParty/ffmpeg/include/libavformat/avio.h +++ b/ThirdParty/ffmpeg/include/libavformat/avio.h @@ -703,6 +703,18 @@ int avio_closep(AVIOContext **s); */ int avio_open_dyn_buf(AVIOContext **s); +/** + * Return the written size and a pointer to the buffer. + * The AVIOContext stream is left intact. + * The buffer must NOT be freed. + * No padding is added to the buffer. + * + * @param s IO context + * @param pbuffer pointer to a byte buffer + * @return the length of the byte buffer + */ +int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer); + /** * Return the written size and a pointer to the buffer. The buffer * must be freed with av_free(). diff --git a/ThirdParty/ffmpeg/include/libavformat/version.h b/ThirdParty/ffmpeg/include/libavformat/version.h index 45c83347f..edd666bef 100644 --- a/ThirdParty/ffmpeg/include/libavformat/version.h +++ b/ThirdParty/ffmpeg/include/libavformat/version.h @@ -32,7 +32,7 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 57 -#define LIBAVFORMAT_VERSION_MINOR 56 +#define LIBAVFORMAT_VERSION_MINOR 65 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/ThirdParty/ffmpeg/include/libavutil/avutil.h b/ThirdParty/ffmpeg/include/libavutil/avutil.h index 29dd830bf..e9aaa0372 100644 --- a/ThirdParty/ffmpeg/include/libavutil/avutil.h +++ b/ThirdParty/ffmpeg/include/libavutil/avutil.h @@ -118,6 +118,12 @@ * * @} * + * @defgroup lavu_video Video related + * + * @{ + * + * @} + * * @defgroup lavu_audio Audio related * * @{ diff --git a/ThirdParty/ffmpeg/include/libavutil/channel_layout.h b/ThirdParty/ffmpeg/include/libavutil/channel_layout.h index ec7effead..50bb8f03c 100644 --- a/ThirdParty/ffmpeg/include/libavutil/channel_layout.h +++ b/ThirdParty/ffmpeg/include/libavutil/channel_layout.h @@ -131,21 +131,30 @@ enum AVMatrixEncoding { * 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix); * - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC, * SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR); - * - a number of channels, in decimal, optionally followed by 'c', yielding + * - a number of channels, in decimal, followed by 'c', yielding * the default channel layout for that number of channels (@see * av_get_default_channel_layout); * - a channel layout mask, in hexadecimal starting with "0x" (see the * AV_CH_* macros). * - * @warning Starting from the next major bump the trailing character - * 'c' to specify a number of channels will be required, while a - * channel layout mask could also be specified as a decimal number - * (if and only if not followed by "c"). - * * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" */ uint64_t av_get_channel_layout(const char *name); +/** + * Return a channel layout and the number of channels based on the specified name. + * + * This function is similar to (@see av_get_channel_layout), but can also parse + * unknown channel layout specifications. + * + * @param[in] name channel layout specification string + * @param[out] channel_layout parsed channel layout (0 if unknown) + * @param[out] nb_channels number of channels + * + * @return 0 on success, AVERROR(EINVAL) if the parsing fails. + */ +int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels); + /** * Return a description of a channel layout. * If nb_channels is <= 0, it is guessed from the channel_layout. diff --git a/ThirdParty/ffmpeg/include/libavutil/cpu.h b/ThirdParty/ffmpeg/include/libavutil/cpu.h index 4bff16714..8499f0ea8 100644 --- a/ThirdParty/ffmpeg/include/libavutil/cpu.h +++ b/ThirdParty/ffmpeg/include/libavutil/cpu.h @@ -85,8 +85,6 @@ void av_force_cpu_flags(int flags); * Set a mask on flags returned by av_get_cpu_flags(). * This function is mainly useful for testing. * Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible - * - * @warning this function is not thread safe. */ attribute_deprecated void av_set_cpu_flags_mask(int mask); diff --git a/ThirdParty/ffmpeg/include/libavutil/ffversion.h b/ThirdParty/ffmpeg/include/libavutil/ffversion.h index c664839c0..89043dbc1 100644 --- a/ThirdParty/ffmpeg/include/libavutil/ffversion.h +++ b/ThirdParty/ffmpeg/include/libavutil/ffversion.h @@ -1,5 +1,5 @@ /* Automatically generated by version.sh, do not manually edit! */ #ifndef AVUTIL_FFVERSION_H #define AVUTIL_FFVERSION_H -#define FFMPEG_VERSION "n3.2.2" +#define FFMPEG_VERSION "N-83254-gf28299d" #endif /* AVUTIL_FFVERSION_H */ diff --git a/ThirdParty/ffmpeg/include/libavutil/frame.h b/ThirdParty/ffmpeg/include/libavutil/frame.h index 8e51361e2..b4500923a 100644 --- a/ThirdParty/ffmpeg/include/libavutil/frame.h +++ b/ThirdParty/ffmpeg/include/libavutil/frame.h @@ -120,7 +120,13 @@ enum AVFrameSideDataType { * The GOP timecode in 25 bit timecode format. Data format is 64-bit integer. * This is set on the first frame of a GOP that has a temporal reference of 0. */ - AV_FRAME_DATA_GOP_TIMECODE + AV_FRAME_DATA_GOP_TIMECODE, + + /** + * The data represents the AVSphericalMapping structure defined in + * libavutil/spherical.h. + */ + AV_FRAME_DATA_SPHERICAL, }; enum AVActiveFormatDescription { diff --git a/ThirdParty/ffmpeg/include/libavutil/hwcontext.h b/ThirdParty/ffmpeg/include/libavutil/hwcontext.h index 5e2af092a..785da090b 100644 --- a/ThirdParty/ffmpeg/include/libavutil/hwcontext.h +++ b/ThirdParty/ffmpeg/include/libavutil/hwcontext.h @@ -318,6 +318,14 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags); * If dst->format is set, then this format will be used, otherwise (when * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen. * + * The two frames must have matching allocated dimensions (i.e. equal to + * AVHWFramesContext.width/height), since not all device types support + * transferring a sub-rectangle of the whole surface. The display dimensions + * (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but + * also have to be equal for both frames. When the display dimensions are + * smaller than the allocated dimensions, the content of the padding in the + * destination frame is unspecified. + * * @param dst the destination frame. dst is not touched on failure. * @param src the source frame. * @param flags currently unused, should be set to zero diff --git a/ThirdParty/ffmpeg/include/libavutil/hwcontext_cuda.h b/ThirdParty/ffmpeg/include/libavutil/hwcontext_cuda.h index 23a77cee7..12dae8449 100644 --- a/ThirdParty/ffmpeg/include/libavutil/hwcontext_cuda.h +++ b/ThirdParty/ffmpeg/include/libavutil/hwcontext_cuda.h @@ -20,7 +20,9 @@ #ifndef AVUTIL_HWCONTEXT_CUDA_H #define AVUTIL_HWCONTEXT_CUDA_H +#ifndef CUDA_VERSION #include +#endif #include "pixfmt.h" @@ -32,11 +34,14 @@ * AVBufferRefs whose data pointer is a CUdeviceptr. */ +typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal; + /** * This struct is allocated as AVHWDeviceContext.hwctx */ typedef struct AVCUDADeviceContext { CUcontext cuda_ctx; + AVCUDADeviceContextInternal *internal; } AVCUDADeviceContext; /** diff --git a/ThirdParty/ffmpeg/include/libavutil/hwcontext_vaapi.h b/ThirdParty/ffmpeg/include/libavutil/hwcontext_vaapi.h index 7fd1a36e8..da1d4fe6c 100644 --- a/ThirdParty/ffmpeg/include/libavutil/hwcontext_vaapi.h +++ b/ThirdParty/ffmpeg/include/libavutil/hwcontext_vaapi.h @@ -33,6 +33,26 @@ * with the data pointer set to a VASurfaceID. */ +enum { + /** + * The quirks field has been set by the user and should not be detected + * automatically by av_hwdevice_ctx_init(). + */ + AV_VAAPI_DRIVER_QUIRK_USER_SET = (1 << 0), + /** + * The driver does not destroy parameter buffers when they are used by + * vaRenderPicture(). Additional code will be required to destroy them + * separately afterwards. + */ + AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS = (1 << 1), + + /** + * The driver does not support the VASurfaceAttribMemoryType attribute, + * so the surface allocation code will not try to use it. + */ + AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE = (1 << 2), +}; + /** * VAAPI connection details. * @@ -43,6 +63,14 @@ typedef struct AVVAAPIDeviceContext { * The VADisplay handle, to be filled by the user. */ VADisplay display; + /** + * Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), + * with reference to a table of known drivers, unless the + * AV_VAAPI_DRIVER_QUIRK_USER_SET bit is already present. The user + * may need to refer to this field when performing any later + * operations using VAAPI with the same VADisplay. + */ + unsigned int driver_quirks; } AVVAAPIDeviceContext; /** diff --git a/ThirdParty/ffmpeg/include/libavutil/imgutils.h b/ThirdParty/ffmpeg/include/libavutil/imgutils.h index 23282a38f..40aee8b98 100644 --- a/ThirdParty/ffmpeg/include/libavutil/imgutils.h +++ b/ThirdParty/ffmpeg/include/libavutil/imgutils.h @@ -191,6 +191,21 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size, */ int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx); +/** + * Check if the given dimension of an image is valid, meaning that all + * bytes of a plane of an image with the specified pix_fmt can be addressed + * with a signed int. + * + * @param w the width of the picture + * @param h the height of the picture + * @param max_pixels the maximum number of pixels the user wants to accept + * @param pix_fmt the pixel format, can be AV_PIX_FMT_NONE if unknown. + * @param log_offset the offset to sum to the log level for logging with log_ctx + * @param log_ctx the parent logging context, it may be NULL + * @return >= 0 if valid, a negative error code otherwise + */ +int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx); + /** * Check if the given sample aspect ratio of an image is valid. * diff --git a/ThirdParty/ffmpeg/include/libavutil/lfg.h b/ThirdParty/ffmpeg/include/libavutil/lfg.h index ec90562cf..03f779ad8 100644 --- a/ThirdParty/ffmpeg/include/libavutil/lfg.h +++ b/ThirdParty/ffmpeg/include/libavutil/lfg.h @@ -22,6 +22,8 @@ #ifndef AVUTIL_LFG_H #define AVUTIL_LFG_H +#include + typedef struct AVLFG { unsigned int state[64]; int index; @@ -29,6 +31,13 @@ typedef struct AVLFG { void av_lfg_init(AVLFG *c, unsigned int seed); +/** + * Seed the state of the ALFG using binary data. + * + * Return value: 0 on success, negative value (AVERROR) on failure. + */ +int av_lfg_init_from_data(AVLFG *c, const uint8_t *data, unsigned int length); + /** * Get the next random unsigned 32-bit number using an ALFG. * diff --git a/ThirdParty/ffmpeg/include/libavutil/opt.h b/ThirdParty/ffmpeg/include/libavutil/opt.h index 9430b989e..0d893795d 100644 --- a/ThirdParty/ffmpeg/include/libavutil/opt.h +++ b/ThirdParty/ffmpeg/include/libavutil/opt.h @@ -228,6 +228,7 @@ enum AVOptionType{ AV_OPT_TYPE_RATIONAL, AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length AV_OPT_TYPE_DICT, + AV_OPT_TYPE_UINT64, AV_OPT_TYPE_CONST = 128, AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), ///< offset must point to two consecutive integers AV_OPT_TYPE_PIXEL_FMT = MKBETAG('P','F','M','T'), diff --git a/ThirdParty/ffmpeg/include/libavutil/pixfmt.h b/ThirdParty/ffmpeg/include/libavutil/pixfmt.h index 7a3f68be7..dfb1b1103 100644 --- a/ThirdParty/ffmpeg/include/libavutil/pixfmt.h +++ b/ThirdParty/ffmpeg/include/libavutil/pixfmt.h @@ -306,6 +306,14 @@ enum AVPixelFormat { AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec + AV_PIX_FMT_GRAY12BE, ///< Y , 12bpp, big-endian + AV_PIX_FMT_GRAY12LE, ///< Y , 12bpp, little-endian + AV_PIX_FMT_GRAY10BE, ///< Y , 10bpp, big-endian + AV_PIX_FMT_GRAY10LE, ///< Y , 10bpp, little-endian + + AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian + AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; @@ -322,6 +330,8 @@ enum AVPixelFormat { #define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) #define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) +#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE) +#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE) #define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) #define AV_PIX_FMT_YA16 AV_PIX_FMT_NE(YA16BE, YA16LE) #define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) @@ -382,6 +392,7 @@ enum AVPixelFormat { #define AV_PIX_FMT_NV20 AV_PIX_FMT_NE(NV20BE, NV20LE) #define AV_PIX_FMT_AYUV64 AV_PIX_FMT_NE(AYUV64BE, AYUV64LE) #define AV_PIX_FMT_P010 AV_PIX_FMT_NE(P010BE, P010LE) +#define AV_PIX_FMT_P016 AV_PIX_FMT_NE(P016BE, P016LE) /** * Chromaticity coordinates of the source primaries. @@ -398,7 +409,8 @@ enum AVColorPrimaries { AVCOL_PRI_SMPTE240M = 7, ///< functionally identical to above AVCOL_PRI_FILM = 8, ///< colour filters using Illuminant C AVCOL_PRI_BT2020 = 9, ///< ITU-R BT2020 - AVCOL_PRI_SMPTEST428_1 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTE428 = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ) + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428, AVCOL_PRI_SMPTE431 = 11, ///< SMPTE ST 431-2 (2011) AVCOL_PRI_SMPTE432 = 12, ///< SMPTE ST 432-1 D65 (2010) AVCOL_PRI_NB ///< Not part of ABI @@ -424,8 +436,10 @@ enum AVColorTransferCharacteristic { AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC) AVCOL_TRC_BT2020_10 = 14, ///< ITU-R BT2020 for 10-bit system AVCOL_TRC_BT2020_12 = 15, ///< ITU-R BT2020 for 12-bit system - AVCOL_TRC_SMPTEST2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems - AVCOL_TRC_SMPTEST428_1 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTE2084 = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084, + AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428, AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma" AVCOL_TRC_NB ///< Not part of ABI }; diff --git a/ThirdParty/ffmpeg/include/libavutil/spherical.h b/ThirdParty/ffmpeg/include/libavutil/spherical.h new file mode 100644 index 000000000..eeda62523 --- /dev/null +++ b/ThirdParty/ffmpeg/include/libavutil/spherical.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2016 Vittorio Giovara + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Spherical video + */ + +#ifndef AVUTIL_SPHERICAL_H +#define AVUTIL_SPHERICAL_H + +#include +#include + +/** + * @addtogroup lavu_video + * @{ + * + * @defgroup lavu_video_spherical Spherical video mapping + * @{ + */ + +/** + * @addtogroup lavu_video_spherical + * A spherical video file contains surfaces that need to be mapped onto a + * sphere. Depending on how the frame was converted, a different distortion + * transformation or surface recomposition function needs to be applied before + * the video should be mapped and displayed. + */ + +/** + * Projection of the video surface(s) on a sphere. + */ +enum AVSphericalProjection { + /** + * Video represents a sphere mapped on a flat surface using + * equirectangular projection. + */ + AV_SPHERICAL_EQUIRECTANGULAR, + + /** + * Video frame is split into 6 faces of a cube, and arranged on a + * 3x2 layout. Faces are oriented upwards for the front, left, right, + * and back faces. The up face is oriented so the top of the face is + * forwards and the down face is oriented so the top of the face is + * to the back. + */ + AV_SPHERICAL_CUBEMAP, +}; + +/** + * This structure describes how to handle spherical videos, outlining + * information about projection, initial layout, and any other view modifier. + * + * @note The struct must be allocated with av_spherical_alloc() and + * its size is not a part of the public ABI. + */ +typedef struct AVSphericalMapping { + /** + * Projection type. + */ + enum AVSphericalProjection projection; + + /** + * @name Initial orientation + * @{ + * There fields describe additional rotations applied to the sphere after + * the video frame is mapped onto it. The sphere is rotated around the + * viewer, who remains stationary. The order of transformation is always + * yaw, followed by pitch, and finally by roll. + * + * The coordinate system matches the one defined in OpenGL, where the + * forward vector (z) is coming out of screen, and it is equivalent to + * a rotation matrix of R = r_y(yaw) * r_x(pitch) * r_z(roll). + * + * A positive yaw rotates the portion of the sphere in front of the viewer + * toward their right. A positive pitch rotates the portion of the sphere + * in front of the viewer upwards. A positive roll tilts the portion of + * the sphere in front of the viewer to the viewer's right. + * + * These values are exported as 16.16 fixed point. + * + * See this equirectangular projection as example: + * + * @code{.unparsed} + * Yaw + * -180 0 180 + * 90 +-------------+-------------+ 180 + * | | | up + * P | | | y| forward + * i | ^ | | /z + * t 0 +-------------X-------------+ 0 Roll | / + * c | | | | / + * h | | | 0|/_____right + * | | | x + * -90 +-------------+-------------+ -180 + * + * X - the default camera center + * ^ - the default up vector + * @endcode + */ + int32_t yaw; ///< Rotation around the up vector [-180, 180]. + int32_t pitch; ///< Rotation around the right vector [-90, 90]. + int32_t roll; ///< Rotation around the forward vector [-180, 180]. + /** + * @} + */ +} AVSphericalMapping; + +/** + * Allocate a AVSphericalVideo structure and initialize its fields to default + * values. + * + * @return the newly allocated struct or NULL on failure + */ +AVSphericalMapping *av_spherical_alloc(size_t *size); + +/** + * @} + * @} + */ + +#endif /* AVUTIL_SPHERICAL_H */ diff --git a/ThirdParty/ffmpeg/include/libavutil/version.h b/ThirdParty/ffmpeg/include/libavutil/version.h index bdd310f85..9d95086ac 100644 --- a/ThirdParty/ffmpeg/include/libavutil/version.h +++ b/ThirdParty/ffmpeg/include/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 55 -#define LIBAVUTIL_VERSION_MINOR 34 +#define LIBAVUTIL_VERSION_MINOR 45 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/ThirdParty/ffmpeg/lib/libavcodec.a b/ThirdParty/ffmpeg/lib/libavcodec.a index a1aa2d65b..33f82ba81 100644 Binary files a/ThirdParty/ffmpeg/lib/libavcodec.a and b/ThirdParty/ffmpeg/lib/libavcodec.a differ diff --git a/ThirdParty/ffmpeg/lib/libavformat.a b/ThirdParty/ffmpeg/lib/libavformat.a index 2d03f4ba4..2f47d12e8 100644 Binary files a/ThirdParty/ffmpeg/lib/libavformat.a and b/ThirdParty/ffmpeg/lib/libavformat.a differ diff --git a/ThirdParty/ffmpeg/lib/libavutil.a b/ThirdParty/ffmpeg/lib/libavutil.a index 0b6f9bda8..5d1f84662 100644 Binary files a/ThirdParty/ffmpeg/lib/libavutil.a and b/ThirdParty/ffmpeg/lib/libavutil.a differ diff --git a/ThirdParty/ffmpeg/lib/pkgconfig/libavcodec.pc b/ThirdParty/ffmpeg/lib/pkgconfig/libavcodec.pc index 46864201e..3908085c3 100644 --- a/ThirdParty/ffmpeg/lib/pkgconfig/libavcodec.pc +++ b/ThirdParty/ffmpeg/lib/pkgconfig/libavcodec.pc @@ -1,14 +1,14 @@ -prefix=/Users/chris/Source/Repos/cog/ThirdParty/ffmpeg +prefix=/Users/Chris/Source/Repos/cog/ThirdParty/ffmpeg exec_prefix=${prefix} libdir=${prefix}/lib includedir=${prefix}/include Name: libavcodec Description: FFmpeg codec library -Version: 57.64.101 -Requires: libavutil >= 55.34.100 +Version: 57.75.100 +Requires: libavutil >= 55.45.100 Requires.private: Conflicts: -Libs: -L${libdir} -lavcodec -framework QuartzCore -framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo -framework CoreFoundation -framework AudioToolbox -framework CoreMedia -framework VideoDecodeAcceleration -framework CoreFoundation -framework QuartzCore -liconv -Wl,-framework,CoreFoundation -Wl,-framework,Security -L/usr/local/lib -lSDL2 -lm -lbz2 -lz -pthread -framework CoreServices +Libs: -L${libdir} -lavcodec -framework QuartzCore -framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo -framework CoreFoundation -framework AudioToolbox -framework CoreMedia -framework VideoDecodeAcceleration -framework CoreFoundation -framework QuartzCore -liconv -Wl,-framework,CoreFoundation -Wl,-framework,Security -lm -lbz2 -lz -pthread -framework CoreServices Libs.private: Cflags: -I${includedir} diff --git a/ThirdParty/ffmpeg/lib/pkgconfig/libavformat.pc b/ThirdParty/ffmpeg/lib/pkgconfig/libavformat.pc index 623f39b30..6d32a5c0b 100644 --- a/ThirdParty/ffmpeg/lib/pkgconfig/libavformat.pc +++ b/ThirdParty/ffmpeg/lib/pkgconfig/libavformat.pc @@ -1,14 +1,14 @@ -prefix=/Users/chris/Source/Repos/cog/ThirdParty/ffmpeg +prefix=/Users/Chris/Source/Repos/cog/ThirdParty/ffmpeg exec_prefix=${prefix} libdir=${prefix}/lib includedir=${prefix}/include Name: libavformat Description: FFmpeg container format library -Version: 57.56.100 -Requires: libavcodec >= 57.64.101, libavutil >= 55.34.100 +Version: 57.65.100 +Requires: libavcodec >= 57.75.100, libavutil >= 55.45.100 Requires.private: Conflicts: -Libs: -L${libdir} -lavformat -framework QuartzCore -framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo -framework CoreFoundation -framework AudioToolbox -framework CoreMedia -framework VideoDecodeAcceleration -framework CoreFoundation -framework QuartzCore -liconv -Wl,-framework,CoreFoundation -Wl,-framework,Security -L/usr/local/lib -lSDL2 -lm -lbz2 -lz -pthread -framework CoreServices +Libs: -L${libdir} -lavformat -framework QuartzCore -framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo -framework CoreFoundation -framework AudioToolbox -framework CoreMedia -framework VideoDecodeAcceleration -framework CoreFoundation -framework QuartzCore -liconv -Wl,-framework,CoreFoundation -Wl,-framework,Security -lm -lbz2 -lz -pthread -framework CoreServices Libs.private: Cflags: -I${includedir} diff --git a/ThirdParty/ffmpeg/lib/pkgconfig/libavutil.pc b/ThirdParty/ffmpeg/lib/pkgconfig/libavutil.pc index f34143d19..18b8c313c 100644 --- a/ThirdParty/ffmpeg/lib/pkgconfig/libavutil.pc +++ b/ThirdParty/ffmpeg/lib/pkgconfig/libavutil.pc @@ -1,11 +1,11 @@ -prefix=/Users/chris/Source/Repos/cog/ThirdParty/ffmpeg +prefix=/Users/Chris/Source/Repos/cog/ThirdParty/ffmpeg exec_prefix=${prefix} libdir=${prefix}/lib includedir=${prefix}/include Name: libavutil Description: FFmpeg utility library -Version: 55.34.100 +Version: 55.45.100 Requires: Requires.private: Conflicts: