Updated FFmpeg and VGMStream.

CQTexperiment
Chris Moeller 2017-01-26 17:12:52 -08:00
parent 89a2ab07a1
commit e274ec01eb
81 changed files with 4378 additions and 4188 deletions

View File

@ -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 = "<group>"; };
83A3F0721E3AD8B900D6A794 /* formats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = formats.h; sourceTree = "<group>"; };
83A3F0731E3AD8B900D6A794 /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; };
83A3F07A1E3AD92400D6A794 /* ps2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2.c; sourceTree = "<group>"; };
83A3F07B1E3AD92400D6A794 /* x360.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360.c; sourceTree = "<group>"; };
83A5F75E198DF021009AF94C /* bfwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfwav.c; sourceTree = "<group>"; };
83BAFB6B19F45EB3005DAB60 /* bfstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfstm.c; sourceTree = "<group>"; };
83D730E51A738EB200CA1366 /* g7221.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = g7221.xcodeproj; path = ../g7221/g7221.xcodeproj; sourceTree = "<group>"; };
@ -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 */,

View File

@ -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*/

View File

@ -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;

View File

@ -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

View File

@ -1,5 +1,5 @@
/*
* streamtypes.h - widely used type definitions
* g72x_state.h - internal state used by g721 decoder
*/

View File

@ -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

View File

@ -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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t byte, nibble;
byte = read_8bit(cur_off + 0x10 + 0x80*c + i/2, stream->streamfile);
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 */

View File

@ -20,11 +20,6 @@ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*8+stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = mem[framesin*8+1+i/2];
#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):
@ -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);
}
}
}

View File

@ -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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+(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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+(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);

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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;i<vgmstream->channels;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);
}
}

View File

@ -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

View File

@ -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 */
{

View File

@ -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 */
{

View File

@ -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;i<channels;i++) {
vgmstream->ch[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;
}

View File

@ -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; j<vgmstream->channels; 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;
}

View File

@ -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; j<vgmstream->channels; 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;
}

View File

@ -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;
}
}

View File

@ -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;i<channel_count;i++) {
vgmstream->ch[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;i<channel_count;i++) {
vgmstream->ch[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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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.
*

File diff suppressed because it is too large Load Diff

View File

@ -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;i<channel_count;i++)
{
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
#ifdef VGM_USE_MPEG
else if(vgmstream->layout_type == layout_mpeg) {
for (i=0;i<channel_count;i++) {
vgmstream->ch[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

View File

@ -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; j<vgmstream->channels; 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; i<channel_count; i++) {
if (vgmstream->layout_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;
}

View File

@ -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) {

View File

@ -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;i<channel_count;i++) {
vgmstream->ch[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_offset<get_streamfile_size(streamFile));
switch (codec_id) {
case 4: { /* DSP */
size_t block_header_size;
size_t num_blocks;
gsb_block_update(start_offset,vgmstream);
vgmstream->coding_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;
}

View File

@ -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; j<vgmstream->channels; j++) {

View File

@ -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*/

View File

@ -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);

View File

@ -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 */

View File

@ -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;i<channel_count;i++) {
vgmstream->ch[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;

View File

@ -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;i<num_crypt;i++)
((uint8_t*)ptr)[i] ^= ov_streamfile->scd_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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;i<channel_count;i++) {
if (vgmstream->interleave_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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;i<channel_count;i++)
{
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i);
}
}
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -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)
{

View File

@ -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;i<channel_count;i++) {
STREAMFILE * intfile =
open_scdint_with_STREAMFILE(file, "ARBITRARY.DSP", start_offset+interleave_size*i, interleave_size, stride_size, total_size);
if (!intfile)
goto fail;
data->substreams[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;
}
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -1,18 +1,22 @@
#ifndef _MSC_VER
#include <unistd.h>
#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;
}

View File

@ -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

View File

@ -7,13 +7,24 @@
#define _STREAMTYPES_H
#ifdef _MSC_VER
#if (_MSC_VER >= 1600)
#include <stdint.h>
#else
#include <pstdint.h>
#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 <stdint.h>
#endif
#endif /* _MSC_VER */
typedef int16_t sample;

View File

@ -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<count;i++) {
@ -175,42 +106,3 @@ void concatn(int length, char * dst, const char * src) {
dst[i]=src[j];
dst[i]='\0';
}
/* length is maximum length of dst. dst will always be double-null-terminated if
* length > 1 */
void concatn_doublenull(int length, char * dst, const char * src) {
int i,j;
if (length <= 1) return;
for (i=0;i<length-2 && (dst[i] || dst[i+1]);i++); /* find end of dst */
if (i==length-2) {
dst[i]='\0';
dst[i+1]='\0';
return;
}
if (i>0) i++;
for (j=0;i<length-2 && (src[j] || src[j+1]);i++,j++) dst[i]=src[j];
dst[i]='\0';
dst[i+1]='\0';
}
/* length is maximum length of dst. dst will always be double-null-terminated if
* length > 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;i<length-2 && (dst[i] || dst[i+1]);i++); /* find end of dst */
if (i==length-2) {
dst[i]='\0';
dst[i+1]='\0';
return;
}
if (i>0) i++;
k = i;
for (j=0;i<length-2 && (src[j] || src[j+1]);i++,j++) dst[i]=src[j];
if (i == length-2 && (src[j] || src[j+1])) {
i = k;
}
dst[i]='\0';
dst[i+1]='\0';
}

View File

@ -62,14 +62,28 @@ static inline int clamp16(int32_t val) {
return val;
}
/* 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);
void make_smpl_chunk(uint8_t * buf, int32_t loop_start, int32_t loop_end);
void swap_samples_le(sample *buf, int count);
void concatn(int length, char * dst, const char * src);
void concatn_doublenull(int length, char * dst, const char * src);
void concatn_fitting_doublenull(int length, char * dst, const char * src);
/* Simple stdout logging for debugging and regression testing purposes.
* Needs C99 variadic macros. */
#ifdef VGM_DEBUG_OUTPUT
#define VGM_ASSERT(condition, ...) \
do { if (condition) printf(__VA_ARGS__); } while (0)
#define VGM_LOG(...) \
do { printf(__VA_ARGS__); } while (0)
#define VGM_LOGF() \
do { printf("%s:%i '%s'\n", __FILE__, __LINE__, __func__); } while (0)
#else
#define VGM_ASSERT(condition,fmt, ...) /* nothing */
#define VGM_LOG(...) /* nothing */
#define VGM_LOGF(...) /* nothing */
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -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 <vorbis/vorbisfile.h>
#endif
#ifdef VGM_USE_MPEG
#include <mpg123/mpg123.h>
#endif
#ifdef VGM_USE_G7221
#include <g7221/g7221.h>
#endif
@ -60,86 +59,105 @@ enum { PATH_LIMIT = 32768 };
#include "maiatrac3plus.h"
#endif
#include "clHCA.h"
#ifdef VGM_USE_FFMPEG
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#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

View File

@ -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\

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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.
*

View File

@ -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().

View File

@ -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, \

View File

@ -118,6 +118,12 @@
*
* @}
*
* @defgroup lavu_video Video related
*
* @{
*
* @}
*
* @defgroup lavu_audio Audio related
*
* @{

View File

@ -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.

View File

@ -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);

View File

@ -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 */

View File

@ -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 {

View File

@ -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

View File

@ -20,7 +20,9 @@
#ifndef AVUTIL_HWCONTEXT_CUDA_H
#define AVUTIL_HWCONTEXT_CUDA_H
#ifndef CUDA_VERSION
#include <cuda.h>
#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;
/**

View File

@ -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;
/**

View File

@ -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.
*

View File

@ -22,6 +22,8 @@
#ifndef AVUTIL_LFG_H
#define AVUTIL_LFG_H
#include <stdint.h>
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.
*

View File

@ -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'),

View File

@ -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
};

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2016 Vittorio Giovara <vittorio.giovara@gmail.com>
*
* 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 <stddef.h>
#include <stdint.h>
/**
* @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 */

View File

@ -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, \

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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}

View File

@ -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}

View File

@ -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: