Updated VGMStream to r1050-3861-g0ad117e8

CQTexperiment
Christopher Snowhill 2021-08-05 00:26:13 -07:00
parent 0a7be8ab41
commit 8622829af7
94 changed files with 2524 additions and 2273 deletions

View File

@ -175,6 +175,8 @@
8349A91F1FE6258200E26435 /* naac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9061FE6258100E26435 /* naac.c */; }; 8349A91F1FE6258200E26435 /* naac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9061FE6258100E26435 /* naac.c */; };
834D3A6E19F47C98001C54F6 /* g1l.c in Sources */ = {isa = PBXBuildFile; fileRef = 834D3A6D19F47C98001C54F6 /* g1l.c */; }; 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */ = {isa = PBXBuildFile; fileRef = 834D3A6D19F47C98001C54F6 /* g1l.c */; };
834D795520E4F0D400C4A5CC /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83F4128F1E932F9A002E37D0 /* Vorbis.framework */; }; 834D795520E4F0D400C4A5CC /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83F4128F1E932F9A002E37D0 /* Vorbis.framework */; };
834FBCE826BBC7D00095647F /* tantalus_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FBCE426BBC7D00095647F /* tantalus_decoder.c */; };
834FBCEA26BBC7E50095647F /* piff_tpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FBCE926BBC7E50095647F /* piff_tpcm.c */; };
834FE0B3215C798C000A5D3D /* acm_decoder_util.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0AA215C798A000A5D3D /* acm_decoder_util.c */; }; 834FE0B3215C798C000A5D3D /* acm_decoder_util.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0AA215C798A000A5D3D /* acm_decoder_util.c */; };
834FE0B4215C798C000A5D3D /* ffmpeg_decoder_custom_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0AB215C798A000A5D3D /* ffmpeg_decoder_custom_opus.c */; }; 834FE0B4215C798C000A5D3D /* ffmpeg_decoder_custom_opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0AB215C798A000A5D3D /* ffmpeg_decoder_custom_opus.c */; };
834FE0B5215C798C000A5D3D /* acm_decoder_libacm.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FE0AC215C798B000A5D3D /* acm_decoder_libacm.h */; }; 834FE0B5215C798C000A5D3D /* acm_decoder_libacm.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FE0AC215C798B000A5D3D /* acm_decoder_libacm.h */; };
@ -967,6 +969,8 @@
8349A9051FE6258100E26435 /* bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = "<group>"; }; 8349A9051FE6258100E26435 /* bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = "<group>"; };
8349A9061FE6258100E26435 /* naac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naac.c; sourceTree = "<group>"; }; 8349A9061FE6258100E26435 /* naac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naac.c; sourceTree = "<group>"; };
834D3A6D19F47C98001C54F6 /* g1l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g1l.c; sourceTree = "<group>"; }; 834D3A6D19F47C98001C54F6 /* g1l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g1l.c; sourceTree = "<group>"; };
834FBCE426BBC7D00095647F /* tantalus_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tantalus_decoder.c; sourceTree = "<group>"; };
834FBCE926BBC7E50095647F /* piff_tpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = piff_tpcm.c; sourceTree = "<group>"; };
834FE0AA215C798A000A5D3D /* acm_decoder_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm_decoder_util.c; sourceTree = "<group>"; }; 834FE0AA215C798A000A5D3D /* acm_decoder_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm_decoder_util.c; sourceTree = "<group>"; };
834FE0AB215C798A000A5D3D /* ffmpeg_decoder_custom_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_custom_opus.c; sourceTree = "<group>"; }; 834FE0AB215C798A000A5D3D /* ffmpeg_decoder_custom_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_custom_opus.c; sourceTree = "<group>"; };
834FE0AC215C798B000A5D3D /* acm_decoder_libacm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acm_decoder_libacm.h; sourceTree = "<group>"; }; 834FE0AC215C798B000A5D3D /* acm_decoder_libacm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acm_decoder_libacm.h; sourceTree = "<group>"; };
@ -1680,6 +1684,7 @@
83E7FD5B25EF2B0C00683FD2 /* tac_decoder_lib.c */, 83E7FD5B25EF2B0C00683FD2 /* tac_decoder_lib.c */,
83E7FD5C25EF2B0C00683FD2 /* tac_decoder_lib.h */, 83E7FD5C25EF2B0C00683FD2 /* tac_decoder_lib.h */,
83E7FD5725EF2B0C00683FD2 /* tac_decoder.c */, 83E7FD5725EF2B0C00683FD2 /* tac_decoder.c */,
834FBCE426BBC7D00095647F /* tantalus_decoder.c */,
8373341023F60C7A00DE14DC /* tgcadpcm_decoder.c */, 8373341023F60C7A00DE14DC /* tgcadpcm_decoder.c */,
837CEA7623487E2400E62A4A /* ubi_adpcm_decoder.c */, 837CEA7623487E2400E62A4A /* ubi_adpcm_decoder.c */,
83F1EE2C245D4FB20076E182 /* vadpcm_decoder.c */, 83F1EE2C245D4FB20076E182 /* vadpcm_decoder.c */,
@ -1989,6 +1994,7 @@
836F6E8618BDC2180095E648 /* pc_mxst.c */, 836F6E8618BDC2180095E648 /* pc_mxst.c */,
8306B0D12098458F000302D4 /* pcm_sre.c */, 8306B0D12098458F000302D4 /* pcm_sre.c */,
83D20076248DDB770048BD24 /* pcm_success.c */, 83D20076248DDB770048BD24 /* pcm_success.c */,
834FBCE926BBC7E50095647F /* piff_tpcm.c */,
836F6E8B18BDC2180095E648 /* pona.c */, 836F6E8B18BDC2180095E648 /* pona.c */,
836F6E8C18BDC2180095E648 /* pos.c */, 836F6E8C18BDC2180095E648 /* pos.c */,
8306B0C52098458D000302D4 /* ppst_streamfile.h */, 8306B0C52098458D000302D4 /* ppst_streamfile.h */,
@ -2741,6 +2747,7 @@
836F6FC118BDC2190095E648 /* pc_adp.c in Sources */, 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */,
836F703B18BDC2190095E648 /* vsf.c in Sources */, 836F703B18BDC2190095E648 /* vsf.c in Sources */,
836F6F8218BDC2190095E648 /* ea_schl.c in Sources */, 836F6F8218BDC2190095E648 /* ea_schl.c in Sources */,
834FBCE826BBC7D00095647F /* tantalus_decoder.c in Sources */,
836F6F7318BDC2190095E648 /* bcstm.c in Sources */, 836F6F7318BDC2190095E648 /* bcstm.c in Sources */,
83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */, 83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */,
836F704018BDC2190095E648 /* wii_sng.c in Sources */, 836F704018BDC2190095E648 /* wii_sng.c in Sources */,
@ -2987,6 +2994,7 @@
836F704F18BDC2190095E648 /* xwb.c in Sources */, 836F704F18BDC2190095E648 /* xwb.c in Sources */,
8346D98525BF83B300D1A8B0 /* compresswave_decoder_lib.c in Sources */, 8346D98525BF83B300D1A8B0 /* compresswave_decoder_lib.c in Sources */,
8346D97D25BF838C00D1A8B0 /* compresswave.c in Sources */, 8346D97D25BF838C00D1A8B0 /* compresswave.c in Sources */,
834FBCEA26BBC7E50095647F /* piff_tpcm.c in Sources */,
8306B0AD20984552000302D4 /* blocked_caf.c in Sources */, 8306B0AD20984552000302D4 /* blocked_caf.c in Sources */,
8306B0AA20984552000302D4 /* blocked_sthd.c in Sources */, 8306B0AA20984552000302D4 /* blocked_sthd.c in Sources */,
836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */, 836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */,

View File

@ -364,7 +364,7 @@ static void clHCA_destructor(clHCA* hca) {
hca->is_valid = 0; hca->is_valid = 0;
} }
int clHCA_sizeof() { int clHCA_sizeof(void) {
return sizeof(clHCA); return sizeof(clHCA);
} }
@ -376,7 +376,7 @@ void clHCA_done(clHCA* hca) {
clHCA_destructor(hca); clHCA_destructor(hca);
} }
clHCA* clHCA_new() { clHCA* clHCA_new(void) {
clHCA* hca = malloc(clHCA_sizeof()); clHCA* hca = malloc(clHCA_sizeof());
if (hca) { if (hca) {
clHCA_constructor(hca); clHCA_constructor(hca);
@ -1941,7 +1941,6 @@ static void imdct_transform(stChannel* ch, int subframe) {
/* update output/imdct with overlapped window (lib fuses this with the above) */ /* update output/imdct with overlapped window (lib fuses this with the above) */
{ {
unsigned int i;
const float* dct = ch->spectra; //ch->dct; const float* dct = ch->spectra; //ch->dct;
const float* prev = ch->imdct_previous; const float* prev = ch->imdct_previous;

View File

@ -14,12 +14,12 @@ int clHCA_isOurFile(const void *data, unsigned int size);
typedef struct clHCA clHCA; typedef struct clHCA clHCA;
/* In case you wish to allocate and reset the structure on your own. */ /* In case you wish to allocate and reset the structure on your own. */
int clHCA_sizeof(); int clHCA_sizeof(void);
void clHCA_clear(clHCA *); void clHCA_clear(clHCA *);
void clHCA_done(clHCA *); void clHCA_done(clHCA *);
/* Or you could let the library allocate it. */ /* Or you could let the library allocate it. */
clHCA * clHCA_new(); clHCA * clHCA_new(void);
void clHCA_delete(clHCA *); void clHCA_delete(clHCA *);
/* Parses the HCA header. Must be called before any decoding may be performed, /* Parses the HCA header. Must be called before any decoding may be performed,

View File

@ -90,7 +90,7 @@ void decode_circus_adpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channel
for (i = first_sample; i < first_sample + samples_to_do; i++) { for (i = first_sample; i < first_sample + samples_to_do; i++) {
int8_t code = read_8bit(frame_offset+i,stream->streamfile); int8_t code = read_u8(frame_offset+i,stream->streamfile);
hist += code << scale; hist += code << scale;
if (code == 0) { if (code == 0) {
@ -102,6 +102,7 @@ void decode_circus_adpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channel
scale++; scale++;
} }
outbuf[sample_pos] = hist; outbuf[sample_pos] = hist;
sample_pos += channelspacing;
} }
stream->adpcm_history1_32 = hist; stream->adpcm_history1_32 = hist;

View File

@ -35,12 +35,12 @@ void decode_rad_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* ou
void decode_rad_ima_mono(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_rad_ima_mono(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_apple_ima4(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_apple_ima4(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_fsb_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_fsb_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_wwise_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_wwise_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_awc_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_awc_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ubi_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_ubi_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ubi_sce_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_ubi_sce_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_h4m_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, uint16_t frame_format); void decode_h4m_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, uint16_t frame_format);
void decode_cd_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_cd_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
size_t ima_bytes_to_samples(size_t bytes, int channels); size_t ima_bytes_to_samples(size_t bytes, int channels);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels); size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
size_t xbox_ima_bytes_to_samples(size_t bytes, int channels); size_t xbox_ima_bytes_to_samples(size_t bytes, int channels);
@ -118,13 +118,13 @@ size_t xa_bytes_to_samples(size_t bytes, int channels, int is_blocked, int is_fo
/* ea_xa_decoder */ /* ea_xa_decoder */
void decode_ea_xa(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo); void decode_ea_xa(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_maxis_xa(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_maxis_xa(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
int32_t ea_xa_bytes_to_samples(size_t bytes, int channels); int32_t ea_xa_bytes_to_samples(size_t bytes, int channels);
/* ea_xas_decoder */ /* ea_xas_decoder */
void decode_ea_xas_v0(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_ea_xas_v0(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ea_xas_v1(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_ea_xas_v1(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
@ -224,6 +224,11 @@ void decode_dsa(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
void decode_xmd(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size); void decode_xmd(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
/* tantalus_decoder */
void decode_tantalus(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
int32_t tantalus_bytes_to_samples(size_t bytes, int channels);
/* derf_decoder */ /* derf_decoder */
void decode_derf(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_derf(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
@ -336,12 +341,12 @@ void free_tac(tac_codec_data* data);
typedef struct ogg_vorbis_codec_data ogg_vorbis_codec_data; typedef struct ogg_vorbis_codec_data ogg_vorbis_codec_data;
typedef struct { //todo simplify typedef struct { //todo simplify
STREAMFILE *streamfile; STREAMFILE *streamfile;
ogg_int64_t start; /* file offset where the Ogg starts */ int64_t start; /* file offset where the Ogg starts */
ogg_int64_t offset; /* virtual offset, from 0 to size */ int64_t offset; /* virtual offset, from 0 to size */
ogg_int64_t size; /* virtual size of the Ogg */ int64_t size; /* virtual size of the Ogg */
/* decryption setup */ /* decryption setup */
void (*decryption_callback)(void *ptr, size_t size, size_t nmemb, void *datasource); void (*decryption_callback)(void* ptr, size_t size, size_t nmemb, void* datasource);
uint8_t scd_xor; uint8_t scd_xor;
off_t scd_xor_length; off_t scd_xor_length;
uint32_t xor_value; uint32_t xor_value;
@ -552,6 +557,8 @@ void free_speex(speex_codec_data* data);
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
/* ffmpeg_decoder */ /* ffmpeg_decoder */
typedef struct ffmpeg_codec_data ffmpeg_codec_data;
ffmpeg_codec_data* init_ffmpeg_offset(STREAMFILE* sf, uint64_t start, uint64_t size); ffmpeg_codec_data* init_ffmpeg_offset(STREAMFILE* sf, uint64_t start, uint64_t size);
ffmpeg_codec_data* init_ffmpeg_header_offset(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size); ffmpeg_codec_data* init_ffmpeg_header_offset(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size);
ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong); ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size, int target_subsong);
@ -566,13 +573,20 @@ uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data* data);
void ffmpeg_set_channel_remapping(ffmpeg_codec_data* data, int* channels_remap); void ffmpeg_set_channel_remapping(ffmpeg_codec_data* data, int* channels_remap);
const char* ffmpeg_get_codec_name(ffmpeg_codec_data* data); const char* ffmpeg_get_codec_name(ffmpeg_codec_data* data);
void ffmpeg_set_force_seek(ffmpeg_codec_data* data); void ffmpeg_set_force_seek(ffmpeg_codec_data* data);
void ffmpeg_set_invert_floats(ffmpeg_codec_data* data);
const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key); const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key);
int32_t ffmpeg_get_samples(ffmpeg_codec_data* data);
int ffmpeg_get_sample_rate(ffmpeg_codec_data* data);
int ffmpeg_get_channels(ffmpeg_codec_data* data);
int ffmpeg_get_subsong_count(ffmpeg_codec_data* data);
STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data); STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data);
/* ffmpeg_decoder_utils.c (helper-things) */ /* ffmpeg_decoder_utils.c (helper-things) */
ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay); ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* out_samples); ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* out_samples);
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size); ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples);
/* ffmpeg_decoder_custom_opus.c (helper-things) */ /* ffmpeg_decoder_custom_opus.c (helper-things) */

View File

@ -829,10 +829,8 @@ void xma_fix_raw_samples_ch(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t stream_o
* Somehow also needs to skip 64 extra samples (looks like another FFmpeg bug * Somehow also needs to skip 64 extra samples (looks like another FFmpeg bug
* where XMA outputs half a subframe samples late, WMAPRO isn't affected), * where XMA outputs half a subframe samples late, WMAPRO isn't affected),
* which sometimes makes FFmpeg complain (=reads after end) but doesn't seem audible. */ * which sometimes makes FFmpeg complain (=reads after end) but doesn't seem audible. */
if (data->skipSamples == 0) {
ffmpeg_set_skip_samples(data, start_skip+64); ffmpeg_set_skip_samples(data, start_skip+64);
} }
}
#endif #endif
} }

View File

@ -557,7 +557,7 @@ struct TCompressWaveData {
//----------------------------------------------------------- //-----------------------------------------------------------
//create //create
TCompressWaveData* TCompressWaveData_Create() { TCompressWaveData* TCompressWaveData_Create(void) {
TCompressWaveData* this = malloc(sizeof(TCompressWaveData)); TCompressWaveData* this = malloc(sizeof(TCompressWaveData));
if (!this) return NULL; if (!this) return NULL;
#if 0 #if 0
@ -604,7 +604,7 @@ void TCompressWaveData_Free(TCompressWaveData* this) {
//----------------------------------------------------------- //-----------------------------------------------------------
//outpus 44100/16bit/stereo waveform to designed buffer //outpus 44100/16bit/stereo waveform to designed buffer
void TCompressWaveData_Rendering_ReadPress(TCompressWaveData* this, int32_t* RFlg, int32_t* LFlg) { static void TCompressWaveData_Rendering_ReadPress(TCompressWaveData* this, int32_t* RFlg, int32_t* LFlg) {
if (this->Hed.Channel == 2) { if (this->Hed.Channel == 2) {
*RFlg = THuff_Read(this->RH); //STEREO *RFlg = THuff_Read(this->RH); //STEREO
*LFlg = THuff_Read(this->RH); *LFlg = THuff_Read(this->RH);
@ -615,7 +615,7 @@ void TCompressWaveData_Rendering_ReadPress(TCompressWaveData* this, int32_t* RFl
} }
} }
void TCompressWaveData_Rendering_WriteWave(TCompressWaveData* this, int16_t** buf1, int32_t RVol, int32_t LVol) { static void TCompressWaveData_Rendering_WriteWave(TCompressWaveData* this, int16_t** buf1, int32_t RVol, int32_t LVol) {
TLRWRITEBUFFER bbb = {0}; TLRWRITEBUFFER bbb = {0};
if (this->Hed.Sample == 44100) { //44100 STEREO/MONO if (this->Hed.Sample == 44100) { //44100 STEREO/MONO
@ -867,8 +867,8 @@ void TCompressWaveData_SetVolume(TCompressWaveData* this, float vol, float fade)
this->FSetVolume = this->FVolume; this->FSetVolume = this->FVolume;
} }
else { //without fade value else { //without fade value
this->Ffade = round(PW_MAXVOLUME / fade / 44100); this->Ffade = round((double)PW_MAXVOLUME / fade / 44100);
this->FSetVolume = round(aaa * PW_MAXVOLUME); this->FSetVolume = round(aaa * (double)PW_MAXVOLUME);
} }
} }

View File

@ -7,7 +7,7 @@ typedef struct TCompressWaveData TCompressWaveData;
void TCompressWaveData_GetLoopState(TCompressWaveData* this); void TCompressWaveData_GetLoopState(TCompressWaveData* this);
void TCompressWaveData_SetLoopState(TCompressWaveData* this); void TCompressWaveData_SetLoopState(TCompressWaveData* this);
TCompressWaveData* TCompressWaveData_Create(); TCompressWaveData* TCompressWaveData_Create(void);
void TCompressWaveData_Free(TCompressWaveData* this); void TCompressWaveData_Free(TCompressWaveData* this);
int TCompressWaveData_Rendering(TCompressWaveData* this, int16_t* buf, uint32_t Len); int TCompressWaveData_Rendering(TCompressWaveData* this, int16_t* buf, uint32_t Len);
int TCompressWaveData_LoadFromStream(TCompressWaveData* this, STREAMFILE* ss); int TCompressWaveData_LoadFromStream(TCompressWaveData* this, STREAMFILE* ss);

View File

@ -30,7 +30,7 @@ static const int EA_XA_TABLE[20] = {
}; };
/* EA XA v2 (always mono); like v1 but with "PCM samples" flag and doesn't add 128 on expand or clamp (pre-adjusted by the encoder?) */ /* EA XA v2 (always mono); like v1 but with "PCM samples" flag and doesn't add 128 on expand or clamp (pre-adjusted by the encoder?) */
void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame_info; uint8_t frame_info;
int32_t coef1, coef2; int32_t coef1, coef2;
int i, sample_count, shift; int i, sample_count, shift;
@ -60,7 +60,7 @@ void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspac
coef2 = EA_XA_TABLE[(frame_info >> 4) + 4]; coef2 = EA_XA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F) + 8; shift = (frame_info & 0x0F) + 8;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) { for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++, sample_count += channelspacing) {
uint8_t sample_byte, sample_nibble; uint8_t sample_byte, sample_nibble;
int32_t new_sample; int32_t new_sample;
off_t byte_offset = (stream->offset + 0x01 + i/2); off_t byte_offset = (stream->offset + 0x01 + i/2);
@ -84,7 +84,7 @@ void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspac
} }
#if 0 #if 0
/* later PC games use float math, though in the end sounds basically the same (decompiled from various exes) */ /* later PC games and EAAC use float math, though in the end sounds basically the same (decompiled from various exes) */
static const double XA_K0[16] = { 0.0, 0.9375, 1.796875, 1.53125 }; static const double XA_K0[16] = { 0.0, 0.9375, 1.796875, 1.53125 };
static const double XA_K1[16] = { 0.0, 0.0, -0.8125, -0.859375 }; static const double XA_K1[16] = { 0.0, 0.0, -0.8125, -0.859375 };
/* code uses look-up table but it's equivalent to: /* code uses look-up table but it's equivalent to:
@ -125,7 +125,7 @@ static const uint32_t FLOAT_TABLE_INT[256] = {
}; };
static const float* FLOAT_TABLE = (const float *)FLOAT_TABLE_INT; static const float* FLOAT_TABLE = (const float *)FLOAT_TABLE_INT;
void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { void decode_ea_xa_v2_f32(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame_info; uint8_t frame_info;
int i, sample_count, shift; int i, sample_count, shift;

View File

@ -113,7 +113,7 @@ void decode_ea_xas_v1(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspa
/* EA-XAS v0 (xas0), without complex layouts and closer to EA-XA. Somewhat based on daemon1's decoder. */ /* EA-XAS v0 (xas0), without complex layouts and closer to EA-XA. Somewhat based on daemon1's decoder. */
void decode_ea_xas_v0(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { void decode_ea_xas_v0(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x13] = {0}; uint8_t frame[0x13] = {0};
off_t frame_offset; off_t frame_offset;
int i, frames_in, samples_done = 0, sample_count = 0; int i, frames_in, samples_done = 0, sample_count = 0;

View File

@ -2,10 +2,61 @@
#include "coding.h" #include "coding.h"
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
/* opaque struct */
struct ffmpeg_codec_data {
/*** IO internals ***/
STREAMFILE* sf;
uint64_t start; // absolute start within the streamfile
uint64_t offset; // absolute offset within the streamfile
uint64_t size; // max size within the streamfile
uint64_t logical_offset; // computed offset FFmpeg sees (including fake header)
uint64_t logical_size; // computed size FFmpeg sees (including fake header)
uint64_t header_size; // fake header (parseable by FFmpeg) prepended on reads
uint8_t* header_block; // fake header data (ie. RIFF)
/*** internal state ***/
// config
int stream_count; /* FFmpeg audio streams (ignores video/etc) */
int stream_index;
int64_t total_samples; /* may be 0 and innacurate */
int64_t skip_samples; /* number of start samples that will be skipped (encoder delay) */
int channel_remap_set;
int channel_remap[32]; /* map of channel > new position */
int invert_floats_set;
int skip_samples_set; /* flag to know skip samples were manually added from vgmstream */
int force_seek; /* flags for special seeking in faulty formats */
int bad_init;
// FFmpeg context used for metadata
AVCodec* codec;
/* FFmpeg decoder state */
unsigned char* buffer;
AVIOContext* ioCtx;
AVFormatContext* formatCtx;
AVCodecContext* codecCtx;
AVFrame* frame; /* last decoded frame */
AVPacket* packet; /* last read data packet */
int read_packet;
int end_of_stream;
int end_of_audio;
/* sample state */
int32_t samples_discard;
int32_t samples_consumed;
int32_t samples_filled;
};
#define FFMPEG_DEFAULT_IO_BUFFER_SIZE 128 * 1024 #define FFMPEG_DEFAULT_IO_BUFFER_SIZE 128 * 1024
static volatile int g_ffmpeg_initialized = 0; static volatile int g_ffmpeg_initialized = 0;
static void free_ffmpeg_config(ffmpeg_codec_data* data); static void free_ffmpeg_config(ffmpeg_codec_data* data);
@ -16,7 +67,7 @@ static int init_ffmpeg_config(ffmpeg_codec_data* data, int target_subsong, int r
/* ******************************************** */ /* ******************************************** */
/* Global FFmpeg init */ /* Global FFmpeg init */
static void g_init_ffmpeg() { static void g_init_ffmpeg(void) {
if (g_ffmpeg_initialized == 1) { if (g_ffmpeg_initialized == 1) {
while (g_ffmpeg_initialized < 2); /* active wait for lack of a better way */ while (g_ffmpeg_initialized < 2); /* active wait for lack of a better way */
} }
@ -69,8 +120,8 @@ static int init_seek(ffmpeg_codec_data* data) {
int size = 0; /* data size (block align) */ int size = 0; /* data size (block align) */
int distance = 0; /* always 0 ("duration") */ int distance = 0; /* always 0 ("duration") */
AVStream * stream = data->formatCtx->streams[data->streamIndex]; AVStream* stream = data->formatCtx->streams[data->stream_index];
AVPacket * pkt = data->packet; AVPacket* pkt = data->packet;
/* read_seek shouldn't need this index, but direct access to FFmpeg's internals is no good */ /* read_seek shouldn't need this index, but direct access to FFmpeg's internals is no good */
@ -95,7 +146,7 @@ static int init_seek(ffmpeg_codec_data* data) {
ret = av_read_frame(data->formatCtx, pkt); ret = av_read_frame(data->formatCtx, pkt);
if (ret < 0) if (ret < 0)
break; break;
if (pkt->stream_index != data->streamIndex) if (pkt->stream_index != data->stream_index)
continue; /* ignore non-selected streams */ continue; /* ignore non-selected streams */
//;VGM_LOG("FFMPEG: packet %i, ret=%i, pos=%i, dts=%i\n", packet_count, ret, (int32_t)pkt->pos, (int32_t)pkt->dts); //;VGM_LOG("FFMPEG: packet %i, ret=%i, pos=%i, dts=%i\n", packet_count, ret, (int32_t)pkt->pos, (int32_t)pkt->dts);
@ -138,7 +189,7 @@ static int init_seek(ffmpeg_codec_data* data) {
test_seek: test_seek:
/* seek to 0 test + move back to beginning, since we just consumed packets */ /* seek to 0 test + move back to beginning, since we just consumed packets */
ret = avformat_seek_file(data->formatCtx, data->streamIndex, ts, ts, ts, AVSEEK_FLAG_ANY); ret = avformat_seek_file(data->formatCtx, data->stream_index, ts, ts, ts, AVSEEK_FLAG_ANY);
if ( ret < 0 ) { if ( ret < 0 ) {
//char test[1000] = {0}; av_strerror(ret, test, 1000); VGM_LOG("FFMPEG: ret=%i %s\n", ret, test); //char test[1000] = {0}; av_strerror(ret, test, 1000); VGM_LOG("FFMPEG: ret=%i %s\n", ret, test);
return ret; /* we can't even reset_vgmstream the file */ return ret; /* we can't even reset_vgmstream the file */
@ -186,7 +237,7 @@ static int ffmpeg_read(void* opaque, uint8_t* buf, int read_size) {
} }
/* main read */ /* main read */
bytes = read_streamfile(buf, data->offset, read_size, data->streamfile); bytes = read_streamfile(buf, data->offset, read_size, data->sf);
data->logical_offset += bytes; data->logical_offset += bytes;
data->offset += bytes; data->offset += bytes;
return bytes + max_to_copy; return bytes + max_to_copy;
@ -215,6 +266,9 @@ static int64_t ffmpeg_seek(void* opaque, int64_t offset, int whence) {
case SEEK_END: /* relative to file end (should be negative) */ case SEEK_END: /* relative to file end (should be negative) */
offset += data->logical_size; offset += data->logical_size;
break; break;
default:
break;
} }
/* clamp offset; fseek does this too */ /* clamp offset; fseek does this too */
@ -244,7 +298,7 @@ ffmpeg_codec_data* init_ffmpeg_offset(STREAMFILE* sf, uint64_t start, uint64_t s
return init_ffmpeg_header_offset(sf, NULL,0, start,size); return init_ffmpeg_header_offset(sf, NULL,0, start,size);
} }
ffmpeg_codec_data* init_ffmpeg_header_offset(STREAMFILE* sf, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size) { ffmpeg_codec_data* init_ffmpeg_header_offset(STREAMFILE* sf, uint8_t* header, uint64_t header_size, uint64_t start, uint64_t size) {
return init_ffmpeg_header_offset_subsong(sf, header, header_size, start, size, 0); return init_ffmpeg_header_offset_subsong(sf, header, header_size, start, size, 0);
} }
@ -281,8 +335,8 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he
data = calloc(1, sizeof(ffmpeg_codec_data)); data = calloc(1, sizeof(ffmpeg_codec_data));
if (!data) return NULL; if (!data) return NULL;
data->streamfile = reopen_streamfile(sf, 0); data->sf = reopen_streamfile(sf, 0);
if (!data->streamfile) goto fail; if (!data->sf) goto fail;
/* fake header to trick FFmpeg into demuxing/decoding the stream */ /* fake header to trick FFmpeg into demuxing/decoding the stream */
if (header_size > 0) { if (header_size > 0) {
@ -307,14 +361,16 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he
/* setup other values */ /* setup other values */
{ {
AVStream *stream = data->formatCtx->streams[data->streamIndex]; AVStream* stream = data->formatCtx->streams[data->stream_index];
AVRational tb = {0}; AVRational tb = {0};
tb.num = 1; tb.den = data->codecCtx->sample_rate;
#if 0
/* derive info */ /* derive info */
data->sampleRate = data->codecCtx->sample_rate; data->sampleRate = data->codecCtx->sample_rate;
data->channels = data->codecCtx->channels; data->channels = data->codecCtx->channels;
data->bitrate = (int)(data->codecCtx->bit_rate); data->bitrate = (int)(data->codecCtx->bit_rate);
#if 0
data->blockAlign = data->codecCtx->block_align; data->blockAlign = data->codecCtx->block_align;
data->frameSize = data->codecCtx->frame_size; data->frameSize = data->codecCtx->frame_size;
if(data->frameSize == 0) /* some formats don't set frame_size but can get on request, and vice versa */ if(data->frameSize == 0) /* some formats don't set frame_size but can get on request, and vice versa */
@ -322,40 +378,40 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he
#endif #endif
/* try to guess frames/samples (duration isn't always set) */ /* try to guess frames/samples (duration isn't always set) */
tb.num = 1; tb.den = data->codecCtx->sample_rate; data->total_samples = av_rescale_q(stream->duration, stream->time_base, tb);
data->totalSamples = av_rescale_q(stream->duration, stream->time_base, tb); if (data->total_samples < 0)
if (data->totalSamples < 0) data->total_samples = 0;
data->totalSamples = 0; /* caller must consider this */
/* expose start samples to be skipped (encoder delay, usually added by MDCT-based encoders like AAC/MP3/ATRAC3/XMA/etc) /* read start samples to be skipped (encoder delay), info only.
* get after init_seek because some demuxers like AAC only fill skip_samples for the first packet */ * Not too reliable though, see ffmpeg_set_skip_samples */
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100) if (stream->start_time && stream->start_time != AV_NOPTS_VALUE)
if (stream->start_skip_samples) /* samples to skip in the first packet */ data->skip_samples = av_rescale_q(stream->start_time, stream->time_base, tb);
data->skipSamples = stream->start_skip_samples; if (data->skip_samples < 0)
data->skip_samples = 0;
#if 0 //LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
/* exposed before but not too reliable either */
else if (stream->start_skip_samples) /* samples to skip in the first packet */
data->skip_samples = stream->start_skip_samples;
else if (stream->skip_samples) /* samples to skip in any packet (first in this case), used sometimes instead (ex. AAC) */ else if (stream->skip_samples) /* samples to skip in any packet (first in this case), used sometimes instead (ex. AAC) */
data->skipSamples = stream->skip_samples; data->skip_samples = stream->skip_samples;
#else
if (stream->start_time)
data->skipSamples = av_rescale_q(stream->start_time, stream->time_base, tb);
#endif #endif
/* check ways to skip encoder delay/padding, for debugging purposes (some may be old/unused/encoder only/etc) */ /* check ways to skip encoder delay/padding, for debugging purposes (some may be old/unused/encoder only/etc) */
VGM_ASSERT(data->codecCtx->delay > 0, "FFMPEG: delay %i\n", (int)data->codecCtx->delay);//delay: OPUS
//VGM_ASSERT(data->codecCtx->internal->skip_samples > 0, ...); /* for codec use, not accessible */ //VGM_ASSERT(data->codecCtx->internal->skip_samples > 0, ...); /* for codec use, not accessible */
VGM_ASSERT(data->codecCtx->delay > 0, "FFMPEG: delay %i\n", (int)data->codecCtx->delay);//delay: OPUS
VGM_ASSERT(stream->codecpar->initial_padding > 0, "FFMPEG: initial_padding %i\n", (int)stream->codecpar->initial_padding);//delay: OPUS VGM_ASSERT(stream->codecpar->initial_padding > 0, "FFMPEG: initial_padding %i\n", (int)stream->codecpar->initial_padding);//delay: OPUS
VGM_ASSERT(stream->codecpar->trailing_padding > 0, "FFMPEG: trailing_padding %i\n", (int)stream->codecpar->trailing_padding); VGM_ASSERT(stream->codecpar->trailing_padding > 0, "FFMPEG: trailing_padding %i\n", (int)stream->codecpar->trailing_padding);
VGM_ASSERT(stream->codecpar->seek_preroll > 0, "FFMPEG: seek_preroll %i\n", (int)stream->codecpar->seek_preroll);//seek delay: OPUS VGM_ASSERT(stream->codecpar->seek_preroll > 0, "FFMPEG: seek_preroll %i\n", (int)stream->codecpar->seek_preroll);//seek delay: OPUS
VGM_ASSERT(stream->start_time > 0, "FFMPEG: start_time %i\n", (int)stream->start_time); //delay
VGM_ASSERT(stream->first_discard_sample > 0, "FFMPEG: first_discard_sample %i\n", (int)stream->first_discard_sample); //padding: MP3
VGM_ASSERT(stream->last_discard_sample > 0, "FFMPEG: last_discard_sample %i\n", (int)stream->last_discard_sample); //padding: MP3
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100) #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
VGM_ASSERT(stream->skip_samples > 0, "FFMPEG: skip_samples %i\n", (int)stream->skip_samples); //delay: MP4 VGM_ASSERT(stream->skip_samples > 0, "FFMPEG: skip_samples %i\n", (int)stream->skip_samples); //delay: MP4
VGM_ASSERT(stream->start_skip_samples > 0, "FFMPEG: start_skip_samples %i\n", (int)stream->start_skip_samples); //delay: MP3 VGM_ASSERT(stream->start_skip_samples > 0, "FFMPEG: start_skip_samples %i\n", (int)stream->start_skip_samples); //delay: MP3
#else
VGM_ASSERT(stream->start_time > 0, "FFMPEG: start_time %i\n", (int)stream->start_time); //delay
#endif #endif
VGM_ASSERT(stream->first_discard_sample > 0, "FFMPEG: first_discard_sample %i\n", (int)stream->first_discard_sample); //padding: MP3
VGM_ASSERT(stream->last_discard_sample > 0, "FFMPEG: last_discard_sample %i\n", (int)stream->last_discard_sample); //padding: MP3
/* also negative timestamp for formats like OGG/OPUS */ /* also negative timestamp for formats like OGG/OPUS */
/* not using it: BINK, FLAC, ATRAC3, XMA, MPC, WMA (may use internal skip samples) */ /* not using it: BINK, FLAC, ATRAC3, XMA, MPC, WMA (may use internal skip samples) */
//todo: double check Opus behavior
} }
@ -398,44 +454,46 @@ static int init_ffmpeg_config(ffmpeg_codec_data* data, int target_subsong, int r
/* find valid audio stream and set other streams to discard */ /* find valid audio stream and set other streams to discard */
{ {
int i, streamIndex, streamCount; int i, stream_index, stream_count;
streamIndex = -1; stream_index = -1;
streamCount = 0; stream_count = 0;
if (reset) if (reset)
streamIndex = data->streamIndex; stream_index = data->stream_index;
for (i = 0; i < data->formatCtx->nb_streams; ++i) { for (i = 0; i < data->formatCtx->nb_streams; ++i) {
AVStream *stream = data->formatCtx->streams[i]; AVStream* stream = data->formatCtx->streams[i];
if (stream->codecpar && stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { if (stream->codecpar && stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
streamCount++; stream_count++;
/* select Nth audio stream if specified, or first one */ /* select Nth audio stream if specified, or first one */
if (streamIndex < 0 || (target_subsong > 0 && streamCount == target_subsong)) { if (stream_index < 0 || (target_subsong > 0 && stream_count == target_subsong)) {
streamIndex = i; stream_index = i;
} }
} }
if (i != streamIndex) if (i != stream_index)
stream->discard = AVDISCARD_ALL; /* disable demuxing for other streams */ stream->discard = AVDISCARD_ALL; /* disable demuxing for other streams */
} }
if (streamCount < target_subsong) goto fail; if (stream_count < target_subsong) goto fail;
if (streamIndex < 0) goto fail; if (stream_index < 0) goto fail;
data->streamIndex = streamIndex; data->stream_index = stream_index;
data->streamCount = streamCount; data->stream_count = stream_count;
} }
/* setup codec with stream info */ /* setup codec with stream info */
data->codecCtx = avcodec_alloc_context3(NULL); data->codecCtx = avcodec_alloc_context3(NULL);
if (!data->codecCtx) goto fail; if (!data->codecCtx) goto fail;
errcode = avcodec_parameters_to_context(data->codecCtx, ((AVStream*)data->formatCtx->streams[data->streamIndex])->codecpar); errcode = avcodec_parameters_to_context(data->codecCtx, data->formatCtx->streams[data->stream_index]->codecpar);
if (errcode < 0) goto fail; if (errcode < 0) goto fail;
//av_codec_set_pkt_timebase(data->codecCtx, stream->time_base); /* deprecated and seemingly not needed */ /* deprecated and seemingly not needed */
//av_codec_set_pkt_timebase(data->codecCtx, stream->time_base);
/* not useddeprecated and seemingly not needed */
data->codec = avcodec_find_decoder(data->codecCtx->codec_id); data->codec = avcodec_find_decoder(data->codecCtx->codec_id);
if (!data->codec) goto fail; if (!data->codec) goto fail;
@ -501,7 +559,7 @@ static int decode_ffmpeg_frame(ffmpeg_codec_data* data) {
} }
/* ignore non-selected streams */ /* ignore non-selected streams */
if (data->packet->stream_index != data->streamIndex) if (data->packet->stream_index != data->stream_index)
continue; continue;
} }
@ -788,7 +846,7 @@ void seek_ffmpeg(ffmpeg_codec_data* data, int32_t num_sample) {
if (errcode < 0) goto fail; if (errcode < 0) goto fail;
} }
else { else {
avformat_seek_file(data->formatCtx, data->streamIndex, 0, 0, 0, AVSEEK_FLAG_ANY); avformat_seek_file(data->formatCtx, data->stream_index, 0, 0, 0, AVSEEK_FLAG_ANY);
avcodec_flush_buffers(data->codecCtx); avcodec_flush_buffers(data->codecCtx);
} }
@ -800,18 +858,10 @@ void seek_ffmpeg(ffmpeg_codec_data* data, int32_t num_sample) {
data->end_of_stream = 0; data->end_of_stream = 0;
data->end_of_audio = 0; data->end_of_audio = 0;
/* consider skip samples (encoder delay), if manually set (otherwise let FFmpeg handle it) */ /* consider skip samples (encoder delay), if manually set */
if (data->skip_samples_set) { if (data->skip_samples_set) {
AVStream *stream = data->formatCtx->streams[data->streamIndex]; data->samples_discard += data->skip_samples;
/* sometimes (ex. AAC) after seeking to the first packet skip_samples is restored, but we want our value */ /* internally FFmpeg may skip (skip_samples/start_skip_samples) too */
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
stream->skip_samples = 0;
stream->start_skip_samples = 0;
#else
stream->start_time = 0;
#endif
data->samples_discard += data->skipSamples;
} }
return; return;
@ -872,40 +922,53 @@ void free_ffmpeg(ffmpeg_codec_data* data) {
data->header_block = NULL; data->header_block = NULL;
} }
close_streamfile(data->streamfile); close_streamfile(data->sf);
free(data); free(data);
} }
/** /**
* Sets the number of samples to skip at the beginning of the stream, needed by some "gapless" formats. * Sets the number of samples to skip at the beginning of the stream (encoder delay), needed by some "gapless" formats.
* (encoder delay, usually added by MDCT-based encoders like AAC/MP3/ATRAC3/XMA/etc to "set up" the decoder).
* - should be used at the beginning of the stream * - should be used at the beginning of the stream
* - should check if there are data->skipSamples before using this, to avoid overwritting FFmpeg's value (ex. AAC). * - should use only if/when FFmpeg's format is known to botch encoder delay.
* *
* This could be added per format in FFmpeg directly, but it's here for flexibility and due to bugs * encoder delay in FFmpeg is handled in multiple ways:
* (FFmpeg's stream->(start_)skip_samples causes glitches in XMA). * - avstream/internal->start_skip_samples: skip in the first packet *if* pts=0 (set in MP3 only?)
* - avstream/internal->skip_samples: skip in any packet (set in AAC encoded by libfaac, OPUS, MP3 in SWF, MOV/MP4)
* - avstream->start_time: usually set same as skip_samples but in pts, info only (most of the above but OPUS)
* - codecCtx->delay: seems equivalent to skip_samples, info only (OPUS)
* - negative timestamp: Xiph style (Ogg Vorbis/Opus only?).
* First two are only exposed in FFmpeg v4.4<, meaning you can't override buggy values after that.
* But since FFmpeg only does encoder delay for a handful of formats, shouldn't matter much.
* May need to detect exact versions if they start fixing formats.
*/ */
void ffmpeg_set_skip_samples(ffmpeg_codec_data* data, int skip_samples) { void ffmpeg_set_skip_samples(ffmpeg_codec_data* data, int skip_samples) {
AVStream *stream = NULL; if (!data || !data->formatCtx || !skip_samples)
if (!data || !data->formatCtx)
return; return;
/* overwrite FFmpeg's skip samples */ /* let FFmpeg handle (may need an option to force override?) */
stream = data->formatCtx->streams[data->streamIndex]; if (data->skip_samples) {
VGM_ASSERT(data->skip_samples != skip_samples,
"FMPEG: ignored skip_samples %i, already set %i\n", skip_samples, (int)data->skip_samples);
return;
}
#if 0
{
AVStream* stream = data->formatCtx->streams[data->stream_index];
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100) #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
stream->start_skip_samples = 0; /* used for the first packet *if* pts=0 */ stream->start_skip_samples = 0;
stream->skip_samples = 0; /* skip_samples can be used for any packet */ stream->skip_samples = 0;
#else #else
stream->start_time = 0; //stream->start_time = 0; /* info only = useless */
#endif
}
#endif #endif
/* set skip samples with our internal discard */ /* set skip samples with our internal discard */
data->skip_samples_set = 1; data->skip_samples_set = 1;
data->samples_discard = skip_samples; data->samples_discard = skip_samples;
data->skip_samples = skip_samples;
/* expose (info only) */
data->skipSamples = skip_samples;
} }
/* returns channel layout if set */ /* returns channel layout if set */
@ -920,10 +983,10 @@ uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data* data) {
void ffmpeg_set_channel_remapping(ffmpeg_codec_data* data, int *channel_remap) { void ffmpeg_set_channel_remapping(ffmpeg_codec_data* data, int *channel_remap) {
int i; int i;
if (data->channels > 32) if (data->codecCtx->channels > 32)
return; return;
for (i = 0; i < data->channels; i++) { for (i = 0; i < data->codecCtx->channels; i++) {
data->channel_remap[i] = channel_remap[i]; data->channel_remap[i] = channel_remap[i];
} }
data->channel_remap_set = 1; data->channel_remap_set = 1;
@ -940,12 +1003,20 @@ const char* ffmpeg_get_codec_name(ffmpeg_codec_data* data) {
} }
void ffmpeg_set_force_seek(ffmpeg_codec_data* data) { void ffmpeg_set_force_seek(ffmpeg_codec_data* data) {
if (!data)
return;
/* some formats like Smacker are so buggy that any seeking is impossible (even on video players), /* some formats like Smacker are so buggy that any seeking is impossible (even on video players),
* or MPC with an incorrectly parsed seek table (using as 0 some non-0 seek offset). * or MPC with an incorrectly parsed seek table (using as 0 some non-0 seek offset).
* whatever, we'll just kill and reconstruct FFmpeg's config every time */ * whatever, we'll just kill and reconstruct FFmpeg's config every time */
data->force_seek = 1; data->force_seek = 1;
reset_ffmpeg(data); /* reset state from trying to seek */ reset_ffmpeg(data); /* reset state from trying to seek */
//stream = data->formatCtx->streams[data->streamIndex]; //stream = data->formatCtx->streams[data->stream_index];
}
void ffmpeg_set_invert_floats(ffmpeg_codec_data* data) {
if (!data)
return;
data->invert_floats_set = 1;
} }
const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key) { const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key) {
@ -955,7 +1026,7 @@ const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key)
if (!data || !data->codec) if (!data || !data->codec)
return NULL; return NULL;
avd = data->formatCtx->streams[data->streamIndex]->metadata; /* per stream (like Ogg) */ avd = data->formatCtx->streams[data->stream_index]->metadata; /* per stream (like Ogg) */
if (!avd) if (!avd)
avd = data->formatCtx->metadata; /* per format (like Flac) */ avd = data->formatCtx->metadata; /* per format (like Flac) */
if (!avd) if (!avd)
@ -968,8 +1039,33 @@ const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key)
return avde->value; return avde->value;
} }
int32_t ffmpeg_get_samples(ffmpeg_codec_data* data) {
if (!data)
return 0;
return (int32_t)data->total_samples;
}
int ffmpeg_get_sample_rate(ffmpeg_codec_data* data) {
if (!data || !data->codecCtx)
return 0;
return data->codecCtx->sample_rate;
}
int ffmpeg_get_channels(ffmpeg_codec_data* data) {
if (!data || !data->codecCtx)
return 0;
return data->codecCtx->channels;
}
int ffmpeg_get_subsong_count(ffmpeg_codec_data* data) {
if (!data)
return 0;
return data->stream_count;
}
STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data) { STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data) {
if (!data) return NULL; if (!data) return NULL;
return data->streamfile; return data->sf;
} }
#endif #endif

View File

@ -764,10 +764,8 @@ static ffmpeg_codec_data* init_ffmpeg_custom_opus_config(STREAMFILE* sf, off_t s
/* FFmpeg + libopus: skips samples, notifies skip in codecCtx->delay (not in stream->skip_samples) /* FFmpeg + libopus: skips samples, notifies skip in codecCtx->delay (not in stream->skip_samples)
* FFmpeg + opus: *doesn't* skip, also notifies skip in codecCtx->delay, hurray (possibly fixed in recent versions) * FFmpeg + opus: *doesn't* skip, also notifies skip in codecCtx->delay, hurray (possibly fixed in recent versions)
* FFmpeg + opus is audibly buggy with some low bitrate SSB Ultimate files too */ * FFmpeg + opus is audibly buggy with some low bitrate SSB Ultimate files */
//if (ffmpeg_data->skipSamples <= 0) { //ffmpeg_set_skip_samples(ffmpeg_data, skip);
// ffmpeg_set_skip_samples(ffmpeg_data, skip);
//}
close_streamfile(temp_sf); close_streamfile(temp_sf);
return ffmpeg_data; return ffmpeg_data;
@ -786,7 +784,7 @@ static ffmpeg_codec_data* init_ffmpeg_custom_opus(STREAMFILE* sf, off_t start_of
return init_ffmpeg_custom_opus_config(sf, start_offset, data_size, &cfg, type); return init_ffmpeg_custom_opus_config(sf, start_offset, data_size, &cfg, type);
} }
ffmpeg_codec_data* init_ffmpeg_custom_table_opus(STREAMFILE* sf, off_t table_offset, int table_count, off_t data_offset, size_t data_size, int channels, int skip, int sample_rate, opus_type_t type) { static ffmpeg_codec_data* init_ffmpeg_custom_table_opus(STREAMFILE* sf, off_t table_offset, int table_count, off_t data_offset, size_t data_size, int channels, int skip, int sample_rate, opus_type_t type) {
opus_config cfg = {0}; opus_config cfg = {0};
cfg.channels = channels; cfg.channels = channels;
cfg.skip = skip; cfg.skip = skip;

View File

@ -2,7 +2,7 @@
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
static 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) { static 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; uint16_t codec_ATRAC3 = 0x0270;
size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4; size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4;
@ -41,7 +41,7 @@ static int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample
return riff_size; return riff_size;
} }
ffmpeg_codec_data * init_ffmpeg_atrac3_raw(STREAMFILE *sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay) { ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay) {
ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[0x100]; uint8_t buf[0x100];
int bytes; int bytes;
@ -57,16 +57,14 @@ ffmpeg_codec_data * init_ffmpeg_atrac3_raw(STREAMFILE *sf, off_t offset, size_t
* in offsets, so calcs are expected to be handled externally (presumably the game would call raw decoding API * in offsets, so calcs are expected to be handled externally (presumably the game would call raw decoding API
* and any skips would be handled manually) */ * and any skips would be handled manually) */
/* FFmpeg reads this but just in case they fiddle with it in the future */
ffmpeg_data->totalSamples = sample_count;
/* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame) /* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame)
* FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */ * FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */
ffmpeg_set_skip_samples(ffmpeg_data, encoder_delay); ffmpeg_set_skip_samples(ffmpeg_data, encoder_delay);
//ffmpeg_set_samples(sample_count); /* useful? */
/* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */
if (is_at3) { if (is_at3) {
ffmpeg_data->invert_floats_set = 1; ffmpeg_set_invert_floats(ffmpeg_data);
} }
return ffmpeg_data; return ffmpeg_data;
@ -76,7 +74,7 @@ fail:
} }
/* init ATRAC3/plus while adding some fixes */ /* init ATRAC3/plus while adding some fixes */
ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples) { ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* p_samples) {
ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_codec_data *ffmpeg_data = NULL;
int is_at3 = 0, is_at3p = 0, codec; int is_at3 = 0, is_at3p = 0, codec;
size_t riff_size; size_t riff_size;
@ -151,35 +149,33 @@ ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* o
implicit_skip = 0; implicit_skip = 0;
} }
/* FFmpeg reads this but just in case they fiddle with it in the future */
ffmpeg_data->totalSamples = fact_samples;
/* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame) /* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame)
* FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */ * FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples + implicit_skip); ffmpeg_set_skip_samples(ffmpeg_data, skip_samples + implicit_skip);
//ffmpeg_set_samples(sample_count); /* useful? */
/* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */
if (is_at3) { if (is_at3) {
ffmpeg_data->invert_floats_set = 1; ffmpeg_set_invert_floats(ffmpeg_data);
} }
/* multichannel fix: LFE channel should be reordered on decode (ATRAC3Plus only, only 1/2/6/8ch exist): /* multichannel fix: LFE channel should be reordered on decode (ATRAC3Plus only, only 1/2/6/8ch exist):
* - 6ch: FL FR FC BL BR LFE > FL FR FC LFE BL BR * - 6ch: FL FR FC BL BR LFE > FL FR FC LFE BL BR
* - 8ch: FL FR FC BL BR SL SR LFE > FL FR FC LFE BL BR SL SR */ * - 8ch: FL FR FC BL BR SL SR LFE > FL FR FC LFE BL BR SL SR */
if (is_at3p && ffmpeg_data->channels == 6) { if (is_at3p && ffmpeg_get_channels(ffmpeg_data) == 6) {
/* LFE BR BL > LFE BL BR > same */ /* LFE BR BL > LFE BL BR > same */
int channel_remap[] = { 0, 1, 2, 5, 5, 5, }; int channel_remap[] = { 0, 1, 2, 5, 5, 5, };
ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap); ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap);
} }
else if (is_at3p && ffmpeg_data->channels == 8) { else if (is_at3p && ffmpeg_get_channels(ffmpeg_data) == 8) {
/* LFE BR SL SR BL > LFE BL SL SR BR > LFE BL BR SR SL > LFE BL BR SL SR > same */ /* LFE BR SL SR BL > LFE BL SL SR BR > LFE BL BR SR SL > LFE BL BR SL SR > same */
int channel_remap[] = { 0, 1, 2, 7, 7, 7, 7, 7}; int channel_remap[] = { 0, 1, 2, 7, 7, 7, 7, 7};
ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap); ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap);
} }
if (out_samples) if (p_samples)
*out_samples = fact_samples; *p_samples = fact_samples;
return ffmpeg_data; return ffmpeg_data;
fail: fail:
@ -187,7 +183,7 @@ fail:
return NULL; return NULL;
} }
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size) { ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples) {
ffmpeg_codec_data* data = NULL; ffmpeg_codec_data* data = NULL;
data = init_ffmpeg_offset(sf, offset, size); data = init_ffmpeg_offset(sf, offset, size);
@ -199,7 +195,7 @@ ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size) {
/* raw AAC doesn't set this, while some decoders like FAAD remove 1024, /* raw AAC doesn't set this, while some decoders like FAAD remove 1024,
* but should be handled in container as each encoder uses its own value * but should be handled in container as each encoder uses its own value
* (Apple: 2112, FAAD: probably 1024, etc) */ * (Apple: 2112, FAAD: probably 1024, etc) */
//ffmpeg_set_skip_samples(data, 1024); ffmpeg_set_skip_samples(data, skip_samples);
return data; return data;
fail: fail:

View File

@ -302,7 +302,7 @@ static void aes_decrypt_block(s14aes_handle* ctx, uint8_t* buf) {
/* **************************** */ /* **************************** */
s14aes_handle* s14aes_init() { s14aes_handle* s14aes_init(void) {
s14aes_handle* ctx = malloc(sizeof(s14aes_handle)); s14aes_handle* ctx = malloc(sizeof(s14aes_handle));
if (!ctx) goto fail; if (!ctx) goto fail;

View File

@ -6,7 +6,7 @@
typedef struct s14aes_handle s14aes_handle; typedef struct s14aes_handle s14aes_handle;
/* init/close handle (AES-192 in ECB mode) */ /* init/close handle (AES-192 in ECB mode) */
s14aes_handle* s14aes_init(); s14aes_handle* s14aes_init(void);
void s14aes_close(s14aes_handle* ctx); void s14aes_close(s14aes_handle* ctx);

View File

@ -1,4 +1,5 @@
#include "coding.h" #include "coding.h"
#include "clHCA.h"
struct hca_codec_data { struct hca_codec_data {

View File

@ -983,7 +983,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t *
} }
/* mono XBOX-IMA with header endianness and alt nibble expand (verified vs AK test demos) */ /* mono XBOX-IMA with header endianness and alt nibble expand (verified vs AK test demos) */
void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { void decode_wwise_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count = 0, num_frame; int i, sample_count = 0, num_frame;
int32_t hist1 = stream->adpcm_history1_32; int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index; int step_index = stream->adpcm_step_index;
@ -1242,7 +1242,7 @@ static inline int _clamp_s32(int value, int min, int max) {
/* Crystal Dynamics IMA. Original code uses mind-bending intrinsics, so this may not be fully accurate. /* Crystal Dynamics IMA. Original code uses mind-bending intrinsics, so this may not be fully accurate.
* Has another table with delta_table MMX combos, and uses header sample (first nibble is always 0). */ * Has another table with delta_table MMX combos, and uses header sample (first nibble is always 0). */
void decode_cd_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { void decode_cd_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x24] = {0}; uint8_t frame[0x24] = {0};
int i, frames_in, sample_pos = 0, block_samples, frame_size; int i, frames_in, sample_pos = 0, block_samples, frame_size;
int32_t hist1 = stream->adpcm_history1_32; int32_t hist1 = stream->adpcm_history1_32;

View File

@ -309,7 +309,7 @@ fail:
/* **************************************** */ /* **************************************** */
static void decode_vima1(STREAMFILE* sf, sbuf_t* sbuf, uint8_t* buf, size_t data_left, int block_num, uint16_t* adpcm_table) { static void decode_vima1(sbuf_t* sbuf, uint8_t* buf, size_t data_left, int block_num, uint16_t* adpcm_table) {
int ch, i, j, s; int ch, i, j, s;
int bitpos; int bitpos;
int adpcm_history[MAX_CHANNELS] = {0}; int adpcm_history[MAX_CHANNELS] = {0};
@ -420,13 +420,13 @@ static void decode_vima1(STREAMFILE* sf, sbuf_t* sbuf, uint8_t* buf, size_t data
sbuf->filled += data_left / sizeof(int16_t) / chs; sbuf->filled += data_left / sizeof(int16_t) / chs;
} }
static int decode_block1(STREAMFILE* sf, imuse_codec_data* data, uint8_t* block, size_t data_left) { static int decode_block1(imuse_codec_data* data, uint8_t* block, size_t data_left) {
int block_num = data->current_block; int block_num = data->current_block;
switch(data->block_table[block_num].flags) { switch(data->block_table[block_num].flags) {
case 0x0D: case 0x0D:
case 0x0F: case 0x0F:
decode_vima1(sf, &data->sbuf, block, data_left, block_num, data->adpcm_table); decode_vima1(&data->sbuf, block, data_left, block_num, data->adpcm_table);
break; break;
default: default:
return 0; return 0;
@ -434,7 +434,7 @@ static int decode_block1(STREAMFILE* sf, imuse_codec_data* data, uint8_t* block,
return 1; return 1;
} }
static void decode_data2(STREAMFILE* sf, sbuf_t* sbuf, uint8_t* buf, size_t data_left, int block_num) { static void decode_data2(sbuf_t* sbuf, uint8_t* buf, size_t data_left, int block_num) {
int i, j; int i, j;
int channels = sbuf->channels; int channels = sbuf->channels;
@ -453,7 +453,7 @@ static void decode_data2(STREAMFILE* sf, sbuf_t* sbuf, uint8_t* buf, size_t data
} }
} }
static void decode_vima2(STREAMFILE* sf, sbuf_t* sbuf, uint8_t* buf, size_t data_left, uint16_t* adpcm_table) { static void decode_vima2(sbuf_t* sbuf, uint8_t* buf, size_t data_left, uint16_t* adpcm_table) {
int ch, i, s; int ch, i, s;
int bitpos; int bitpos;
int adpcm_history[MAX_CHANNELS] = {0}; int adpcm_history[MAX_CHANNELS] = {0};
@ -554,16 +554,16 @@ static void decode_vima2(STREAMFILE* sf, sbuf_t* sbuf, uint8_t* buf, size_t data
sbuf->filled += data_left / sizeof(int16_t) / chs; sbuf->filled += data_left / sizeof(int16_t) / chs;
} }
static int decode_block2(STREAMFILE* sf, imuse_codec_data* data, uint8_t* block, size_t data_left) { static int decode_block2(imuse_codec_data* data, uint8_t* block, size_t data_left) {
int block_num = data->current_block; int block_num = data->current_block;
switch(data->block_table[block_num].flags) { switch(data->block_table[block_num].flags) {
case 0x00: case 0x00:
decode_data2(sf, &data->sbuf, block, data_left, block_num); decode_data2(&data->sbuf, block, data_left, block_num);
break; break;
case 0x01: case 0x01:
decode_vima2(sf, &data->sbuf, block, data_left, data->adpcm_table); decode_vima2(&data->sbuf, block, data_left, data->adpcm_table);
break; break;
default: default:
return 0; return 0;
@ -597,11 +597,11 @@ static int decode_block(STREAMFILE* sf, imuse_codec_data* data) {
switch(data->type) { switch(data->type) {
case COMP: case COMP:
ok = decode_block1(sf, data, block, data_left); ok = decode_block1(data, block, data_left);
break; break;
case MCMP: case MCMP:
ok = decode_block2(sf, data, block, data_left); ok = decode_block2(data, block, data_left);
break; break;
default: default:

View File

@ -3,13 +3,12 @@
#include "../vgmstream.h" #include "../vgmstream.h"
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
#include <mpg123/mpg123.h>
#include "mpeg_decoder.h" #include "mpeg_decoder.h"
#define MPEG_DATA_BUFFER_SIZE 0x1000 /* at least one MPEG frame (max ~0x5A1 plus some more in case of free bitrate) */ #define MPEG_DATA_BUFFER_SIZE 0x1000 /* at least one MPEG frame (max ~0x5A1 plus some more in case of free bitrate) */
static mpg123_handle* init_mpg123_handle(); static mpg123_handle* init_mpg123_handle(void);
static void decode_mpeg_standard(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channels); static void decode_mpeg_standard(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channels);
static void decode_mpeg_custom(VGMSTREAM* vgmstream, mpeg_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channels); static void decode_mpeg_custom(VGMSTREAM* vgmstream, mpeg_codec_data* data, sample_t* outbuf, int32_t samples_to_do, int channels);
static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data* data, int num_stream); static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data* data, int num_stream);
@ -185,7 +184,7 @@ fail:
} }
static mpg123_handle* init_mpg123_handle() { static mpg123_handle* init_mpg123_handle(void) {
mpg123_handle* m = NULL; mpg123_handle* m = NULL;
int rc; int rc;

View File

@ -1,5 +1,6 @@
#ifndef _MPEG_DECODER_H_ #ifndef _MPEG_DECODER_H_
#define _MPEG_DECODER_H_ #define _MPEG_DECODER_H_
#include <mpg123/mpg123.h>
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../coding/coding.h" #include "../coding/coding.h"

View File

@ -0,0 +1,63 @@
#include "coding.h"
/* Decodes Tantalus TADC ADPCM codec, used in Saturn games.
* Guessed based on other XA-style codecs values. */
void decode_tantalus(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x10] = {0};
off_t frame_offset;
int i, frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
int shift, filter, coef1, coef2;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
/* external interleave (fixed size), mono */
bytes_per_frame = 0x10;
samples_per_frame = (bytes_per_frame - 0x01) * 2;
frames_in = first_sample / samples_per_frame;
//first_sample = first_sample % samples_per_frame; /* for flat layout */
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame*frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
filter = (frame[0x00] >> 4) & 0xf; /* 0 in tested files */
shift = (frame[0x00] >> 0) & 0xf;
if (filter != 0) {
VGM_LOG_ONCE("TANTALUS: unknown filter\n");
coef1 = 64;
coef2 = 64; /* will sound horrid and hopefully reported */
}
else {
coef1 = 64;
coef2 = 0;
}
/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
uint8_t nibbles = frame[0x01 + i/2];
int32_t sample;
sample = i&1 ? /* low nibble first */
get_high_nibble_signed(nibbles) :
get_low_nibble_signed(nibbles);
sample = sample << (shift + 6);
sample = (sample + (hist1 * coef1) + (hist2 * coef2)) >> 6;
outbuf[sample_count] = clamp16(sample);
sample_count += channelspacing;
hist2 = hist1;
hist1 = sample;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2;
}
int32_t tantalus_bytes_to_samples(size_t bytes, int channels) {
if (channels <= 0) return 0;
return bytes / channels / 0x10 * 30;
}

View File

@ -455,7 +455,7 @@ static void decode_subframe_stereo(ubi_adpcm_channel_data* ch0_state, ubi_adpcm_
* 0xA82557DB LE = 1010 100000 100101 010101 111101 1011 ... (where last 00 | first 1010 = 001010), etc * 0xA82557DB LE = 1010 100000 100101 010101 111101 1011 ... (where last 00 | first 1010 = 001010), etc
* Codes aren't signed but rather have a particular meaning (see decoding). * Codes aren't signed but rather have a particular meaning (see decoding).
*/ */
void unpack_codes(uint8_t* data, uint8_t* codes, int code_count, int bps) { static void unpack_codes(uint8_t* data, uint8_t* codes, int code_count, int bps) {
int i; int i;
size_t pos = 0; size_t pos = 0;
uint64_t bits = 0, input = 0; uint64_t bits = 0, input = 0;

View File

@ -3,7 +3,6 @@
#include "vorbis_custom_decoder.h" #include "vorbis_custom_decoder.h"
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
#include <vorbis/codec.h>
#define VORBIS_DEFAULT_BUFFER_SIZE 0x8000 /* should be at least the size of the setup header, ~0x2000 */ #define VORBIS_DEFAULT_BUFFER_SIZE 0x8000 /* should be at least the size of the setup header, ~0x2000 */

View File

@ -6,6 +6,7 @@
/* used by vorbis_custom_decoder.c, but scattered in other .c files */ /* used by vorbis_custom_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
#include <vorbis/codec.h>
/* custom Vorbis without Ogg layer */ /* custom Vorbis without Ogg layer */
struct vorbis_custom_codec_data { struct vorbis_custom_codec_data {

View File

@ -77,7 +77,7 @@ int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL* stream, vorbis_custom_code
/* get packet info the VID1 header */ /* get packet info the VID1 header */
get_packet_header(stream->streamfile, &stream->offset, (uint32_t*)&data->op.bytes); get_packet_header(stream->streamfile, &stream->offset, (size_t*)&data->op.bytes);
if (data->op.bytes == 0 || data->op.bytes > data->buffer_size) goto fail; /* EOF or end padding */ if (data->op.bytes == 0 || data->op.bytes > data->buffer_size) goto fail; /* EOF or end padding */
/* read raw block */ /* read raw block */

View File

@ -365,11 +365,6 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack
/* rebuild first bits of packet type and window info (for the i-MDCT) */ /* rebuild first bits of packet type and window info (for the i-MDCT) */
uint32_t packet_type = 0, mode_number = 0, remainder = 0; uint32_t packet_type = 0, mode_number = 0, remainder = 0;
if (!data->mode_blockflag) { /* config error */
VGM_LOG("Wwise Vorbis: didn't load mode_blockflag\n");
goto fail;
}
/* audio packet type */ /* audio packet type */
packet_type = 0; packet_type = 0;
wv_bits(ow, 1, packet_type); wv_bits(ow, 1, packet_type);
@ -434,8 +429,8 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack
return 1; return 1;
fail: //fail:
return 0; // return 0;
} }
/*******************************************************************************/ /*******************************************************************************/

View File

@ -135,6 +135,8 @@ void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channels
samples_left_in_frame--) { /* done with reading a sample */ samples_left_in_frame--) { /* done with reading a sample */
outbuf[sample_count]=(hist-0x80)*0x100; outbuf[sample_count]=(hist-0x80)*0x100;
} }
default:
break;
} }
} }
} }

View File

@ -503,6 +503,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
return 256; /* (0x8c - 0xc) * 2 */ return 256; /* (0x8c - 0xc) * 2 */
case coding_ASF: case coding_ASF:
return 32; /* (0x11 - 0x1) * 2 */ return 32; /* (0x11 - 0x1) * 2 */
case coding_TANTALUS:
return 30; /* (0x10 - 0x01) * 2 */
case coding_DSA: case coding_DSA:
return 14; /* (0x08 - 0x1) * 2 */ return 14; /* (0x08 - 0x1) * 2 */
case coding_XMD: case coding_XMD:
@ -716,6 +718,8 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
return 0x8c; return 0x8c;
case coding_ASF: case coding_ASF:
return 0x11; return 0x11;
case coding_TANTALUS:
return 0x10;
case coding_DSA: case coding_DSA:
return 0x08; return 0x08;
case coding_XMD: case coding_XMD:
@ -1008,7 +1012,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
case coding_EA_XA_V2: case coding_EA_XA_V2:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_ea_xa_v2(&vgmstream->ch[ch], buffer+ch, decode_ea_xa_v2(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do, ch); vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
} }
break; break;
case coding_MAXIS_XA: case coding_MAXIS_XA:
@ -1020,7 +1024,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
case coding_EA_XAS_V0: case coding_EA_XAS_V0:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_ea_xas_v0(&vgmstream->ch[ch], buffer+ch, decode_ea_xas_v0(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do, ch); vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
} }
break; break;
case coding_EA_XAS_V1: case coding_EA_XAS_V1:
@ -1184,7 +1188,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
case coding_WWISE_IMA: case coding_WWISE_IMA:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_wwise_ima(vgmstream,&vgmstream->ch[ch], buffer+ch, decode_wwise_ima(vgmstream,&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do, ch); vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
} }
break; break;
case coding_REF_IMA: case coding_REF_IMA:
@ -1223,7 +1227,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
case coding_CD_IMA: case coding_CD_IMA:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_cd_ima(&vgmstream->ch[ch], buffer+ch, decode_cd_ima(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do, ch); vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
} }
break; break;
@ -1386,6 +1390,12 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
vgmstream->channels, vgmstream->samples_into_block, samples_to_do); vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
} }
break; break;
case coding_TANTALUS:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_tantalus(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
}
break;
case coding_DSA: case coding_DSA:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_dsa(&vgmstream->ch[ch], buffer+ch, decode_dsa(&vgmstream->ch[ch], buffer+ch,

View File

@ -515,6 +515,7 @@ static const char* extension_list[] = {
"sxd2", "sxd2",
"sxd3", "sxd3",
"tad",
"tec", "tec",
"tgq", "tgq",
"thp", "thp",
@ -787,6 +788,7 @@ static const coding_info coding_info_list[] = {
{coding_MC3, "Paradigm MC3 3-bit ADPCM"}, {coding_MC3, "Paradigm MC3 3-bit ADPCM"},
{coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"}, {coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"},
{coding_ASF, "Argonaut ASF 4-bit ADPCM"}, {coding_ASF, "Argonaut ASF 4-bit ADPCM"},
{coding_TANTALUS, "Tantalus 4-bit ADPCM"},
{coding_DSA, "Ocean DSA 4-bit ADPCM"}, {coding_DSA, "Ocean DSA 4-bit ADPCM"},
{coding_XMD, "Konami XMD 4-bit ADPCM"}, {coding_XMD, "Konami XMD 4-bit ADPCM"},
{coding_PCFX, "PC-FX 4-bit ADPCM"}, {coding_PCFX, "PC-FX 4-bit ADPCM"},
@ -997,7 +999,7 @@ static const meta_info meta_info_list[] = {
{meta_LEG, "Legaia 2 - Duel Saga LEG Header"}, {meta_LEG, "Legaia 2 - Duel Saga LEG Header"},
{meta_FILP, "Bio Hazard - Gun Survivor FILp Header"}, {meta_FILP, "Bio Hazard - Gun Survivor FILp Header"},
{meta_IKM, "MiCROViSiON IKM header"}, {meta_IKM, "MiCROViSiON IKM header"},
{meta_SFS, "Baroque SFS Header"}, {meta_SFS, "String .SFS header"},
{meta_SAT_DVI, "Konami KCEN DVI. header"}, {meta_SAT_DVI, "Konami KCEN DVI. header"},
{meta_DC_KCEY, "Konami KCEY KCEYCOMP header"}, {meta_DC_KCEY, "Konami KCEY KCEYCOMP header"},
{meta_BG00, "Falcom BG00 Header"}, {meta_BG00, "Falcom BG00 Header"},
@ -1350,6 +1352,7 @@ static const meta_info meta_info_list[] = {
{meta_IDSP_TOSE, "TOSE .IDSP header"}, {meta_IDSP_TOSE, "TOSE .IDSP header"},
{meta_DSP_KWA, "Kuju London .KWA header"}, {meta_DSP_KWA, "Kuju London .KWA header"},
{meta_OGV_3RDEYE, "3rdEye .OGV header"}, {meta_OGV_3RDEYE, "3rdEye .OGV header"},
{meta_PIFF_TPCM, "Tantalus PIFF TPCM header"},
}; };
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {

View File

@ -4,7 +4,7 @@
#include "../vgmstream.h" #include "../vgmstream.h"
static size_t get_channel_header_size(STREAMFILE* sf, off_t offset, int channels, int big_endian); static size_t get_channel_header_size(STREAMFILE* sf, off_t offset, int big_endian);
static size_t get_block_header_size(STREAMFILE* sf, off_t offset, size_t channel_header_size, int channels, int big_endian); static size_t get_block_header_size(STREAMFILE* sf, off_t offset, size_t channel_header_size, int channels, int big_endian);
/* AWC music chunks */ /* AWC music chunks */
@ -38,7 +38,7 @@ void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream) {
* 32b * entries = global samples per frame in each block (for MPEG probably per full frame) * 32b * entries = global samples per frame in each block (for MPEG probably per full frame)
*/ */
channel_header_size = get_channel_header_size(sf, block_offset, vgmstream->channels, vgmstream->codec_endian); channel_header_size = get_channel_header_size(sf, block_offset, vgmstream->codec_endian);
header_size = get_block_header_size(sf, block_offset, channel_header_size, vgmstream->channels, vgmstream->codec_endian); header_size = get_block_header_size(sf, block_offset, channel_header_size, vgmstream->channels, vgmstream->codec_endian);
for (i = 0; i < vgmstream->channels; i++) { for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = block_offset + header_size + 0x800*entries*i; vgmstream->ch[i].offset = block_offset + header_size + 0x800*entries*i;
@ -47,7 +47,7 @@ void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream) {
} }
static size_t get_channel_header_size(STREAMFILE* sf, off_t offset, int channels, int big_endian) { static size_t get_channel_header_size(STREAMFILE* sf, off_t offset, int big_endian) {
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE; int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
/* later games have an smaller channel header, try to detect using /* later games have an smaller channel header, try to detect using

View File

@ -4,7 +4,7 @@
/* XVAG with subsongs layers, interleaves chunks of each subsong (a hack to support them) */ /* XVAG with subsongs layers, interleaves chunks of each subsong (a hack to support them) */
void block_update_xvag_subsong(off_t block_offset, VGMSTREAM * vgmstream) { void block_update_xvag_subsong(off_t block_offset, VGMSTREAM* vgmstream) {
int i; int i;
size_t channel_size = 0x10; size_t channel_size = 0x10;

View File

@ -240,6 +240,7 @@ VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data) {
int i, channels, loop_flag, sample_rate, external_looping; int i, channels, loop_flag, sample_rate, external_looping;
int32_t num_samples, loop_start, loop_end; int32_t num_samples, loop_start, loop_end;
int delta = 1024; int delta = 1024;
coding_t coding_type = data->layers[0]->coding_type;
/* get data */ /* get data */
channels = data->output_channels; channels = data->output_channels;
@ -250,6 +251,7 @@ VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data) {
loop_end = data->layers[0]->loop_end_sample; loop_end = data->layers[0]->loop_end_sample;
external_looping = 0; external_looping = 0;
sample_rate = 0; sample_rate = 0;
for (i = 0; i < data->layer_count; i++) { for (i = 0; i < data->layer_count; i++) {
int32_t layer_samples = vgmstream_get_samples(data->layers[i]); int32_t layer_samples = vgmstream_get_samples(data->layers[i]);
int layer_loop = data->layers[i]->loop_flag; int layer_loop = data->layers[i]->loop_flag;
@ -280,6 +282,9 @@ VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data) {
if (sample_rate < layer_rate) if (sample_rate < layer_rate)
sample_rate = layer_rate; sample_rate = layer_rate;
if (coding_type == coding_SILENCE)
coding_type = data->layers[i]->coding_type;
} }
data->external_looping = external_looping; data->external_looping = external_looping;
@ -289,12 +294,12 @@ VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data) {
vgmstream = allocate_vgmstream(channels, loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = data->layers[0]->meta_type;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start; vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end; vgmstream->loop_end_sample = loop_end;
vgmstream->meta_type = data->layers[0]->meta_type; /* info */ vgmstream->coding_type = coding_type;
vgmstream->coding_type = data->layers[0]->coding_type; /* info */
vgmstream->layout_type = layout_layered; vgmstream->layout_type = layout_layered;
vgmstream->layout_data = data; vgmstream->layout_data = data;

View File

@ -296,6 +296,7 @@ VGMSTREAM* allocate_segmented_vgmstream(segmented_layout_data* data, int loop_fl
int channel_layout; int channel_layout;
int i, sample_rate; int i, sample_rate;
int32_t num_samples, loop_start, loop_end; int32_t num_samples, loop_start, loop_end;
coding_t coding_type = data->segments[0]->coding_type;
/* save data */ /* save data */
channel_layout = data->segments[0]->channel_layout; channel_layout = data->segments[0]->channel_layout;
@ -322,10 +323,14 @@ VGMSTREAM* allocate_segmented_vgmstream(segmented_layout_data* data, int loop_fl
if (sample_rate < segment_rate) if (sample_rate < segment_rate)
sample_rate = segment_rate; sample_rate = segment_rate;
if (coding_type == coding_SILENCE)
coding_type = data->segments[i]->coding_type;
} }
/* respect loop_flag even when no loop_end found as it's possible file loops are set outside */ /* respect loop_flag even when no loop_end found as it's possible file loops are set outside */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(data->output_channels, loop_flag); vgmstream = allocate_vgmstream(data->output_channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
@ -335,7 +340,7 @@ VGMSTREAM* allocate_segmented_vgmstream(segmented_layout_data* data, int loop_fl
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start; vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end; vgmstream->loop_end_sample = loop_end;
vgmstream->coding_type = data->segments[0]->coding_type; vgmstream->coding_type = coding_type;
vgmstream->channel_layout = channel_layout; vgmstream->channel_layout = channel_layout;
vgmstream->layout_type = layout_segmented; vgmstream->layout_type = layout_segmented;

View File

@ -2,43 +2,42 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* .208 - from Ocean game(s?) [Last Rites (PC)] */ /* .208 - from Ocean game(s?) [Last Rites (PC)] */
VGMSTREAM * init_vgmstream_208(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_208(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset, data_size;
int loop_flag, channel_count, sample_rate; int loop_flag, channels, sample_rate;
size_t data_size;
/* checks */ /* checks */
if (!check_extensions(streamFile, "208")) if (!check_extensions(sf, "208"))
goto fail; goto fail;
/* possible validation: (0x04 == 0 and 0xcc == 0x1F7D984D) or 0x04 == 0xf0 and 0xcc == 0) */ /* possible validation: (0x04 == 0 and 0xcc == 0x1F7D984D) or 0x04 == 0xf0 and 0xcc == 0) */
if (!((read_32bitLE(0x04,streamFile) == 0x00 && read_32bitBE(0xcc,streamFile) == 0x1F7D984D) || if (!((read_u32le(0x04,sf) == 0x00 && read_u32be(0xcc,sf) == 0x1F7D984D) ||
(read_32bitLE(0x04,streamFile) == 0xF0 && read_32bitBE(0xcc,streamFile) == 0x00000000))) (read_u32le(0x04,sf) == 0xF0 && read_u32be(0xcc,sf) == 0x00000000)))
goto fail; goto fail;
start_offset = read_32bitLE(0x00,streamFile); start_offset = read_s32le(0x00,sf);
data_size = read_32bitLE(0x0c,streamFile); data_size = read_s32le(0x0c,sf);
sample_rate = read_32bitLE(0x34,streamFile); sample_rate = read_s32le(0x34,sf);
channel_count = read_32bitLE(0x3C,streamFile); /* assumed */ channels = read_s32le(0x3C,sf); /* assumed */
loop_flag = 0; loop_flag = 0;
if (start_offset + data_size != get_streamfile_size(streamFile)) if (start_offset + data_size != get_streamfile_size(sf))
goto fail; goto fail;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_208; vgmstream->meta_type = meta_208;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 8); vgmstream->num_samples = pcm8_bytes_to_samples(data_size, channels);
vgmstream->coding_type = coding_PCM8_U; vgmstream->coding_type = coding_PCM8_U;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1; vgmstream->interleave_block_size = 0x1;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -91,7 +91,7 @@ fail:
#define ACB_MAX_NAME 1024 /* even more is possible in rare cases [Senran Kagura Burst Re:Newal (PC)] */ #define ACB_MAX_NAME 1024 /* even more is possible in rare cases [Senran Kagura Burst Re:Newal (PC)] */
STREAMFILE* setup_acb_streamfile(STREAMFILE* sf, size_t buffer_size) { static STREAMFILE* setup_acb_streamfile(STREAMFILE* sf, size_t buffer_size) {
STREAMFILE* new_sf = NULL; STREAMFILE* new_sf = NULL;
/* buffer seems better than reopening when opening multiple subsongs at the same time with STDIO, /* buffer seems better than reopening when opening multiple subsongs at the same time with STDIO,

View File

@ -274,7 +274,7 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
key_size = read_key_file(keybuf, sizeof(keybuf), sf); key_size = read_key_file(keybuf, sizeof(keybuf), sf);
if (key_size > 0) { if (key_size > 0) {
int i, is_ascii = 0; int is_ascii = 0;
/* keystrings should be ASCII, also needed to tell apart 0x06 strings from derived keys */ /* keystrings should be ASCII, also needed to tell apart 0x06 strings from derived keys */
if (type == 8) { if (type == 8) {

View File

@ -2,8 +2,8 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* .AIF - from Asobo Studio games [Ratatouille (PC), WALL-E (PC), Up (PC)] */ /* .AIF - from Asobo Studio games [Ratatouille (PC), WALL-E (PC), Up (PC)] */
VGMSTREAM * init_vgmstream_aif_asobo(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_aif_asobo(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
size_t data_size; size_t data_size;
int loop_flag, channel_count; int loop_flag, channel_count;
@ -11,23 +11,23 @@ VGMSTREAM * init_vgmstream_aif_asobo(STREAMFILE *streamFile) {
/* checks */ /* checks */
/* aif: standard, .laif/aiffl: for plugins */ /* aif: standard, .laif/aiffl: for plugins */
if ( !check_extensions(streamFile,"aif,laif,aiffl") ) if ( !check_extensions(sf,"aif,laif,aiffl") )
goto fail; goto fail;
if ((uint16_t)read_16bitLE(0x00,streamFile) != 0x69) /* Xbox codec */ if ((uint16_t)read_16bitLE(0x00,sf) != 0x69) /* Xbox codec */
goto fail; goto fail;
channel_count = read_16bitLE(0x02,streamFile); /* assumed, only stereo is known */ channel_count = read_16bitLE(0x02,sf); /* assumed, only stereo is known */
if (channel_count != 2) goto fail; if (channel_count != 2) goto fail;
/* 0x08: ? */ /* 0x08: ? */
if ((uint16_t)read_16bitLE(0x0c,streamFile) != 0x24*channel_count) /* Xbox block */ if ((uint16_t)read_16bitLE(0x0c,sf) != 0x24*channel_count) /* Xbox block */
goto fail; goto fail;
if ((uint16_t)read_16bitLE(0x0e,streamFile) != 0x04) /* Xbox bps */ if ((uint16_t)read_16bitLE(0x0e,sf) != 0x04) /* Xbox bps */
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
start_offset = 0x14; start_offset = 0x14;
data_size = get_streamfile_size(streamFile) - start_offset; data_size = get_streamfile_size(sf) - start_offset;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
@ -35,13 +35,13 @@ VGMSTREAM * init_vgmstream_aif_asobo(STREAMFILE *streamFile) {
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_AIF_ASOBO; vgmstream->meta_type = meta_AIF_ASOBO;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile); vgmstream->sample_rate = read_32bitLE(0x04,sf);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size,channel_count); vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size,channel_count);
vgmstream->coding_type = coding_XBOX_IMA; vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -3,20 +3,20 @@
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
/* AKB (AAC only) - found in SQEX iOS games */ /* AKB (AAC only) - found in SQEX iOS games */
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
size_t filesize; size_t filesize;
uint32_t loop_start, loop_end; uint32_t loop_start, loop_end;
if ((uint32_t)read_32bitBE(0, streamFile) != 0x414b4220) goto fail; if ((uint32_t)read_32bitBE(0, sf) != 0x414b4220) goto fail;
loop_start = read_32bitLE(0x14, streamFile); loop_start = read_32bitLE(0x14, sf);
loop_end = read_32bitLE(0x18, streamFile); loop_end = read_32bitLE(0x18, sf);
filesize = get_streamfile_size( streamFile ); filesize = get_streamfile_size( sf );
vgmstream = init_vgmstream_mp4_aac_offset( streamFile, 0x20, filesize - 0x20 ); vgmstream = init_vgmstream_mp4_aac_offset( sf, 0x20, filesize - 0x20 );
if ( !vgmstream ) goto fail; if ( !vgmstream ) goto fail;
if ( loop_start || loop_end ) { if ( loop_start || loop_end ) {
@ -34,7 +34,7 @@ fail:
/* AKB - found in SQEX iOS games */ /* AKB - found in SQEX iOS games */
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_akb(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, extradata_offset = 0; off_t start_offset, extradata_offset = 0;
size_t stream_size, header_size, subheader_size = 0, extradata_size = 0; size_t stream_size, header_size, subheader_size = 0, extradata_size = 0;
@ -44,28 +44,28 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
/* checks */ /* checks */
/* .akb.bytes is the usual extension in later games */ /* .akb.bytes is the usual extension in later games */
if ( !check_extensions(streamFile, "akb,bytes") ) if ( !check_extensions(sf, "akb,bytes") )
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x414B4220) /* "AKB " */ if (read_32bitBE(0x00,sf) != 0x414B4220) /* "AKB " */
goto fail; goto fail;
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile)) if (read_32bitLE(0x08,sf) != get_streamfile_size(sf))
goto fail; goto fail;
/* 0x04(1): version */ /* 0x04(1): version */
header_size = read_16bitLE(0x06,streamFile); header_size = read_16bitLE(0x06,sf);
codec = read_8bit(0x0c,streamFile); codec = read_8bit(0x0c,sf);
channel_count = read_8bit(0x0d,streamFile); channel_count = read_8bit(0x0d,sf);
sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile); sample_rate = (uint16_t)read_16bitLE(0x0e,sf);
num_samples = read_32bitLE(0x10,streamFile); num_samples = read_32bitLE(0x10,sf);
loop_start = read_32bitLE(0x14,streamFile); loop_start = read_32bitLE(0x14,sf);
loop_end = read_32bitLE(0x18,streamFile); loop_end = read_32bitLE(0x18,sf);
/* possibly more complex, see AKB2 */ /* possibly more complex, see AKB2 */
if (header_size >= 0x44) { /* v2+ */ if (header_size >= 0x44) { /* v2+ */
extradata_size = read_16bitLE(0x1c,streamFile); extradata_size = read_16bitLE(0x1c,sf);
/* 0x20+: config? (pan, volume) */ /* 0x20+: config? (pan, volume) */
subheader_size = read_16bitLE(0x28,streamFile); subheader_size = read_16bitLE(0x28,sf);
/* 0x24: file_id? */ /* 0x24: file_id? */
/* 0x2b: encryption bitflag if version > 2? */ /* 0x2b: encryption bitflag if version > 2? */
extradata_offset = header_size + subheader_size; extradata_offset = header_size + subheader_size;
@ -75,7 +75,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
start_offset = header_size; start_offset = header_size;
} }
stream_size = get_streamfile_size(streamFile) - start_offset; stream_size = get_streamfile_size(sf) - start_offset;
loop_flag = (loop_end > loop_start); loop_flag = (loop_end > loop_start);
@ -91,14 +91,14 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
case 0x02: { /* MSADPCM [Dragon Quest II (iOS) sfx] */ case 0x02: { /* MSADPCM [Dragon Quest II (iOS) sfx] */
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->frame_size = read_16bitLE(extradata_offset + 0x02,streamFile); vgmstream->frame_size = read_16bitLE(extradata_offset + 0x02,sf);
/* adjusted samples; bigger or smaller than base samples, akb lib uses these fields instead /* adjusted samples; bigger or smaller than base samples, akb lib uses these fields instead
* (base samples may have more than possible and read over file size otherwise, very strange) * (base samples may have more than possible and read over file size otherwise, very strange)
* loop_end seems to exist even with loop disabled */ * loop_end seems to exist even with loop disabled */
vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile); vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, sf);
vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile); vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, sf);
vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile); vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, sf);
break; break;
} }
@ -112,7 +112,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
/* extradata + 0x04: Ogg loop start offset */ /* extradata + 0x04: Ogg loop start offset */
/* oggs have loop info in the comments */ /* oggs have loop info in the comments */
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); ogg_vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
if (ogg_vgmstream) { if (ogg_vgmstream) {
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return ogg_vgmstream; return ogg_vgmstream;
@ -128,7 +128,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
/* Alt decoding without libvorbis (minor number of beginning samples difference). /* Alt decoding without libvorbis (minor number of beginning samples difference).
* Otherwise same output with (inaudible) +-1 lower byte differences due to rounding. */ * Otherwise same output with (inaudible) +-1 lower byte differences due to rounding. */
case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */ case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */
vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset,stream_size); vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset,stream_size);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
@ -145,7 +145,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x06: { /* M4A with AAC [The World Ends with You (iPad)] */ case 0x06: { /* M4A with AAC [The World Ends with You (iPad)] */
/* init_vgmstream_akb_mp4 above has priority, but this works fine too */ /* init_vgmstream_akb_mp4 above has priority, but this works fine too */
vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset,stream_size-start_offset); vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset,stream_size-start_offset);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
@ -168,7 +168,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
} }
/* open the file for reading */ /* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -180,22 +180,22 @@ fail:
/* AKB2 - found in later SQEX iOS games */ /* AKB2 - found in later SQEX iOS games */
VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_akb2(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, material_offset, extradata_offset; off_t start_offset, material_offset, extradata_offset;
size_t material_size, extradata_size, stream_size; size_t material_size, extradata_size, stream_size;
int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, num_samples, loop_start, loop_end; int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, num_samples, loop_start, loop_end;
int total_subsongs, target_subsong = streamFile->stream_index; int total_subsongs, target_subsong = sf->stream_index;
/* check extensions */ /* check extensions */
/* .akb.bytes is the usual extension in later games */ /* .akb.bytes is the usual extension in later games */
if ( !check_extensions(streamFile, "akb,bytes") ) if ( !check_extensions(sf, "akb,bytes") )
goto fail; goto fail;
/* checks */ /* checks */
if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */ if (read_32bitBE(0x00,sf) != 0x414B4232) /* "AKB2" */
goto fail; goto fail;
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile)) if (read_32bitLE(0x08,sf) != get_streamfile_size(sf))
goto fail; goto fail;
/* 0x04: version */ /* 0x04: version */
@ -203,37 +203,37 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
{ {
off_t table_offset; off_t table_offset;
size_t table_size, entry_size; size_t table_size, entry_size;
off_t akb_header_size = read_16bitLE(0x06, streamFile); off_t akb_header_size = read_16bitLE(0x06, sf);
int table_count = read_8bit(0x0c, streamFile); int table_count = read_8bit(0x0c, sf);
/* probably each table has its type somewhere, but only seen last table = sound table */ /* probably each table has its type somewhere, but only seen last table = sound table */
if (table_count > 2) /* 2 only seen in some Mobius FF sound banks */ if (table_count > 2) /* 2 only seen in some Mobius FF sound banks */
goto fail; goto fail;
entry_size = 0x10; /* technically every entry/table has its own size but to simplify... */ entry_size = 0x10; /* technically every entry/table has its own size but to simplify... */
table_offset = read_32bitLE(akb_header_size + (table_count-1)*entry_size + 0x04, streamFile); table_offset = read_32bitLE(akb_header_size + (table_count-1)*entry_size + 0x04, sf);
table_size = read_16bitLE(table_offset + 0x02, streamFile); table_size = read_16bitLE(table_offset + 0x02, sf);
total_subsongs = read_8bit(table_offset + 0x0f, streamFile); /* can contain 0 entries too */ total_subsongs = read_8bit(table_offset + 0x0f, sf); /* can contain 0 entries too */
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
material_offset = table_offset + read_32bitLE(table_offset + table_size + (target_subsong-1)*entry_size + 0x04, streamFile); material_offset = table_offset + read_32bitLE(table_offset + table_size + (target_subsong-1)*entry_size + 0x04, sf);
} }
/** stream header (material) **/ /** stream header (material) **/
/* 0x00: 0? */ /* 0x00: 0? */
codec = read_8bit(material_offset+0x01,streamFile); codec = read_8bit(material_offset+0x01,sf);
channel_count = read_8bit(material_offset+0x02,streamFile); channel_count = read_8bit(material_offset+0x02,sf);
encryption_flag = read_8bit(material_offset+0x03,streamFile); encryption_flag = read_8bit(material_offset+0x03,sf);
material_size = read_16bitLE(material_offset+0x04,streamFile); material_size = read_16bitLE(material_offset+0x04,sf);
sample_rate = (uint16_t)read_16bitLE(material_offset+0x06,streamFile); sample_rate = (uint16_t)read_16bitLE(material_offset+0x06,sf);
stream_size = read_32bitLE(material_offset+0x08,streamFile); stream_size = read_32bitLE(material_offset+0x08,sf);
num_samples = read_32bitLE(material_offset+0x0c,streamFile); num_samples = read_32bitLE(material_offset+0x0c,sf);
loop_start = read_32bitLE(material_offset+0x10,streamFile); loop_start = read_32bitLE(material_offset+0x10,sf);
loop_end = read_32bitLE(material_offset+0x14,streamFile); loop_end = read_32bitLE(material_offset+0x14,sf);
extradata_size = read_32bitLE(material_offset+0x18,streamFile); extradata_size = read_32bitLE(material_offset+0x18,sf);
/* rest: ? (empty or 0x3f80) */ /* rest: ? (empty or 0x3f80) */
loop_flag = (loop_end > loop_start); loop_flag = (loop_end > loop_start);
@ -269,14 +269,14 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
case 0x02: { /* MSADPCM [The Irregular at Magic High School Lost Zero (Android)] */ case 0x02: { /* MSADPCM [The Irregular at Magic High School Lost Zero (Android)] */
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->frame_size = read_16bitLE(extradata_offset + 0x02, streamFile); vgmstream->frame_size = read_16bitLE(extradata_offset + 0x02, sf);
/* adjusted samples; bigger or smaller than base samples, akb lib uses these fields instead /* adjusted samples; bigger or smaller than base samples, akb lib uses these fields instead
* (base samples may have more than possible and read over file size otherwise, very strange) * (base samples may have more than possible and read over file size otherwise, very strange)
* loop_end seems to exist even with loop disabled */ * loop_end seems to exist even with loop disabled */
vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile); vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, sf);
vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile); vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, sf);
vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile); vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, sf);
break; break;
} }
@ -289,7 +289,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
ovmi.total_subsongs = total_subsongs; ovmi.total_subsongs = total_subsongs;
ovmi.stream_size = stream_size; ovmi.stream_size = stream_size;
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); ogg_vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
if (ogg_vgmstream) { if (ogg_vgmstream) {
ogg_vgmstream->num_streams = vgmstream->num_streams; ogg_vgmstream->num_streams = vgmstream->num_streams;
ogg_vgmstream->stream_size = vgmstream->stream_size; ogg_vgmstream->stream_size = vgmstream->stream_size;
@ -310,7 +310,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
case 0x05: { /* Ogg Vorbis [The World Ends with You (iOS / latest update)] */ case 0x05: { /* Ogg Vorbis [The World Ends with You (iOS / latest update)] */
ffmpeg_codec_data *ffmpeg_data; ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size); ffmpeg_data = init_ffmpeg_offset(sf, start_offset,stream_size);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
@ -319,8 +319,8 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
/* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off) /* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off)
* Actual num_samples would be loop_end_sample+1, but more testing is needed */ * Actual num_samples would be loop_end_sample+1, but more testing is needed */
vgmstream->num_samples = read_32bitLE(material_offset+0x0c,streamFile);//num_samples; vgmstream->num_samples = read_32bitLE(material_offset+0x0c,sf);//num_samples;
vgmstream->loop_start_sample = read_32bitLE(material_offset+0x10,streamFile);//loop_start; vgmstream->loop_start_sample = read_32bitLE(material_offset+0x10,sf);//loop_start;
vgmstream->loop_end_sample = loop_end; vgmstream->loop_end_sample = loop_end;
break; break;
} }
@ -331,7 +331,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
} }
/* open the file for reading */ /* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -27,7 +27,7 @@ VGMSTREAM* init_vgmstream_ao(STREAMFILE *sf) {
/* AlphaOgg defines up to 16 loop points for some reason */ /* AlphaOgg defines up to 16 loop points for some reason */
start_offset = 0xc8; start_offset = 0xc8;
vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, start_offset, &ovmi); vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
} }
#else #else
goto fail; goto fail;

View File

@ -44,7 +44,7 @@ static void get_name_bar(BARSTREAMFILE *streamFile, char *name, size_t length) {
streamFile->real_file->get_name(streamFile->real_file, name, length); streamFile->real_file->get_name(streamFile->real_file, name, length);
} }
STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) { static STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) {
STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize); STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize);
if (!newfile) if (!newfile)
return NULL; return NULL;

View File

@ -2,11 +2,11 @@
#include "../layout/layout.h" #include "../layout/layout.h"
#define TXT_LINE_MAX 0x1000 #define TXT_LINE_MAX 0x1000
static int get_falcom_looping(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end); static int get_falcom_looping(STREAMFILE* sf, int* p_loop_start, int* p_loop_end);
/* .DEC/DE2 - from Falcom PC games (Xanadu Next, Zwei!!, VM Japan, Gurumin) */ /* .DEC/DE2 - from Falcom PC games (Xanadu Next, Zwei!!, VM Japan, Gurumin) */
VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_dec(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
off_t riff_off = 0x00; off_t riff_off = 0x00;
size_t pcm_size = 0; size_t pcm_size = 0;
@ -16,42 +16,42 @@ VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) {
/* checks /* checks
* .dec: main, * .dec: main,
* .de2: Gurumin (PC) */ * .de2: Gurumin (PC) */
if ( !check_extensions(streamFile,"dec,de2") ) if (!check_extensions(sf,"dec,de2"))
goto fail; goto fail;
/* Gurumin has extra data, maybe related to rhythm (~0x50000) */ /* Gurumin has extra data, maybe related to rhythm (~0x50000) */
if (check_extensions(streamFile,"de2")) { if (check_extensions(sf,"de2")) {
/* still not sure what this is for, but consistently 0xb */ /* still not sure what this is for, but consistently 0xb */
if (read_32bitLE(0x04,streamFile) != 0x0b) goto fail; if (read_32bitLE(0x04,sf) != 0x0b) goto fail;
/* legitimate! really! */ /* legitimate! really! */
riff_off = 0x10 + (read_32bitLE(0x0c,streamFile) ^ read_32bitLE(0x04,streamFile)); riff_off = 0x10 + (read_32bitLE(0x0c,sf) ^ read_32bitLE(0x04,sf));
} }
/* fake PCM RIFF header (the original WAV's) wrapping MS-ADPCM */ /* fake PCM RIFF header (the original WAV's) wrapping MS-ADPCM */
if (read_32bitBE(riff_off+0x00,streamFile) != 0x52494646 || /* "RIFF" */ if (!is_id32be(riff_off+0x00,sf, "RIFF") ||
read_32bitBE(riff_off+0x08,streamFile) != 0x57415645) /* "WAVE" */ !is_id32be(riff_off+0x08,sf, "WAVE"))
goto fail; goto fail;
if (read_32bitBE(riff_off+0x0c,streamFile) == 0x50414420) { /* "PAD " (Zwei!!), blank with wrong chunk size */ if (is_id32be(riff_off+0x0c,sf, "PAD ")) { /* blank with wrong chunk size [Zwei!! ())PC)]*/
sample_rate = 44100; sample_rate = 44100;
channel_count = 2; channel_count = 2;
pcm_size = read_32bitLE(riff_off+0x04,streamFile) - 0x24; pcm_size = read_32bitLE(riff_off+0x04,sf) - 0x24;
/* somehow there is garbage at the beginning of some tracks */ /* somehow there is garbage at the beginning of some tracks */
} }
else if (read_32bitBE(riff_off+0x0c,streamFile) == 0x666D7420) { /* "fmt " (rest) */ else if (is_id32be(riff_off+0x0c,sf, "fmt ")) {
//if (read_32bitLE(riff_off+0x10,streamFile) != 0x12) goto fail; /* 0x10 in some */ //if (read_32bitLE(riff_off+0x10,sf) != 0x12) goto fail; /* 0x10 in some */
if (read_16bitLE(riff_off+0x14,streamFile) != 0x01) goto fail; /* PCM (actually MS-ADPCM) */ if (read_16bitLE(riff_off+0x14,sf) != 0x01) goto fail; /* PCM (actually MS-ADPCM) */
if (read_16bitLE(riff_off+0x20,streamFile) != 4 || if (read_16bitLE(riff_off+0x20,sf) != 4 ||
read_16bitLE(riff_off+0x22,streamFile) != 16) goto fail; /* 16-bit */ read_16bitLE(riff_off+0x22,sf) != 16) goto fail; /* 16-bit */
channel_count = read_16bitLE(riff_off+0x16,streamFile); channel_count = read_16bitLE(riff_off+0x16,sf);
sample_rate = read_32bitLE(riff_off+0x18,streamFile); sample_rate = read_32bitLE(riff_off+0x18,sf);
if (read_32bitBE(riff_off+0x24,streamFile) == 0x64617461) { /* "data" size except in some Zwei!! */ if (read_32bitBE(riff_off+0x24,sf) == 0x64617461) { /* "data" size except in some Zwei!! */
pcm_size = read_32bitLE(riff_off+0x28,streamFile); pcm_size = read_32bitLE(riff_off+0x28,sf);
} else { } else {
pcm_size = read_32bitLE(riff_off+0x04,streamFile) - 0x24; pcm_size = read_32bitLE(riff_off+0x04,sf) - 0x24;
} }
} }
else { else {
@ -62,7 +62,7 @@ VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) {
goto fail; goto fail;
start_offset = riff_off + 0x2c; start_offset = riff_off + 0x2c;
loop_flag = get_falcom_looping(streamFile, &loop_start, &loop_end); loop_flag = get_falcom_looping(sf, &loop_start, &loop_end);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
@ -79,7 +79,7 @@ VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) {
vgmstream->frame_size = 0x800; vgmstream->frame_size = 0x800;
vgmstream->layout_type = layout_blocked_dec; vgmstream->layout_type = layout_blocked_dec;
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -91,7 +91,7 @@ fail:
/* Falcom loves loop points in external text files, here we parse them */ /* Falcom loves loop points in external text files, here we parse them */
typedef enum { XANADU_NEXT, ZWEI, DINOSAUR_RESURRECTION, GURUMIN } falcom_loop_t; typedef enum { XANADU_NEXT, ZWEI, DINOSAUR_RESURRECTION, GURUMIN } falcom_loop_t;
static int get_falcom_looping(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end) { static int get_falcom_looping(STREAMFILE *sf, int *out_loop_start, int *out_loop_end) {
STREAMFILE *streamText; STREAMFILE *streamText;
off_t txt_offset = 0x00; off_t txt_offset = 0x00;
falcom_loop_t type; falcom_loop_t type;
@ -100,23 +100,23 @@ static int get_falcom_looping(STREAMFILE *streamFile, int *out_loop_start, int *
/* try one of the many loop files */ /* try one of the many loop files */
if ((streamText = open_streamfile_by_filename(streamFile,"bgm.tbl")) != NULL) { if ((streamText = open_streamfile_by_filename(sf,"bgm.tbl")) != NULL) {
type = XANADU_NEXT; type = XANADU_NEXT;
} }
else if ((streamText = open_streamfile_by_filename(streamFile,"bgm.scr")) != NULL) { else if ((streamText = open_streamfile_by_filename(sf,"bgm.scr")) != NULL) {
type = ZWEI; type = ZWEI;
} }
else if ((streamText = open_streamfile_by_filename(streamFile,"loop.txt")) != NULL) { /* actual name in Shift JIS, 0x838B815B8376 */ else if ((streamText = open_streamfile_by_filename(sf,"loop.txt")) != NULL) { /* actual name in Shift JIS, 0x838B815B8376 */
type = DINOSAUR_RESURRECTION; type = DINOSAUR_RESURRECTION;
} }
else if ((streamText = open_streamfile_by_filename(streamFile,"map.itm")) != NULL) { else if ((streamText = open_streamfile_by_filename(sf,"map.itm")) != NULL) {
type = GURUMIN; type = GURUMIN;
} }
else { else {
goto end; goto end;
} }
get_streamfile_filename(streamFile,filename,TXT_LINE_MAX); get_streamfile_filename(sf,filename,TXT_LINE_MAX);
/* read line by line */ /* read line by line */
while (txt_offset < get_streamfile_size(streamText)) { while (txt_offset < get_streamfile_size(streamText)) {
@ -166,6 +166,9 @@ static int get_falcom_looping(STREAMFILE *streamFile, int *out_loop_start, int *
goto end; goto end;
} }
break; break;
default:
break;
} }
} }

View File

@ -508,7 +508,7 @@ fail:
} }
/* open map/mpf+mus pairs that aren't exact pairs, since EA's games can load any combo */ /* open map/mpf+mus pairs that aren't exact pairs, since EA's games can load any combo */
static STREAMFILE *open_mapfile_pair(STREAMFILE* sf, int track, int num_tracks) { static STREAMFILE *open_mapfile_pair(STREAMFILE* sf, int track /*, int num_tracks*/) {
static const char *const mapfile_pairs[][2] = { static const char *const mapfile_pairs[][2] = {
/* standard cases, replace map part with mus part (from the end to preserve prefixes) */ /* standard cases, replace map part with mus part (from the end to preserve prefixes) */
{"game.mpf", "Game_Stream.mus"}, /* Skate 1/2/3 */ {"game.mpf", "Game_Stream.mus"}, /* Skate 1/2/3 */
@ -685,7 +685,7 @@ VGMSTREAM* init_vgmstream_ea_mpf_mus_eaac(STREAMFILE* sf) {
} }
/* open MUS file that matches this track */ /* open MUS file that matches this track */
musFile = open_mapfile_pair(sf, i, num_tracks); musFile = open_mapfile_pair(sf, i);//, num_tracks
if (!musFile) if (!musFile)
goto fail; goto fail;
@ -1136,6 +1136,8 @@ static VGMSTREAM* init_vgmstream_eaaudiocore_header(STREAMFILE* sf_head, STREAMF
eaac.loop_offset = read_32bitBE(header_offset + 0x10, sf_head); eaac.loop_offset = read_32bitBE(header_offset + 0x10, sf_head);
} }
break; break;
default:
goto fail;
} }
/* get data offsets */ /* get data offsets */
@ -1151,6 +1153,8 @@ static VGMSTREAM* init_vgmstream_eaaudiocore_header(STREAMFILE* sf_head, STREAMF
eaac.prefetch_offset = header_offset + header_size; eaac.prefetch_offset = header_offset + header_size;
eaac.stream_offset = start_offset; eaac.stream_offset = start_offset;
break; break;
default:
goto fail;
} }
} else { } else {
eaac.stream_offset = header_offset - 0x04 + header_block_size; eaac.stream_offset = header_offset - 0x04 + header_block_size;
@ -1340,7 +1344,7 @@ static VGMSTREAM* init_vgmstream_eaaudiocore_header(STREAMFILE* sf_head, STREAMF
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case EAAC_CODEC_EAMP3: { /* "EM30": EA-MP3 [Need for Speed 2015 (PS4)] */ case EAAC_CODEC_EAMP3: { /* "EM30": EA-MP3 [Need for Speed 2015 (PS4), FIFA 2021 (PC)] */
mpeg_custom_config cfg = {0}; mpeg_custom_config cfg = {0};
temp_sf = setup_eaac_audio_streamfile(sf, eaac.version, eaac.codec, eaac.streamed,0,0, 0x00); temp_sf = setup_eaac_audio_streamfile(sf, eaac.version, eaac.codec, eaac.streamed,0,0, 0x00);
@ -1551,6 +1555,8 @@ static STREAMFILE *setup_eaac_streamfile(eaac_header *ea, STREAMFILE* sf_head, S
sf_segments[0] = NULL; sf_segments[0] = NULL;
sf_segments[1] = NULL; sf_segments[1] = NULL;
break; break;
default:
goto fail;
} }
} else { } else {
data_size = calculate_eaac_size(sf_head, ea, ea->num_samples, ea->stream_offset, 0); data_size = calculate_eaac_size(sf_head, ea, ea->num_samples, ea->stream_offset, 0);
@ -1689,8 +1695,8 @@ static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *sf_data, eaac_
data->layers[i]->loop_start_sample = eaac->loop_start; data->layers[i]->loop_start_sample = eaac->loop_start;
data->layers[i]->loop_end_sample = eaac->loop_end; data->layers[i]->loop_end_sample = eaac->loop_end;
#ifdef VGM_USE_FFMPEG
switch(eaac->codec) { switch(eaac->codec) {
#ifdef VGM_USE_FFMPEG
/* EA-XMA uses completely separate 1/2ch streams, unlike standard XMA that interleaves 1/2ch /* EA-XMA uses completely separate 1/2ch streams, unlike standard XMA that interleaves 1/2ch
* streams with a skip counter to reinterleave (so EA-XMA streams don't have skips set) */ * streams with a skip counter to reinterleave (so EA-XMA streams don't have skips set) */
case EAAC_CODEC_EAXMA: { case EAAC_CODEC_EAXMA: {
@ -1743,11 +1749,10 @@ static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *sf_data, eaac_
data->layers[i]->layout_type = layout_none; data->layers[i]->layout_type = layout_none;
break; break;
} }
}
#else
goto fail;
#endif #endif
default:
goto fail;
}
if (!vgmstream_open_stream(data->layers[i], temp_sf, 0x00)) { if (!vgmstream_open_stream(data->layers[i], temp_sf, 0x00)) {
goto fail; goto fail;

View File

@ -637,7 +637,7 @@ fail:
/* open map/mpf+mus pairs that aren't exact pairs, since EA's games can load any combo */ /* open map/mpf+mus pairs that aren't exact pairs, since EA's games can load any combo */
static STREAMFILE* open_mapfile_pair(STREAMFILE* sf, int track, int num_tracks) { static STREAMFILE* open_mapfile_pair(STREAMFILE* sf, int track /*, int num_tracks*/) {
static const char *const mapfile_pairs[][2] = { static const char *const mapfile_pairs[][2] = {
/* standard cases, replace map part with mus part (from the end to preserve prefixes) */ /* standard cases, replace map part with mus part (from the end to preserve prefixes) */
{"MUS_CTRL.MPF", "MUS_STR.MUS"}, /* GoldenEye - Rogue Agent (PS2) */ {"MUS_CTRL.MPF", "MUS_STR.MUS"}, /* GoldenEye - Rogue Agent (PS2) */
@ -760,7 +760,7 @@ VGMSTREAM* init_vgmstream_ea_map_mus(STREAMFILE* sf) {
version = read_8bit(0x04, sf); version = read_8bit(0x04, sf);
if (version > 1) goto fail; if (version > 1) goto fail;
sf_mus = open_mapfile_pair(sf, 0, 1); sf_mus = open_mapfile_pair(sf, 0); //, 1
if (!sf_mus) goto fail; if (!sf_mus) goto fail;
/* /*
@ -994,7 +994,7 @@ VGMSTREAM* init_vgmstream_ea_mpf_mus(STREAMFILE* sf) {
goto fail; goto fail;
/* open MUS file that matches this track */ /* open MUS file that matches this track */
sf_mus = open_mapfile_pair(sf, i, num_tracks); sf_mus = open_mapfile_pair(sf, i); //, num_tracks
if (!sf_mus) if (!sf_mus)
goto fail; goto fail;

View File

@ -23,7 +23,7 @@ static int find_meta_loops(ffmpeg_codec_data* data, int32_t* p_loop_start, int32
VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
ffmpeg_codec_data* data = NULL; ffmpeg_codec_data* data = NULL;
int loop_flag = 0; int loop_flag = 0, channels, sample_rate;
int32_t loop_start = 0, loop_end = 0, num_samples = 0, encoder_delay = 0; int32_t loop_start = 0, loop_end = 0, num_samples = 0, encoder_delay = 0;
int total_subsongs, target_subsong = sf->stream_index; int total_subsongs, target_subsong = sf->stream_index;
@ -35,9 +35,12 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
if (get_streamfile_size(sf) <= 0x1000) if (get_streamfile_size(sf) <= 0x1000)
goto fail; goto fail;
// many PSP rips have poorly demuxed videos with a failty RIFF, allow for now
#if 0
/* reject some formats handled elsewhere (better fail and check there than let buggy FFmpeg take over) */ /* reject some formats handled elsewhere (better fail and check there than let buggy FFmpeg take over) */
if (check_extensions(sf, "at3")) if (check_extensions(sf, "at3"))
goto fail; goto fail;
#endif
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
@ -45,18 +48,18 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
data = init_ffmpeg_header_offset_subsong(sf, NULL, 0, 0, get_streamfile_size(sf), target_subsong); data = init_ffmpeg_header_offset_subsong(sf, NULL, 0, 0, get_streamfile_size(sf), target_subsong);
if (!data) return NULL; if (!data) return NULL;
total_subsongs = data->streamCount; /* uncommon, ex. wmv [Lost Odyssey (X360)] */ total_subsongs = ffmpeg_get_subsong_count(data); /* uncommon, ex. wmv [Lost Odyssey (X360)] */
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* try to get .pos data */ /* try to get .pos data */
{ {
uint8_t posbuf[4+4+4]; uint8_t posbuf[0x04*3];
if (read_pos_file(posbuf, 4+4+4, sf)) { if (read_pos_file(posbuf, sizeof(posbuf), sf)) {
loop_start = get_s32le(posbuf+0); loop_start = get_s32le(posbuf+0x00);
loop_end = get_s32le(posbuf+4); loop_end = get_s32le(posbuf+0x04);
loop_flag = 1; /* incorrect looping will be validated outside */ loop_flag = 1; /* incorrect looping will be validated outside */
/* FFmpeg can't always determine totalSamples correctly so optionally load it (can be 0/NULL) /* FFmpeg can't always determine samples correctly so optionally load it (can be 0/NULL)
* won't crash and will output silence if no loop points and bigger than actual stream's samples */ * won't crash and will output silence if no loop points and bigger than actual stream's samples */
num_samples = get_s32le(posbuf+8); num_samples = get_s32le(posbuf+8);
} }
@ -82,6 +85,9 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
* .mus: Marc Ecko's Getting Up (PC) */ * .mus: Marc Ecko's Getting Up (PC) */
if (!num_samples && check_extensions(sf, "mp3,lmp3,mus")) { if (!num_samples && check_extensions(sf, "mp3,lmp3,mus")) {
num_samples = mpeg_get_samples(sf, 0x00, get_streamfile_size(sf)); num_samples = mpeg_get_samples(sf, 0x00, get_streamfile_size(sf));
/* this seems correct thankfully */
//ffmpeg_set_skip_samples(data, encoder_delay);
} }
#endif #endif
@ -100,18 +106,22 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
/* default but often inaccurate when calculated using bitrate (wrong for VBR) */ /* default but often inaccurate when calculated using bitrate (wrong for VBR) */
if (!num_samples) { if (!num_samples) {
num_samples = data->totalSamples; /* may be 0 if FFmpeg can't precalculate it */ num_samples = ffmpeg_get_samples(data); /* may be 0 if FFmpeg can't precalculate it */
} }
channels = ffmpeg_get_channels(data);
sample_rate = ffmpeg_get_sample_rate(data);
/* build VGMSTREAM */ /* build VGMSTREAM */
vgmstream = allocate_vgmstream(data->channels, loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = data->sampleRate;
vgmstream->meta_type = meta_FFMPEG; vgmstream->meta_type = meta_FFMPEG;
vgmstream->coding_type = coding_FFmpeg; vgmstream->sample_rate = sample_rate;
vgmstream->codec_data = data; vgmstream->codec_data = data;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
@ -211,7 +221,7 @@ static int find_meta_loops(ffmpeg_codec_data* data, int32_t* p_loop_start, int32
if (loop_end <= 0) { if (loop_end <= 0) {
// Looks a calculation was not possible, or tag value is wrongly set. Use the end of track as end value // Looks a calculation was not possible, or tag value is wrongly set. Use the end of track as end value
loop_end = data->totalSamples; loop_end = ffmpeg_get_samples(data);
} }
if (loop_start <= 0) { if (loop_start <= 0) {

View File

@ -1,5 +1,5 @@
#ifndef _FSB_ENCRYPTED_STREAMFILE_H_ #ifndef _FSB_ENCRYPTED_STREAMFILE_H_
#define _FSB_ENCRYPTED_H_ #define _FSB_ENCRYPTED_STREAMFILE_H_
#define FSB_KEY_MAX 0x10000 //0x168 #define FSB_KEY_MAX 0x10000 //0x168
@ -71,4 +71,4 @@ static STREAMFILE* setup_fsb_streamfile(STREAMFILE* sf, const uint8_t* key, size
return new_sf; return new_sf;
} }
#endif /* _FSB5_STREAMFILE_H_ */ #endif /* _FSB_ENCRYPTED_STREAMFILE_H_ */

View File

@ -307,7 +307,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
//if (vgmstream->num_samples == 0) //if (vgmstream->num_samples == 0)
// vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */ // vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); /* sometimes works */
} }
else { else {
/* fake header FFmpeg */ /* fake header FFmpeg */

View File

@ -2,16 +2,17 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* .gin - EA engine sounds [Need for Speed: Most Wanted (multi)] */ /* .gin - EA engine sounds [Need for Speed: Most Wanted (multi)] */
VGMSTREAM * init_vgmstream_gin(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_gin(STREAMFILE *sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM *vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count, sample_rate, num_samples; int loop_flag, channel_count, sample_rate, num_samples;
if (!check_extensions(streamFile, "gin")) if (!check_extensions(sf, "gin"))
goto fail; goto fail;
/* checks */ /* checks */
if (read_32bitBE(0x00, streamFile) != 0x476E7375) /* "Gnsu" */ if (!is_id32be(0x00, sf, "Gnsu") && /* original */
!is_id32be(0x00, sf, "Octn")) /* later (2013+) games, looks same as "Gnsu" */
goto fail; goto fail;
/* contains mapped values for engine RPM sounds but we'll just play the whole thing */ /* contains mapped values for engine RPM sounds but we'll just play the whole thing */
@ -21,11 +22,11 @@ VGMSTREAM * init_vgmstream_gin(STREAMFILE *streamFile) {
/* 0x14: RPM ??? table size */ /* 0x14: RPM ??? table size */
/* always LE even on X360/PS3 */ /* always LE even on X360/PS3 */
num_samples = read_32bitLE(0x18, streamFile); num_samples = read_u32le(0x18, sf);
sample_rate = read_32bitLE(0x1c, streamFile); sample_rate = read_u32le(0x1c, sf);
start_offset = 0x20 + start_offset = 0x20 +
(read_32bitLE(0x10, streamFile) + 1) * 0x04 + (read_u32le(0x10, sf) + 1) * 0x04 +
(read_32bitLE(0x14, streamFile) + 1) * 0x04; (read_u32le(0x14, sf) + 1) * 0x04;
channel_count = 1; channel_count = 1;
loop_flag = 0; loop_flag = 0;
@ -44,7 +45,7 @@ VGMSTREAM * init_vgmstream_gin(STREAMFILE *streamFile) {
/* calculate size for TMX */ /* calculate size for TMX */
vgmstream->stream_size = (align_size_to_block(num_samples, 32) / 32) * 0x13; vgmstream->stream_size = (align_size_to_block(num_samples, 32) / 32) * 0x13;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -1,6 +1,7 @@
#include "meta.h" #include "meta.h"
#include "hca_keys.h" #include "hca_keys.h"
#include "../coding/coding.h" #include "../coding/coding.h"
#include "clHCA.h"
//#define HCA_BRUTEFORCE //#define HCA_BRUTEFORCE
#ifdef HCA_BRUTEFORCE #ifdef HCA_BRUTEFORCE
@ -15,7 +16,7 @@ VGMSTREAM* init_vgmstream_hca(STREAMFILE* sf) {
} }
VGMSTREAM* init_vgmstream_hca_subkey(STREAMFILE* sf, uint16_t subkey) { VGMSTREAM* init_vgmstream_hca_subkey(STREAMFILE* sf, uint16_t subkey) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
hca_codec_data* hca_data = NULL; hca_codec_data* hca_data = NULL;
clHCA_stInfo* hca_info; clHCA_stInfo* hca_info;
@ -152,19 +153,23 @@ static inline void test_key(hca_codec_data* hca_data, uint64_t key, uint16_t sub
static void find_hca_key(hca_codec_data* hca_data, uint64_t* p_keycode, uint16_t subkey) { static void find_hca_key(hca_codec_data* hca_data, uint64_t* p_keycode, uint16_t subkey) {
const size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info); const size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info);
int best_score = -1; int best_score = -1;
int i,j; int i;
*p_keycode = 0xCC55463930DBE1AB; /* defaults to PSO2 key, most common */ *p_keycode = 0xCC55463930DBE1AB; /* defaults to PSO2 key, most common */
for (i = 0; i < keys_length; i++) { for (i = 0; i < keys_length; i++) {
uint64_t key = hcakey_list[i].key; uint64_t key = hcakey_list[i].key;
size_t subkeys_size = hcakey_list[i].subkeys_size;
const uint16_t *subkeys = hcakey_list[i].subkeys;
test_key(hca_data, key, subkey, &best_score, p_keycode); test_key(hca_data, key, subkey, &best_score, p_keycode);
if (best_score == 1) if (best_score == 1)
goto done; goto done;
#if 0
{
int j;
size_t subkeys_size = hcakey_list[i].subkeys_size;
const uint16_t *subkeys = hcakey_list[i].subkeys;
if (subkeys_size > 0 && subkey == 0) { if (subkeys_size > 0 && subkey == 0) {
for (j = 0; j < subkeys_size; j++) { for (j = 0; j < subkeys_size; j++) {
test_key(hca_data, key, subkeys[j], &best_score, p_keycode); test_key(hca_data, key, subkeys[j], &best_score, p_keycode);
@ -173,6 +178,8 @@ static void find_hca_key(hca_codec_data* hca_data, uint64_t* p_keycode, uint16_t
} }
} }
} }
#endif
}
done: done:
VGM_ASSERT(best_score > 1, "HCA: best key=%08x%08x (score=%i)\n", VGM_ASSERT(best_score > 1, "HCA: best key=%08x%08x (score=%i)\n",

View File

@ -5,8 +5,10 @@
typedef struct { typedef struct {
uint64_t key; /* hca key or seed ('user') key */ uint64_t key; /* hca key or seed ('user') key */
const uint16_t *subkeys; /* scramble subkey table for seed key */ #if 0
const uint16_t* subkeys; /* scramble subkey table for seed key */
size_t subkeys_size; /* size of the derivation subkey table */ size_t subkeys_size; /* size of the derivation subkey table */
#endif
} hcakey_info; } hcakey_info;
@ -410,6 +412,9 @@ static const hcakey_info hcakey_list[] = {
/* Dragon Quest Tact (Android) */ /* Dragon Quest Tact (Android) */
{3234477171400153310}, // 2CE32BD9B36A98DE {3234477171400153310}, // 2CE32BD9B36A98DE
/* Alchemy Stars (Android) */
{1564789515523}, // 0000016C54B92503
/* D4DJ Groovy Mix (Android) [base files] */ /* D4DJ Groovy Mix (Android) [base files] */
{393410674916959300}, // 0575ACECA945A444 {393410674916959300}, // 0575ACECA945A444
/* D4DJ Groovy Mix (Android) [music_* files, per-song later mixed with subkey] */ /* D4DJ Groovy Mix (Android) [music_* files, per-song later mixed with subkey] */
@ -711,6 +716,9 @@ static const hcakey_info hcakey_list[] = {
{0x78bec41dd27d8788}, //music_5050074 {0x78bec41dd27d8788}, //music_5050074
{0x52c250eade92393b}, //music_9010001 {0x52c250eade92393b}, //music_9010001
{0xfea0d6adff136868}, //music_9050001 {0xfea0d6adff136868}, //music_9050001
// Mini 4WD Hyper Dash Grand Prix (Android)
{7957824642808300098}, // 6E6FDF59AB704242
}; };
#endif/*_HCA_KEYS_H_*/ #endif/*_HCA_KEYS_H_*/

View File

@ -3,49 +3,49 @@
/* HIS - Her Interactive games [Nancy Drew series (PC)] */ /* HIS - Her Interactive games [Nancy Drew series (PC)] */
VGMSTREAM * init_vgmstream_his(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_his(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
int channel_count, loop_flag = 0, bps, sample_rate, num_samples, version; int channel_count, loop_flag = 0, bps, sample_rate, num_samples, version;
off_t start_offset; off_t start_offset;
/* checks */ /* checks */
if (!check_extensions(streamFile, "his")) if (!check_extensions(sf, "his"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) == 0x48657220) { /* "Her Interactive Sound\x1a" */ if (read_32bitBE(0x00,sf) == 0x48657220) { /* "Her Interactive Sound\x1a" */
/* Nancy Drew: Secrets Can Kill (PC) */ /* Nancy Drew: Secrets Can Kill (PC) */
version = 0; version = 0;
channel_count = read_16bitLE(0x16,streamFile); channel_count = read_16bitLE(0x16,sf);
sample_rate = read_32bitLE(0x18,streamFile); sample_rate = read_32bitLE(0x18,sf);
/* 0x1c: bitrate */ /* 0x1c: bitrate */
/* 0x20: block size */ /* 0x20: block size */
bps = read_16bitLE(0x22,streamFile); bps = read_16bitLE(0x22,sf);
if (read_32bitBE(0x24,streamFile) != 0x64617461) /* "data" */ if (read_32bitBE(0x24,sf) != 0x64617461) /* "data" */
goto fail; goto fail;
num_samples = pcm_bytes_to_samples(read_32bitLE(0x28,streamFile), channel_count, bps); num_samples = pcm_bytes_to_samples(read_32bitLE(0x28,sf), channel_count, bps);
start_offset = 0x2c; start_offset = 0x2c;
} }
else if (read_32bitBE(0x00,streamFile) == 0x48495300) { /* HIS\0 */ else if (read_32bitBE(0x00,sf) == 0x48495300) { /* HIS\0 */
/* most(?) others */ /* most(?) others */
version = read_32bitLE(0x04,streamFile); version = read_32bitLE(0x04,sf);
/* 0x08: codec */ /* 0x08: codec */
channel_count = read_16bitLE(0x0a,streamFile); channel_count = read_16bitLE(0x0a,sf);
sample_rate = read_32bitLE(0x0c,streamFile); sample_rate = read_32bitLE(0x0c,sf);
/* 0x10: bitrate */ /* 0x10: bitrate */
/* 0x14: block size */ /* 0x14: block size */
bps = read_16bitLE(0x16,streamFile); bps = read_16bitLE(0x16,sf);
num_samples = pcm_bytes_to_samples(read_32bitLE(0x18,streamFile), channel_count, bps); /* true even for Ogg */ num_samples = pcm_bytes_to_samples(read_32bitLE(0x18,sf), channel_count, bps); /* true even for Ogg */
/* later games use "OggS" */ /* later games use "OggS" */
if (version == 1) if (version == 1)
start_offset = 0x1c; /* Nancy Drew: The Final Scene (PC) */ start_offset = 0x1c; /* Nancy Drew: The Final Scene (PC) */
else if (version == 2 && read_32bitBE(0x1e,streamFile) == 0x4F676753) else if (version == 2 && read_32bitBE(0x1e,sf) == 0x4F676753)
start_offset = 0x1e; /* Nancy Drew: The Haunted Carousel (PC) */ start_offset = 0x1e; /* Nancy Drew: The Haunted Carousel (PC) */
else if (version == 2 && read_32bitBE(0x20,streamFile) == 0x4F676753) else if (version == 2 && read_32bitBE(0x20,sf) == 0x4F676753)
start_offset = 0x20; /* Nancy Drew: The Silent Spy (PC) */ start_offset = 0x20; /* Nancy Drew: The Silent Spy (PC) */
else else
goto fail; goto fail;
@ -60,7 +60,7 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *streamFile) {
ogg_vorbis_meta_info_t ovmi = {0}; ogg_vorbis_meta_info_t ovmi = {0};
ovmi.meta_type = meta_HIS; ovmi.meta_type = meta_HIS;
return init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); return init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
#else #else
goto fail; goto fail;
#endif #endif
@ -89,7 +89,7 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *streamFile) {
goto fail; goto fail;
} }
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -80,7 +80,7 @@ VGMSTREAM* init_vgmstream_ikm_pc(STREAMFILE* sf) {
ovmi.loop_flag = ovmi.loop_end > 0; ovmi.loop_flag = ovmi.loop_end > 0;
ovmi.stream_size = read_s32le(0x24, sf); ovmi.stream_size = read_s32le(0x24, sf);
vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, start_offset, &ovmi); vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
} }
#else #else
goto fail; goto fail;

View File

@ -137,9 +137,11 @@ typedef struct {
off_t scd_xor_length; off_t scd_xor_length;
uint32_t xor_value; uint32_t xor_value;
//ov_callbacks *callbacks
} ogg_vorbis_meta_info_t; } ogg_vorbis_meta_info_t;
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callbacks *callbacks, off_t start, const ogg_vorbis_meta_info_t *ovmi); VGMSTREAM* init_vgmstream_ogg_vorbis_config(STREAMFILE *sf, off_t start, const ogg_vorbis_meta_info_t* ovmi);
#endif #endif
VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile);
@ -951,4 +953,6 @@ VGMSTREAM* init_vgmstream_ogv_3rdeye(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf); VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_piff_tpcm(STREAMFILE* sf);
#endif /*_META_H*/ #endif /*_META_H*/

View File

@ -10,12 +10,12 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */ /* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */
VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_mogg(STREAMFILE *sf) {
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
off_t start_offset; off_t start_offset;
/* checks */ /* checks */
if (!check_extensions(streamFile, "mogg")) if (!check_extensions(sf, "mogg"))
goto fail; goto fail;
{ {
@ -24,8 +24,8 @@ VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) {
ovmi.meta_type = meta_MOGG; ovmi.meta_type = meta_MOGG;
start_offset = read_32bitLE(0x04, streamFile); start_offset = read_32bitLE(0x04, sf);
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); result = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
if (result != NULL) { if (result != NULL) {
return result; return result;

View File

@ -163,11 +163,14 @@ fail:
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
typedef struct { typedef struct {
int channels;
int sample_rate;
int32_t num_samples; int32_t num_samples;
int loop_flag; int loop_flag;
int32_t loop_start; int32_t loop_start;
int32_t loop_end; int32_t loop_end;
int32_t encoder_delay; int32_t encoder_delay;
int subsongs;
} mp4_header; } mp4_header;
static void parse_mp4(STREAMFILE* sf, mp4_header* mp4); static void parse_mp4(STREAMFILE* sf, mp4_header* mp4);
@ -199,36 +202,45 @@ VGMSTREAM* init_vgmstream_mp4_aac_ffmpeg(STREAMFILE* sf) {
parse_mp4(sf, &mp4); parse_mp4(sf, &mp4);
/* most values aren't read directly and use FFmpeg b/c MP4 makes things hard */
if (!mp4.num_samples)
mp4.num_samples = ffmpeg_get_samples(ffmpeg_data); /* does this take into account encoder delay? see FFV */
if (!mp4.channels)
mp4.channels = ffmpeg_get_channels(ffmpeg_data);
if (!mp4.sample_rate)
mp4.sample_rate = ffmpeg_get_sample_rate(ffmpeg_data);
if (!mp4.subsongs)
mp4.subsongs = ffmpeg_get_subsong_count(ffmpeg_data); /* may contain N tracks */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(ffmpeg_data->channels, mp4.loop_flag); vgmstream = allocate_vgmstream(mp4.channels, mp4.loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_MP4; vgmstream->meta_type = meta_MP4;
vgmstream->sample_rate = ffmpeg_data->sampleRate; vgmstream->sample_rate = mp4.sample_rate;
vgmstream->num_samples = mp4.num_samples; vgmstream->num_samples = mp4.num_samples;
if (vgmstream->num_samples == 0)
vgmstream->num_samples = ffmpeg_data->totalSamples;
vgmstream->loop_start_sample = mp4.loop_start; vgmstream->loop_start_sample = mp4.loop_start;
vgmstream->loop_end_sample = mp4.loop_end; vgmstream->loop_end_sample = mp4.loop_end;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_streams = ffmpeg_data->streamCount; /* may contain N tracks */ vgmstream->num_streams = mp4.subsongs;
vgmstream->channel_layout = ffmpeg_get_channel_layout(vgmstream->codec_data); vgmstream->channel_layout = ffmpeg_get_channel_layout(ffmpeg_data);
if (mp4.encoder_delay)
/* needed for CRI MP4, otherwise FFmpeg usually reads standard delay */
ffmpeg_set_skip_samples(vgmstream->codec_data, mp4.encoder_delay); ffmpeg_set_skip_samples(vgmstream->codec_data, mp4.encoder_delay);
return vgmstream; return vgmstream;
fail: fail:
if (ffmpeg_data) {
free_ffmpeg(ffmpeg_data); free_ffmpeg(ffmpeg_data);
if (vgmstream) vgmstream->codec_data = NULL; if (vgmstream) {
vgmstream->codec_data = NULL;
close_vgmstream(vgmstream);
} }
if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -108,7 +108,7 @@ VGMSTREAM* init_vgmstream_msf(STREAMFILE* sf) {
encoder_delay = 1024 + 69*2; encoder_delay = 1024 + 69*2;
block_align = (codec==4 ? 0x60 : (codec==5 ? 0x98 : 0xC0)) * vgmstream->channels; block_align = (codec==4 ? 0x60 : (codec==5 ? 0x98 : 0xC0)) * vgmstream->channels;
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay; vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay;
if (vgmstream->sample_rate == 0xFFFFFFFF) /* some MSFv1 (Digi World SP) */ if (vgmstream->sample_rate == -1) /* some MSFv1 (Digi World SP) */
vgmstream->sample_rate = 44100; /* voice tracks seems to use 44khz, not sure about other tracks */ vgmstream->sample_rate = 44100; /* voice tracks seems to use 44khz, not sure about other tracks */
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
@ -144,20 +144,16 @@ VGMSTREAM* init_vgmstream_msf(STREAMFILE* sf) {
} }
#elif defined(VGM_USE_FFMPEG) #elif defined(VGM_USE_FFMPEG)
case 0x07: { /* MPEG (LAME MP3) [Dengeki Bunko Fighting Climax (PS3), Asura's Wrath (PS3)-vbr] */ case 0x07: { /* MPEG (LAME MP3) [Dengeki Bunko Fighting Climax (PS3), Asura's Wrath (PS3)-vbr] */
ffmpeg_codec_data *ffmpeg_data = NULL; int is_vbr = (flags & 0x20); /* must calc samples/loop offsets manually */
ffmpeg_data = init_ffmpeg_offset(sf, start_offset, sf->get_size(sf)); vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, 0);;
if (!ffmpeg_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
//todo use same calcs as above vgmstream->num_samples = mpeg_get_samples_clean(sf, start_offset, data_size, &loop_start, &loop_end, is_vbr);
vgmstream->num_samples = (int64_t)data_size * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; vgmstream->loop_start_sample = loop_start;
if (loop_flag) { vgmstream->loop_end_sample = loop_end;
vgmstream->loop_start_sample = (int64_t)loop_start * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate;
vgmstream->loop_end_sample = (int64_t)loop_end * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate;
}
break; break;
} }
#endif #endif

View File

@ -2,39 +2,39 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* .MUS - Vicious Cycle games [Dinotopia: The Sunstone Odyssey (GC/Xbox), Robotech: Battlecry (PS2/Xbox)] */ /* .MUS - Vicious Cycle games [Dinotopia: The Sunstone Odyssey (GC/Xbox), Robotech: Battlecry (PS2/Xbox)] */
VGMSTREAM * init_vgmstream_mus_vc(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_mus_vc(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count, sample_rate; int loop_flag, channels, sample_rate;
int big_endian, type; int big_endian, type;
int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL; int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL;
/* checks */ /* checks */
if (!check_extensions(streamFile, "mus")) if (!check_extensions(sf, "mus"))
goto fail; goto fail;
if (read_32bitBE(0x08,streamFile) != 0xBBBBBBBB && if (read_u32be(0x08,sf) != 0xBBBBBBBB &&
read_32bitBE(0x14,streamFile) != 0xBBBBBBBB && read_u32be(0x14,sf) != 0xBBBBBBBB &&
read_32bitBE(0x2c,streamFile) != 0xBEBEBEBE) read_u32be(0x2c,sf) != 0xBEBEBEBE)
goto fail; goto fail;
big_endian = (read_32bitBE(0x00,streamFile) == 0xFBBFFBBF); big_endian = (read_u32be(0x00,sf) == 0xFBBFFBBF);
read_32bit = big_endian ? read_32bitBE : read_32bitLE; read_32bit = big_endian ? read_32bitBE : read_32bitLE;
type = read_32bit(0x04, streamFile); type = read_32bit(0x04, sf);
/* 0x08: pseudo size? */ /* 0x08: pseudo size? */
/* other fields may be chunk sizes and lesser stuff */ /* other fields may be chunk sizes and lesser stuff */
/* 0x88: codec header */ /* 0x88: codec header */
channel_count = read_32bit(0x54,streamFile); /* assumed */ channels = read_32bit(0x54,sf); /* assumed */
if (channel_count != 1) goto fail; if (channels != 1) goto fail;
sample_rate = read_32bit(0x58,streamFile); sample_rate = read_32bit(0x58,sf);
loop_flag = 1; /* most files repeat except small jingles, but smaller ambient tracks also repeat */ loop_flag = 1; /* most files repeat except small jingles, but smaller ambient tracks also repeat */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_MUS_VC; vgmstream->meta_type = meta_MUS_VC;
@ -44,19 +44,19 @@ VGMSTREAM * init_vgmstream_mus_vc(STREAMFILE *streamFile) {
case 0x01: case 0x01:
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = dsp_bytes_to_samples(read_32bit(0xB0,streamFile), vgmstream->channels); vgmstream->num_samples = dsp_bytes_to_samples(read_32bit(0xB0,sf), vgmstream->channels);
vgmstream->loop_start_sample = 0; vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
start_offset = 0xB8; start_offset = 0xB8;
dsp_read_coefs_be(vgmstream,streamFile,0x88,0x00); dsp_read_coefs_be(vgmstream,sf,0x88,0x00);
dsp_read_hist_be (vgmstream,streamFile,0xac,0x00); dsp_read_hist_be (vgmstream,sf,0xac,0x00);
break; break;
case 0x02: case 0x02:
vgmstream->coding_type = coding_XBOX_IMA; vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bit(0x9a,streamFile), vgmstream->channels); vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bit(0x9a,sf), vgmstream->channels);
vgmstream->loop_start_sample = 0; vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
@ -67,9 +67,9 @@ VGMSTREAM * init_vgmstream_mus_vc(STREAMFILE *streamFile) {
goto fail; goto fail;
} }
read_string(vgmstream->stream_name,0x14, 0x34,streamFile); /* repeated at 0x64, size at 0x30/0x60 */ read_string(vgmstream->stream_name,0x14, 0x34,sf); /* repeated at 0x64, size at 0x30/0x60 */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -6,7 +6,7 @@
VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) { VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channels; int loop_flag, channels, skip_samples;
size_t data_size; size_t data_size;
@ -22,6 +22,7 @@ VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) {
start_offset = 0x1000; start_offset = 0x1000;
loop_flag = (read_s32le(0x18,sf) != 0); loop_flag = (read_s32le(0x18,sf) != 0);
channels = read_s32le(0x08,sf); channels = read_s32le(0x08,sf);
skip_samples = 1024; /* raw AAC doesn't set this */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
@ -42,15 +43,14 @@ VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
{ {
vgmstream->codec_data = init_ffmpeg_aac(sf, start_offset, data_size); vgmstream->codec_data = init_ffmpeg_aac(sf, start_offset, data_size, skip_samples);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* observed default, some files start without silence though seems correct when loop_start=0 */ /* observed default, some files start without silence though seems correct when loop_start=0 */
ffmpeg_set_skip_samples(vgmstream->codec_data, 1024); /* raw AAC doesn't set this */ vgmstream->num_samples -= skip_samples;
vgmstream->num_samples -= 1024; vgmstream->loop_end_sample -= skip_samples;
vgmstream->loop_end_sample -= 1024;
/* for some reason last frame is ignored/bugged in various decoders (gives EOF errors) */ /* for some reason last frame is ignored/bugged in various decoders (gives EOF errors) */
} }
#else #else

View File

@ -2,41 +2,41 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* .str - Cauldron/Conan mini-header + interleaved dsp data [Conan (GC)] */ /* .str - Cauldron/Conan mini-header + interleaved dsp data [Conan (GC)] */
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ngc_str(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int channel_count, loop_flag; int channels, loop_flag;
/* checks */ /* checks */
if (!check_extensions(streamFile, "str")) if (!check_extensions(sf, "str"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0xFAAF0001) /* header id */ if (read_u32be(0x00,sf) != 0xFAAF0001) /* header id */
goto fail; goto fail;
channel_count = 2; /* always loop & stereo */ channels = 2; /* always loop & stereo */
loop_flag = 1; loop_flag = 1;
start_offset = 0x60; start_offset = 0x60;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitBE(0x04,streamFile); vgmstream->sample_rate = read_s32be(0x04,sf);
vgmstream->num_samples = read_32bitBE(0x08,streamFile); vgmstream->num_samples = read_s32be(0x08,sf);
vgmstream->loop_start_sample = 0; vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_DSP_STR; vgmstream->meta_type = meta_DSP_STR;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile); vgmstream->interleave_block_size = read_u32be(0x0C,sf);
dsp_read_coefs_be(vgmstream, streamFile, 0x10, 0x20); dsp_read_coefs_be(vgmstream, sf, 0x10, 0x20);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -62,6 +62,7 @@ static STREAMFILE* setup_nus3bank_streamfile(STREAMFILE *sf, off_t start) {
/* find "data" */ /* find "data" */
pos = 0x0c; pos = 0x0c;
data_pos = 0;
while(pos < sizeof(buf)) { while(pos < sizeof(buf)) {
chunk_type = get_u32be(buf + pos + 0x00) ^ chunk_key; chunk_type = get_u32be(buf + pos + 0x00) ^ chunk_key;
chunk_size = get_u32be(buf + pos + 0x04) ^ chunk_key; chunk_size = get_u32be(buf + pos + 0x04) ^ chunk_key;

View File

@ -2,16 +2,16 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* NWAV - from Chunsoft games [Fuurai no Shiren Gaiden: Onnakenshi Asuka Kenzan! (PC)] */ /* NWAV - from Chunsoft games [Fuurai no Shiren Gaiden: Onnakenshi Asuka Kenzan! (PC)] */
VGMSTREAM * init_vgmstream_nwav(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_nwav(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
/* checks */ /* checks */
/* .nwav: header id (no filenames in bigfiles) */ /* .nwav: header id (no filenames in bigfiles) */
if ( !check_extensions(streamFile,"nwav") ) if ( !check_extensions(sf,"nwav") )
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4E574156) /* "NWAV" */ if (read_32bitBE(0x00,sf) != 0x4E574156) /* "NWAV" */
goto fail; goto fail;
@ -22,17 +22,17 @@ VGMSTREAM * init_vgmstream_nwav(STREAMFILE *streamFile) {
/* 0x04: version? */ /* 0x04: version? */
/* 0x08: crc? */ /* 0x08: crc? */
ovmi.stream_size = read_32bitLE(0x0c, streamFile); ovmi.stream_size = read_32bitLE(0x0c, sf);
ovmi.loop_end = read_32bitLE(0x10, streamFile); /* num_samples, actually */ ovmi.loop_end = read_32bitLE(0x10, sf); /* num_samples, actually */
/* 0x14: sample rate */ /* 0x14: sample rate */
/* 0x18: bps? (16) */ /* 0x18: bps? (16) */
channels = read_8bit(0x19, streamFile); channels = read_8bit(0x19, sf);
start_offset = read_16bitLE(0x1a, streamFile); start_offset = read_16bitLE(0x1a, sf);
ovmi.loop_flag = read_16bitLE(0x1c, streamFile) != 0; /* loop count? -1 = loops */ ovmi.loop_flag = read_16bitLE(0x1c, sf) != 0; /* loop count? -1 = loops */
/* 0x1e: always 2? */ /* 0x1e: always 2? */
/* 0x20: always 1? */ /* 0x20: always 1? */
ovmi.loop_start = read_32bitLE(0x24, streamFile); ovmi.loop_start = read_32bitLE(0x24, sf);
/* 0x28: always 1? */ /* 0x28: always 1? */
/* 0x2a: always 1? */ /* 0x2a: always 1? */
/* 0x2c: always null? */ /* 0x2c: always null? */
@ -43,7 +43,7 @@ VGMSTREAM * init_vgmstream_nwav(STREAMFILE *streamFile) {
ovmi.loop_start = ovmi.loop_start / sizeof(int16_t) / channels; ovmi.loop_start = ovmi.loop_start / sizeof(int16_t) / channels;
ovmi.loop_end = ovmi.loop_end / sizeof(int16_t) / channels; ovmi.loop_end = ovmi.loop_end / sizeof(int16_t) / channels;
vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
} }
#else #else
goto fail; goto fail;

View File

@ -286,21 +286,21 @@ VGMSTREAM* init_vgmstream_ogg_vorbis(STREAMFILE* sf) {
* 0x0c(2): PCM block size, 0x0e(2): PCM bps, 0x10: null, 0x18: samples (in PCM bytes) * 0x0c(2): PCM block size, 0x0e(2): PCM bps, 0x10: null, 0x18: samples (in PCM bytes)
* - .isl: looping table (encrypted like the files) */ * - .isl: looping table (encrypted like the files) */
if (isl_name) { if (isl_name) {
STREAMFILE* islFile = NULL; STREAMFILE* sf_isl = NULL;
islFile = open_streamfile_by_filename(sf, isl_name); sf_isl = open_streamfile_by_filename(sf, isl_name);
if (!islFile) { if (!sf_isl) {
/* try in ../(file) too since that's how the .isl is stored on disc */ /* try in ../(file) too since that's how the .isl is stored on disc */
char isl_path[PATH_LIMIT]; char isl_path[PATH_LIMIT];
snprintf(isl_path, sizeof(isl_path), "../%s", isl_name); snprintf(isl_path, sizeof(isl_path), "../%s", isl_name);
islFile = open_streamfile_by_filename(sf, isl_path); sf_isl = open_streamfile_by_filename(sf, isl_path);
} }
if (islFile) { if (sf_isl) {
STREAMFILE* dec_sf = NULL; STREAMFILE* dec_sf = NULL;
dec_sf = setup_ogg_vorbis_streamfile(islFile, cfg); dec_sf = setup_ogg_vorbis_streamfile(sf_isl, cfg);
if (dec_sf) { if (dec_sf) {
off_t loop_offset; off_t loop_offset;
char basename[PATH_LIMIT]; char basename[PATH_LIMIT];
@ -327,7 +327,7 @@ VGMSTREAM* init_vgmstream_ogg_vorbis(STREAMFILE* sf) {
close_streamfile(dec_sf); close_streamfile(dec_sf);
} }
close_streamfile(islFile); close_streamfile(sf_isl);
} }
} }
} }
@ -367,7 +367,7 @@ VGMSTREAM* init_vgmstream_ogg_vorbis(STREAMFILE* sf) {
} }
if (is_lse) { /* [Nippon Ichi PC games] */ if (is_lse) { /* [Nippon Ichi PC games] */
if (read_32bitBE(0x00,sf) == 0xFFFFFFFF) { /* [Operation Abyss: New Tokyo Legacy (PC)] */ if (read_u32be(0x00,sf) == 0xFFFFFFFF) { /* [Operation Abyss: New Tokyo Legacy (PC)] */
cfg.key[0] = 0xFF; cfg.key[0] = 0xFF;
cfg.key_len = 1; cfg.key_len = 1;
cfg.is_header_swap = 1; cfg.is_header_swap = 1;
@ -416,7 +416,7 @@ VGMSTREAM* init_vgmstream_ogg_vorbis(STREAMFILE* sf) {
ovmi.meta_type = meta_OGG_VORBIS; ovmi.meta_type = meta_OGG_VORBIS;
} }
vgmstream = init_vgmstream_ogg_vorbis_callbacks(temp_sf != NULL ? temp_sf : sf, NULL, start_offset, &ovmi); vgmstream = init_vgmstream_ogg_vorbis_config(temp_sf != NULL ? temp_sf : sf, start_offset, &ovmi);
close_streamfile(temp_sf); close_streamfile(temp_sf);
return vgmstream; return vgmstream;
@ -426,7 +426,7 @@ fail:
return NULL; return NULL;
} }
VGMSTREAM* init_vgmstream_ogg_vorbis_callbacks(STREAMFILE* sf, ov_callbacks* callbacks, off_t start, const ogg_vorbis_meta_info_t *ovmi) { VGMSTREAM* init_vgmstream_ogg_vorbis_config(STREAMFILE* sf, off_t start, const ogg_vorbis_meta_info_t* ovmi) {
VGMSTREAM* vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
ogg_vorbis_codec_data* data = NULL; ogg_vorbis_codec_data* data = NULL;
ogg_vorbis_io io = {0}; ogg_vorbis_io io = {0};

View File

@ -27,7 +27,7 @@ VGMSTREAM* init_vgmstream_ogv_3rdeye(STREAMFILE* sf) {
ovmi.meta_type = meta_OGV_3RDEYE; ovmi.meta_type = meta_OGV_3RDEYE;
ovmi.stream_size = subfile_size; ovmi.stream_size = subfile_size;
vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, subfile_offset, &ovmi); vgmstream = init_vgmstream_ogg_vorbis_config(sf, subfile_offset, &ovmi);
} }
#else #else
goto fail; goto fail;

View File

@ -157,16 +157,16 @@ VGMSTREAM* init_vgmstream_opus_n1(STREAMFILE* sf) {
int num_samples, loop_start, loop_end; int num_samples, loop_start, loop_end;
/* checks */ /* checks */
if ( !check_extensions(sf,"opus,lopus")) if (!check_extensions(sf,"opus,lopus"))
goto fail; goto fail;
if (!((read_32bitBE(0x04,sf) == 0x00000000 && read_32bitBE(0x0c,sf) == 0x00000000) || if (!((read_u32be(0x04,sf) == 0x00000000 && read_u32be(0x0c,sf) == 0x00000000) ||
(read_32bitBE(0x04,sf) == 0xFFFFFFFF && read_32bitBE(0x0c,sf) == 0xFFFFFFFF))) (read_u32be(0x04,sf) == 0xFFFFFFFF && read_u32be(0x0c,sf) == 0xFFFFFFFF)))
goto fail; goto fail;
offset = 0x10; offset = 0x10;
num_samples = 0; num_samples = 0;
loop_start = read_32bitLE(0x00,sf); loop_start = read_s32le(0x00,sf);
loop_end = read_32bitLE(0x08,sf); loop_end = read_s32le(0x08,sf);
return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end);
fail: fail:

View File

@ -0,0 +1,54 @@
#include "meta.h"
#include "../coding/coding.h"
/* PIFF TADH - from Tantalus games [House of the Dead (SAT)] */
VGMSTREAM* init_vgmstream_piff_tpcm(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, header_offset, data_size;
int loop_flag, channels, sample_rate;
/* checks */
/* .tad: from internal filenames */
if (!check_extensions(sf, "tad"))
goto fail;
/* Tantalus also has PIFF without this */
if (!is_id32be(0x00,sf, "PIFF") || !is_id32be(0x08,sf, "TPCM") || !is_id32be(0x0c,sf, "TADH"))
goto fail;
header_offset = 0x14;
/* 0x00: 1? */
/* 0x01: 1? */
channels = read_u16le(header_offset + 0x02,sf);
sample_rate = read_s32le(header_offset + 0x04,sf);
/* 0x08+: ? (mostly fixed, maybe related to ADPCM?) */
loop_flag = 0;
if (!is_id32be(0x38,sf, "BODY"))
goto fail;
start_offset = 0x40;
data_size = read_u32le(0x3c,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_PIFF_TPCM;
vgmstream->sample_rate = sample_rate;
vgmstream->coding_type = coding_TANTALUS;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->num_samples = tantalus_bytes_to_samples(data_size, channels);
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,64 +1,53 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../coding/coding.h"
/* SFS (from Baroque) */ /* SFS - from Sting games [Baroque (PS2)] */
VGMSTREAM * init_vgmstream_sfs(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_sfs(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag; int loop_flag, channels, sample_rate;
int channel_count; size_t channel_size, loop_start;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("sfs",filename_extension(filename))) goto fail;
/* check header */ /* checks */
if (read_32bitBE(0x00,streamFile) != 0x53544552) /* "STER" */ /* .sfs: bigfile extension (no apparent names) */
if (!check_extensions(sf, "sfs"))
goto fail; goto fail;
loop_flag = (read_32bitLE(0x08,streamFile)!=0xFFFFFFFF); if (!is_id32be(0x00,sf, "STER"))
channel_count = 2; goto fail;
channel_size = read_u32le(0x04, sf);
loop_start = read_u32le(0x08, sf); /* absolute (ex. offset 0x50 for full loops) */
/* 0x0c: data size BE */
sample_rate = read_s32be(0x10,sf);
loop_flag = loop_start != 0xFFFFFFFF;
channels = 2;
start_offset = 0x30;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ vgmstream->meta_type = meta_SFS;
start_offset = 0x30; vgmstream->sample_rate = sample_rate;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x04,streamFile)*2)*28/16/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)*28/16/channel_count;
vgmstream->loop_end_sample = (read_32bitLE(0x04,streamFile)*2)*28/16/channel_count;
}
vgmstream->num_samples = ps_bytes_to_samples(channel_size, 1);
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start - start_offset, channels);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_SFS;
/* open the file for reading */ read_string(vgmstream->stream_name,0x10+1, 0x20,sf);
{
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, sf, start_offset))
goto fail;
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -3,43 +3,43 @@
/* .VAS - from Konami Jikkyou Powerful Pro Yakyuu games */ /* .VAS - from Konami Jikkyou Powerful Pro Yakyuu games */
VGMSTREAM * init_vgmstream_ps2_vas(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ps2_vas(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count; int loop_flag, channels;
/* checks */ /* checks */
if (!check_extensions(streamFile, "vas")) if (!check_extensions(sf, "vas"))
goto fail; goto fail;
if (read_32bitLE(0x00,streamFile) + 0x800 != get_streamfile_size(streamFile)) if (read_u32le(0x00,sf) + 0x800 != get_streamfile_size(sf))
goto fail; goto fail;
loop_flag = (read_32bitLE(0x10,streamFile) != 0); loop_flag = (read_u32le(0x10,sf) != 0);
channel_count = 2; channels = 2;
start_offset = 0x800; start_offset = 0x800;
/* header is too simple so test a bit */ /* header is too simple so test a bit */
if (!ps_check_format(streamFile, start_offset, 0x1000)) if (!ps_check_format(sf, start_offset, 0x1000))
goto fail; goto fail;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_PS2_VAS; vgmstream->meta_type = meta_PS2_VAS;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile); vgmstream->sample_rate = read_s32le(0x04,sf);
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x200; vgmstream->interleave_block_size = 0x200;
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x00,streamFile), channel_count); vgmstream->num_samples = ps_bytes_to_samples(read_u32le(0x00,sf), channels);
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x14,streamFile), channel_count); vgmstream->loop_start_sample = ps_bytes_to_samples(read_u32le(0x14,sf), channels);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -50,35 +50,35 @@ fail:
/* .VAS in containers */ /* .VAS in containers */
VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ps2_vas_container(STREAMFILE* sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL; STREAMFILE* temp_sf = NULL;
off_t subfile_offset = 0; off_t subfile_offset = 0;
size_t subfile_size = 0; size_t subfile_size = 0;
int total_subsongs, target_subsong = streamFile->stream_index; int total_subsongs, target_subsong = sf->stream_index;
/* checks */ /* checks */
if (!check_extensions(streamFile, "vas")) if (!check_extensions(sf, "vas"))
goto fail; goto fail;
if (read_32bitBE(0x00, streamFile) == 0xAB8A5A00) { /* fixed value */ if (read_u32be(0x00, sf) == 0xAB8A5A00) { /* fixed value */
/* just in case */ /* just in case */
if (read_32bitLE(0x04, streamFile)*0x800 + 0x800 != get_streamfile_size(streamFile)) if (read_u32le(0x04, sf) * 0x800 + 0x800 != get_streamfile_size(sf))
goto fail; goto fail;
total_subsongs = read_32bitLE(0x08, streamFile); /* also at 0x10 */ total_subsongs = read_s32le(0x08, sf); /* also at 0x10 */
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* check offset table flag, 0x98 has table size */ /* check offset table flag, 0x98 has table size */
if (read_32bitLE(0x94, streamFile)) { if (read_32bitLE(0x94, sf)) {
off_t header_offset = 0x800 + 0x10*(target_subsong-1); off_t header_offset = 0x800 + 0x10*(target_subsong-1);
/* some values are repeats found in the file sub-header */ /* some values are repeats found in the file sub-header */
subfile_offset = read_32bitLE(header_offset + 0x00,streamFile) * 0x800; subfile_offset = read_32bitLE(header_offset + 0x00,sf) * 0x800;
subfile_size = read_32bitLE(header_offset + 0x08,streamFile) + 0x800; subfile_size = read_32bitLE(header_offset + 0x08,sf) + 0x800;
} }
else { else {
/* a bunch of files */ /* a bunch of files */
@ -86,7 +86,7 @@ VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) {
int i; int i;
for (i = 0; i < total_subsongs; i++) { for (i = 0; i < total_subsongs; i++) {
size_t size = read_32bitLE(offset, streamFile) + 0x800; size_t size = read_32bitLE(offset, sf) + 0x800;
if (i + 1 == target_subsong) { if (i + 1 == target_subsong) {
subfile_offset = offset; subfile_offset = offset;
@ -102,18 +102,18 @@ VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) {
} }
else { else {
/* some .vas are just files pasted together, better extracted externally but whatevs */ /* some .vas are just files pasted together, better extracted externally but whatevs */
size_t file_size = get_streamfile_size(streamFile); size_t file_size = get_streamfile_size(sf);
off_t offset = 0; off_t offset = 0;
/* must have multiple .vas */ /* must have multiple .vas */
if (read_32bitLE(0x00,streamFile) + 0x800 >= file_size) if (read_32bitLE(0x00,sf) + 0x800 >= file_size)
goto fail; goto fail;
total_subsongs = 0; total_subsongs = 0;
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
while (offset < file_size) { while (offset < file_size) {
size_t size = read_32bitLE(offset,streamFile) + 0x800; size_t size = read_32bitLE(offset,sf) + 0x800;
/* some files can be null, ignore */ /* some files can be null, ignore */
if (size > 0x800) { if (size > 0x800) {
@ -136,19 +136,19 @@ VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) {
} }
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL);
if (!temp_streamFile) goto fail; if (!temp_sf) goto fail;
vgmstream = init_vgmstream_ps2_vas(temp_streamFile); vgmstream = init_vgmstream_ps2_vas(temp_sf);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->num_streams = total_subsongs; vgmstream->num_streams = total_subsongs;
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
return vgmstream; return vgmstream;
fail: fail:
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -294,7 +294,7 @@ fail:
return 0; return 0;
} }
static int is_ue4_msadpcm(VGMSTREAM* vgmstream, STREAMFILE* sf, riff_fmt_chunk* fmt, int fact_sample_count, off_t start_offset); static int is_ue4_msadpcm(STREAMFILE* sf, riff_fmt_chunk* fmt, int fact_sample_count, off_t start_offset);
static size_t get_ue4_msadpcm_interleave(STREAMFILE* sf, riff_fmt_chunk* fmt, off_t start, size_t size); static size_t get_ue4_msadpcm_interleave(STREAMFILE* sf, riff_fmt_chunk* fmt, off_t start, size_t size);
@ -604,10 +604,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
/* ignore Beyond Good & Evil HD PS3 evil reuse of PCM codec */ /* ignore Beyond Good & Evil HD PS3 evil reuse of PCM codec */
if (fmt.coding_type == coding_PCM16LE && if (fmt.coding_type == coding_PCM16LE &&
read_32bitBE(start_offset+0x00, sf) == 0x4D534643 && /* "MSF\43" */ read_u32be(start_offset+0x00, sf) == 0x4D534643 && /* "MSF\43" */
read_32bitBE(start_offset+0x34, sf) == 0xFFFFFFFF && /* always */ read_u32be(start_offset+0x34, sf) == 0xFFFFFFFF && /* always */
read_32bitBE(start_offset+0x38, sf) == 0xFFFFFFFF && read_u32be(start_offset+0x38, sf) == 0xFFFFFFFF &&
read_32bitBE(start_offset+0x3c, sf) == 0xFFFFFFFF) read_u32be(start_offset+0x3c, sf) == 0xFFFFFFFF)
goto fail; goto fail;
/* ignore Gitaroo Man Live! (PSP) multi-RIFF (to allow chunked TXTH) */ /* ignore Gitaroo Man Live! (PSP) multi-RIFF (to allow chunked TXTH) */
@ -795,7 +795,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
} }
/* UE4 uses interleaved mono MSADPCM, try to autodetect without breaking normal MSADPCM */ /* UE4 uses interleaved mono MSADPCM, try to autodetect without breaking normal MSADPCM */
if (fmt.coding_type == coding_MSADPCM && is_ue4_msadpcm(vgmstream, sf, &fmt, fact_sample_count, start_offset)) { if (fmt.coding_type == coding_MSADPCM && is_ue4_msadpcm(sf, &fmt, fact_sample_count, start_offset)) {
vgmstream->coding_type = coding_MSADPCM_int; vgmstream->coding_type = coding_MSADPCM_int;
vgmstream->codec_config = 1; /* mark as UE4 MSADPCM */ vgmstream->codec_config = 1; /* mark as UE4 MSADPCM */
vgmstream->frame_size = fmt.block_size; vgmstream->frame_size = fmt.block_size;
@ -850,6 +850,8 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start_nxbf, vgmstream->channels, 16); vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start_nxbf, vgmstream->channels, 16);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
break; break;
default:
break;
} }
} }
} }
@ -868,7 +870,7 @@ fail:
} }
/* UE4 MSADPCM is quite normal but has a few minor quirks we can use to detect it */ /* UE4 MSADPCM is quite normal but has a few minor quirks we can use to detect it */
static int is_ue4_msadpcm(VGMSTREAM* vgmstream, STREAMFILE* sf, riff_fmt_chunk* fmt, int fact_sample_count, off_t start) { static int is_ue4_msadpcm(STREAMFILE* sf, riff_fmt_chunk* fmt, int fact_sample_count, off_t start) {
/* multichannel ok */ /* multichannel ok */
if (fmt->channel_count < 2) if (fmt->channel_count < 2)

View File

@ -2,45 +2,45 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* RKV - from Legacy of Kain - Blood Omen 2 (PS2) */ /* RKV - from Legacy of Kain - Blood Omen 2 (PS2) */
VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ps2_rkv(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, header_offset; off_t start_offset, header_offset;
size_t data_size; size_t data_size;
int loop_flag, channel_count; int loop_flag, channels;
/* checks */ /* checks */
if (!check_extensions(streamFile, "rkv")) if (!check_extensions(sf, "rkv"))
goto fail; goto fail;
if (read_32bitBE(0x24,streamFile) != 0x00) /* quick test vs GC rkv (coef position) */ if (read_u32be(0x24,sf) != 0x00) /* quick test vs GC rkv (coef position) */
goto fail; goto fail;
/* some RKV got info at offset 0x00, some other at 0x0 4 */ /* some RKV got info at offset 0x00, some other at 0x0 4 */
if (read_32bitLE(0x00,streamFile)==0) if (read_u32le(0x00,sf) == 0)
header_offset = 0x04; header_offset = 0x04;
else else
header_offset = 0x00; header_offset = 0x00;
switch (read_32bitLE(header_offset+0x0c,streamFile)) { switch (read_u32le(header_offset+0x0c,sf)) {
case 0x00: channel_count = 1; break; case 0x00: channels = 1; break;
case 0x01: channel_count = 2; break; case 0x01: channels = 2; break;
default: goto fail; default: goto fail;
} }
loop_flag = (read_32bitLE(header_offset+0x04,streamFile) != 0xFFFFFFFF); loop_flag = (read_u32le(header_offset+0x04,sf) != 0xFFFFFFFF);
start_offset = 0x800; start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset; data_size = get_streamfile_size(sf) - start_offset;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(header_offset,streamFile); vgmstream->sample_rate = read_s32le(header_offset,sf);
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); vgmstream->num_samples = ps_bytes_to_samples(data_size, channels);
//vgmstream->num_samples = read_32bitLE(header_offset+0x08,streamFile); /* sometimes not set */ //vgmstream->num_samples = read_32bitLE(header_offset+0x08,sf); /* sometimes not set */
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(header_offset+0x04,streamFile); vgmstream->loop_start_sample = read_s32le(header_offset+0x04,sf);
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x08,streamFile); vgmstream->loop_end_sample = read_s32le(header_offset+0x08,sf);
} }
vgmstream->meta_type = meta_PS2_RKV; vgmstream->meta_type = meta_PS2_RKV;
@ -51,7 +51,7 @@ VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE *streamFile) {
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels; vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -61,39 +61,41 @@ fail:
} }
/* RKV - from Legacy of Kain - Blood Omen 2 (GC) */ /* RKV - from Legacy of Kain - Blood Omen 2 (GC) */
VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ngc_rkv(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count; int loop_flag, channels;
/* checks */ /* checks */
/* "": empty (files have names but no extensions), .rkv: container bigfile extension, .bo2: fake extension */ /* "": empty (files have names but no extensions)
if (!check_extensions(streamFile, ",rkv,bo2")) * .rkv: container bigfile extension
* .bo2: fake extension */
if (!check_extensions(sf, ",rkv,bo2"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x00) if (read_u32be(0x00,sf) != 0x00)
goto fail; goto fail;
if (read_32bitBE(0x24,streamFile) == 0x00) /* quick test vs GC rkv (coef position) */ if (read_u32be(0x24,sf) == 0x00) /* quick test vs GC rkv (coef position) */
goto fail; goto fail;
switch (read_32bitBE(0x10,streamFile)) { switch (read_u32be(0x10,sf)) {
case 0x00: channel_count = 1; break; case 0x00: channels = 1; break;
case 0x01: channel_count = 2; break; case 0x01: channels = 2; break;
default: goto fail; default: goto fail;
} }
loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF); loop_flag = (read_u32be(0x08,sf) != 0xFFFFFFFF);
start_offset = 0x800; start_offset = 0x800;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitBE(0x04,streamFile); vgmstream->sample_rate = read_s32be(0x04,sf);
vgmstream->num_samples = read_32bitBE(0x0C,streamFile); vgmstream->num_samples = read_s32be(0x0C,sf);
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile); vgmstream->loop_start_sample = read_s32be(0x08,sf);
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile); vgmstream->loop_end_sample = read_s32be(0x0C,sf);
} }
vgmstream->meta_type = meta_NGC_RKV; vgmstream->meta_type = meta_NGC_RKV;
@ -101,11 +103,11 @@ VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x400; vgmstream->interleave_block_size = 0x400;
dsp_read_coefs_be(vgmstream,streamFile,0x24,0x2e); dsp_read_coefs_be(vgmstream,sf,0x24,0x2e);
/* hist at 0x44/0x72? */ /* hist at 0x44/0x72? */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -3,11 +3,11 @@
/* RSD - from Radical Entertainment games */ /* RSD - from Radical Entertainment games */
VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, name_offset; off_t start_offset, name_offset;
size_t data_size; size_t data_size;
int loop_flag, channel_count, sample_rate, interleave; int loop_flag, channels, sample_rate, interleave;
uint32_t codec; uint32_t codec;
uint8_t version; uint8_t version;
@ -15,22 +15,22 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
/* checks */ /* checks */
if (!check_extensions(sf,"rsd,rsp")) if (!check_extensions(sf,"rsd,rsp"))
goto fail; goto fail;
if ((read_32bitBE(0x00,sf) & 0xFFFFFF00) != 0x52534400) /* "RSD\00" */ if ((read_u32be(0x00,sf) & 0xFFFFFF00) != 0x52534400) /* "RSD\00" */
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
codec = (uint32_t)read_32bitBE(0x04,sf); codec = read_u32be(0x04,sf);
channel_count = read_32bitLE(0x08, sf); channels = read_s32le(0x08, sf);
/* 0x0c: always 16? */ /* 0x0c: always 16? */
sample_rate = read_32bitLE(0x10, sf); sample_rate = read_s32le(0x10, sf);
version = read_8bit(0x03, sf); version = read_8bit(0x03, sf);
switch(version) { switch(version) {
case '2': /* known codecs: VAG/XADP/PCMB [The Simpsons: Road Rage] */ case '2': /* known codecs: VAG/XADP/PCMB [The Simpsons: Road Rage] */
case '3': /* known codecs: VAG/PCM/PCMB/GADP? [Dark Summit] */ case '3': /* known codecs: VAG/PCM/PCMB/GADP? [Dark Summit] */
interleave = read_32bitLE(0x14,sf); /* VAG only, 0x04 otherwise */ interleave = read_u32le(0x14,sf); /* VAG only, 0x04 otherwise */
start_offset = read_32bitLE(0x18,sf); start_offset = read_u32le(0x18,sf);
name_offset = 0; name_offset = 0;
break; break;
@ -42,8 +42,8 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
name_offset = 0; name_offset = 0;
/* PCMB/PCM/GADP normally start early but sometimes have padding [The Simpsons: Hit & Run (GC/Xbox)] */ /* PCMB/PCM/GADP normally start early but sometimes have padding [The Simpsons: Hit & Run (GC/Xbox)] */
if ((codec == 0x50434D20 || codec == 0x550434D42 || codec == 0x47414450) if ((codec == get_id32be("PCM ") || codec == get_id32be("PCMB") || codec == get_id32be("GADP"))
&& read_32bitLE(0x80,sf) != 0x2D2D2D2D) && read_u32le(0x80,sf) != 0x2D2D2D2D)
start_offset = 0x80; start_offset = 0x80;
break; break;
@ -62,7 +62,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_RSD; vgmstream->meta_type = meta_RSD;
@ -74,7 +74,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2; vgmstream->interleave_block_size = 0x2;
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 16); vgmstream->num_samples = pcm_bytes_to_samples(data_size, channels, 16);
break; break;
case 0x50434D42: /* "PCMB" [The Simpsons: Road Rage (GC), Dark Summit (GC)] */ case 0x50434D42: /* "PCMB" [The Simpsons: Road Rage (GC), Dark Summit (GC)] */
@ -82,7 +82,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2; vgmstream->interleave_block_size = 0x2;
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 16); vgmstream->num_samples = pcm_bytes_to_samples(data_size, channels, 16);
break; break;
case 0x56414720: /* "VAG " [The Simpsons: Road Rage (PS2), Crash Tag Team Racing (PSP)] */ case 0x56414720: /* "VAG " [The Simpsons: Road Rage (PS2), Crash Tag Team Racing (PSP)] */
@ -90,11 +90,11 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = (interleave == 0) ? 0x10 : interleave; vgmstream->interleave_block_size = (interleave == 0) ? 0x10 : interleave;
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); vgmstream->num_samples = ps_bytes_to_samples(data_size, channels);
break; break;
case 0x58414450: /* "XADP" [The Simpsons: Road Rage (Xbox)], Crash Tag Team Racing (Xbox)] */ case 0x58414450: /* "XADP" [The Simpsons: Road Rage (Xbox)], Crash Tag Team Racing (Xbox)] */
vgmstream->coding_type = (channel_count > 2) ? coding_XBOX_IMA_mch : coding_XBOX_IMA; vgmstream->coding_type = (channels > 2) ? coding_XBOX_IMA_mch : coding_XBOX_IMA;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
@ -107,7 +107,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
dsp_read_coefs_le(vgmstream,sf,0x14,0x2e); /* LE! */ dsp_read_coefs_le(vgmstream,sf,0x14,0x2e); /* LE! */
dsp_read_hist_le (vgmstream,sf,0x38,0x2e); dsp_read_hist_le (vgmstream,sf,0x38,0x2e);
vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count); vgmstream->num_samples = dsp_bytes_to_samples(data_size, channels);
break; break;
case 0x57414450: /* "WADP" [Crash: Mind Over Mutant (Wii)] */ case 0x57414450: /* "WADP" [Crash: Mind Over Mutant (Wii)] */
@ -117,15 +117,15 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
dsp_read_coefs_be(vgmstream,sf,0x1a4,0x28); dsp_read_coefs_be(vgmstream,sf,0x1a4,0x28);
dsp_read_hist_be (vgmstream,sf,0x1c8,0x28); dsp_read_hist_be (vgmstream,sf,0x1c8,0x28);
vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count); vgmstream->num_samples = dsp_bytes_to_samples(data_size, channels);
break; break;
case 0x52414450: /* "RADP" [The Simpsons: Hit & Run (GC), Scarface (Wii)] */ case 0x52414450: /* "RADP" [The Simpsons: Hit & Run (GC), Scarface (Wii)] */
vgmstream->coding_type = coding_RAD_IMA; vgmstream->coding_type = coding_RAD_IMA;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x14*channel_count; vgmstream->interleave_block_size = 0x14*channels;
vgmstream->num_samples = data_size / 0x14 / channel_count * 32; /* bytes-to-samples */ vgmstream->num_samples = data_size / 0x14 / channels * 32; /* bytes-to-samples */
break; break;
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
@ -134,7 +134,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
ovmi.meta_type = meta_RSD; ovmi.meta_type = meta_RSD;
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, start_offset, &ovmi); vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
break; break;
} }
@ -142,17 +142,15 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x574D4120: { /* "WMA " [Scarface (Xbox)] */ case 0x574D4120: { /* "WMA " [Scarface (Xbox)] */
ffmpeg_codec_data *ffmpeg_data = NULL;
/* mini header + WMA header at start_offset */ /* mini header + WMA header at start_offset */
ffmpeg_data = init_ffmpeg_offset(sf, start_offset+0x08,data_size); vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset+0x08,data_size);
if (!ffmpeg_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; /* an estimation, sometimes cuts files a bit early */ vgmstream->num_samples = ffmpeg_get_samples(vgmstream->codec_data); /* an estimation, sometimes cuts files a bit early */
//vgmstream->num_samples = read_32bitLE(start_offset + 0x00, sf) / channel_count / 2; /* may be PCM data size, but not exact */ //vgmstream->num_samples = read_32bitLE(start_offset + 0x00, sf) / channels / 2; /* may be PCM data size, but not exact */
vgmstream->sample_rate = read_32bitLE(start_offset + 0x04, sf); vgmstream->sample_rate = read_32bitLE(start_offset + 0x04, sf);
break; break;
} }
@ -170,7 +168,6 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
} }
case 0x584D4120: { /* "XMA " [Crash of the Titans (X360)-v1, Crash: Mind over Mutant (X360)-v2] */ case 0x584D4120: { /* "XMA " [Crash of the Titans (X360)-v1, Crash: Mind over Mutant (X360)-v2] */
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[0x100]; uint8_t buf[0x100];
size_t bytes, xma_size, block_size, block_count; size_t bytes, xma_size, block_size, block_count;
int xma_version; int xma_version;
@ -199,15 +196,14 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) {
} }
bytes = ffmpeg_make_riff_xma2(buf,sizeof(buf), vgmstream->num_samples, xma_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf,sizeof(buf), vgmstream->num_samples, xma_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
ffmpeg_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, xma_size); vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, xma_size);
if (!ffmpeg_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* for some reason (dev trickery?) .rsd don't set skip in the bitstream, though they should */ /* for some reason (dev trickery?) .rsd don't set skip in the bitstream, though they should */
//xma_fix_raw_samples(vgmstream, sf, start_offset,xma_size, 0, 0,0); //xma_fix_raw_samples(vgmstream, sf, start_offset,xma_size, 0, 0,0);
ffmpeg_set_skip_samples(ffmpeg_data, 512+64); ffmpeg_set_skip_samples(vgmstream->codec_data, 512+64);
break; break;
} }
#endif #endif

View File

@ -192,7 +192,7 @@ VGMSTREAM* init_vgmstream_rxws_badrip(STREAMFILE* sf) {
(read_32bitBE(0x10,sf) == 0x464F524D))) (read_32bitBE(0x10,sf) == 0x464F524D)))
goto fail; goto fail;
loop_flag = (read_32bitLE(0x3C,sf)!=0xFFFFFFFF); loop_flag = (read_u32le(0x3C,sf)!=0xFFFFFFFF);
channels=2; /* Always stereo files */ channels=2; /* Always stereo files */
/* build the VGMSTREAM */ /* build the VGMSTREAM */

View File

@ -1,31 +1,33 @@
#include "meta.h" #include "meta.h"
/* DVI - from Konami KCE Nayoga SAT games (Castlevania Symphony of the Night, Jikkyou Oshaberi Parodius - Forever with Me) */ /* DVI - from Konami KCE Nayoga SAT games (Castlevania Symphony of the Night, Jikkyou Oshaberi Parodius - Forever with Me) */
VGMSTREAM * init_vgmstream_sat_dvi(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_sat_dvi(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count; int loop_flag, channels;
/* check extension (.pcm: original, .dvi: renamed to header id) */ /* checks
if ( !check_extensions(streamFile,"pcm,dvi") ) * .pcm: original
* .dvi: header id (to be removed )*/
if (!check_extensions(sf,"pcm,dvi"))
goto fail; goto fail;
/* check header */ if (!is_id32be(0x00,sf, "DVI."))
if (read_32bitBE(0x00,streamFile) != 0x4456492E) /* "DVI." */
goto fail; goto fail;
start_offset = read_32bitBE(0x04,streamFile); start_offset = read_s32be(0x04,sf);
loop_flag = (read_32bitBE(0x0C,streamFile) != 0xFFFFFFFF); loop_flag = (read_s32be(0x0C,sf) != -1);
channel_count = 2; /* no mono files seem to exists */ channels = 2; /* no mono files seem to exists */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = 44100; vgmstream->sample_rate = 44100;
vgmstream->num_samples = read_32bitBE(0x08,streamFile); vgmstream->num_samples = read_s32be(0x08,sf);
vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile); vgmstream->loop_start_sample = read_s32be(0x0C,sf);
vgmstream->loop_end_sample = read_32bitBE(0x08,streamFile); vgmstream->loop_end_sample = read_s32be(0x08,sf);
vgmstream->coding_type = coding_DVI_IMA_int; vgmstream->coding_type = coding_DVI_IMA_int;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
@ -34,12 +36,11 @@ VGMSTREAM * init_vgmstream_sat_dvi(STREAMFILE *streamFile) {
/* at 0x10 (L) / 0x20 (R): probably ADPCM loop history @+0x00 and step @+0x17 (not init values) */ /* at 0x10 (L) / 0x20 (R): probably ADPCM loop history @+0x00 and step @+0x17 (not init values) */
/* open the file for reading */ if (!vgmstream_open_stream(vgmstream, sf, start_offset) )
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail; goto fail;
/* for some reason right channel goes first (tested in SOTN vs emu and PS/OST version), swap offsets */ /* for some reason right channel goes first (tested in SOTN vs emu and PS/OST version), swap offsets */
if (channel_count == 2) { if (channels == 2) {
off_t temp = vgmstream->ch[0].offset; off_t temp = vgmstream->ch[0].offset;
vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].channel_start_offset =
vgmstream->ch[0].offset = vgmstream->ch[1].offset; vgmstream->ch[0].offset = vgmstream->ch[1].offset;

View File

@ -1,45 +1,65 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
typedef enum { PSX, PCM, DSP } sdf_codec;
/* SDF - from Beyond Reality games */ /* SDF - from Beyond Reality games */
VGMSTREAM * init_vgmstream_sdf(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_sdf(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
size_t data_size; size_t data_size;
int loop_flag, channel_count, sample_rate, interleave, coefs_offset; int loop_flag, channels, sample_rate, interleave, coefs_offset;
sdf_codec codec;
/* checks */ /* checks */
if (!check_extensions(streamFile,"sdf")) if (!check_extensions(sf,"sdf"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53444600) /* "SDF\0" */ if (!is_id32be(0x00,sf, "SDF\0"))
goto fail; goto fail;
if (read_32bitBE(0x04,streamFile) != 0x03000000) /* version? */ if (read_u32le(0x04,sf) != 3) /* version? */
goto fail; goto fail;
data_size = read_32bitLE(0x08,streamFile); data_size = read_u32le(0x08,sf);
start_offset = get_streamfile_size(streamFile) - data_size; start_offset = get_streamfile_size(sf) - data_size;
switch(start_offset) { switch(start_offset) {
case 0x18: /* Agent Hugo - Lemoon Twist (PS2)*/ case 0x18:
sample_rate = read_32bitLE(0x0c,streamFile); if (read_u32le(0x10,sf) > 6) {
channel_count = read_32bitLE(0x10,streamFile); /* Hugo Magic in the Troll Woods (NDS) */
interleave = read_32bitLE(0x14,streamFile); /* 0x0c: some size? */
sample_rate = read_s32le(0x10,sf);
channels = read_u8(0x14,sf);
/* 0x14: 1? */
interleave = read_u16le(0x16,sf);
codec = PCM;
}
else {
/* Agent Hugo: Lemoon Twist (PS2) */
sample_rate = read_s32le(0x0c,sf);
channels = read_u32le(0x10,sf);
interleave = read_u32le(0x14,sf);
codec = PSX;
}
break; break;
case 0x78: /* Gummy Bears Mini Golf (3DS) */ case 0x78: /* Gummy Bears Mini Golf (3DS) */
sample_rate = read_32bitLE(0x10,streamFile); sample_rate = read_s32le(0x10,sf);
channel_count = read_32bitLE(0x14,streamFile); channels = read_u32le(0x14,sf);
interleave = read_32bitLE(0x18,streamFile); interleave = read_u32le(0x18,sf);
coefs_offset = 0x1c; coefs_offset = 0x1c;
codec = DSP;
break; break;
case 0x84: /* Mr. Bean's Wacky World (Wii) */ case 0x84: /* Mr. Bean's Wacky World (Wii) */
sample_rate = read_32bitLE(0x10,streamFile); sample_rate = read_s32le(0x10,sf);
channel_count = read_32bitLE(0x14,streamFile); channels = read_u32le(0x14,sf);
interleave = read_32bitLE(0x18,streamFile); interleave = read_u32le(0x18,sf);
data_size = read_32bitLE(0x20,streamFile); /* usable size */ data_size = read_u32le(0x20,sf); /* usable size */
coefs_offset = 0x28; coefs_offset = 0x28;
codec = DSP;
break; break;
default: default:
@ -50,33 +70,40 @@ VGMSTREAM * init_vgmstream_sdf(STREAMFILE *streamFile) {
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SDF; vgmstream->meta_type = meta_SDF;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
switch(start_offset) { switch(codec) {
case 0x18: case PCM:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
vgmstream->num_samples = pcm16_bytes_to_samples(data_size, channels);
break;
case PSX:
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = interleave;
vgmstream->num_samples = ps_bytes_to_samples(data_size,channel_count); vgmstream->num_samples = ps_bytes_to_samples(data_size, channels);
break; break;
case 0x78: case DSP:
case 0x84:
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = interleave;
if (vgmstream->interleave_block_size == 0) /* Gummy Bears Mini Golf */ if (vgmstream->interleave_block_size == 0) /* Gummy Bears Mini Golf */
vgmstream->interleave_block_size = data_size / channel_count; vgmstream->interleave_block_size = data_size / channels;
vgmstream->num_samples = dsp_bytes_to_samples(data_size,channel_count); vgmstream->num_samples = dsp_bytes_to_samples(data_size, channels);
dsp_read_coefs_le(vgmstream, streamFile, coefs_offset+0x00,0x2e); dsp_read_coefs_le(vgmstream, sf, coefs_offset+0x00,0x2e);
dsp_read_hist_le (vgmstream, streamFile, coefs_offset+0x24,0x2e); dsp_read_hist_le (vgmstream, sf, coefs_offset+0x24,0x2e);
break; break;
default: default:
@ -89,7 +116,7 @@ VGMSTREAM * init_vgmstream_sdf(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
} }
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -192,7 +192,7 @@ VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) {
} }
/* actual Ogg init */ /* actual Ogg init */
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, start_offset, &ovmi); ogg_vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi);
if (ogg_vgmstream && name_offset) if (ogg_vgmstream && name_offset)
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, sf); read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, sf);
return ogg_vgmstream; return ogg_vgmstream;

View File

@ -172,7 +172,7 @@ VGMSTREAM* init_vgmstream_sqex_sead(STREAMFILE* sf) {
/* 0x18: reserved x2 */ /* 0x18: reserved x2 */
/* 0x20: seek table */ /* 0x20: seek table */
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, subfile_offset, &ovmi); ogg_vgmstream = init_vgmstream_ogg_vorbis_config(sf, subfile_offset, &ovmi);
if (ogg_vgmstream) { if (ogg_vgmstream) {
ogg_vgmstream->num_streams = vgmstream->num_streams; ogg_vgmstream->num_streams = vgmstream->num_streams;
ogg_vgmstream->stream_size = vgmstream->stream_size; ogg_vgmstream->stream_size = vgmstream->stream_size;

View File

@ -150,8 +150,8 @@ VGMSTREAM* init_vgmstream_str_wav(STREAMFILE* sf) {
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = ffmpeg_data->totalSamples; vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data);
if (vgmstream->channels != ffmpeg_data->channels) if (vgmstream->channels != ffmpeg_get_channels(ffmpeg_data))
goto fail; goto fail;
break; break;

View File

@ -4,9 +4,9 @@
/* .STRM - from Abylight 3DS games [Cursed Castilla (3DS)] */ /* .STRM - from Abylight 3DS games [Cursed Castilla (3DS)] */
VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) { VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count, sample_rate; int loop_flag, channel_count, sample_rate, skip_samples;
size_t data_size; size_t data_size;
@ -22,6 +22,7 @@ VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) {
loop_flag = 0; loop_flag = 0;
channel_count = 2; /* there are various possible fields but all files are stereo */ channel_count = 2; /* there are various possible fields but all files are stereo */
sample_rate = read_32bitLE(0x08,sf); sample_rate = read_32bitLE(0x08,sf);
skip_samples = 1024; /* assumed, maybe a bit more */
start_offset = 0x1e; start_offset = 0x1e;
data_size = read_32bitLE(0x10,sf); data_size = read_32bitLE(0x10,sf);
@ -42,14 +43,12 @@ VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
{ {
vgmstream->codec_data = init_ffmpeg_aac(sf, start_offset, data_size); vgmstream->codec_data = init_ffmpeg_aac(sf, start_offset, data_size, skip_samples);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* assumed, maybe a bit more */ vgmstream->num_samples -= skip_samples;
ffmpeg_set_skip_samples(vgmstream->codec_data, 1024);
vgmstream->num_samples -= 1024;
} }
#else #else
goto fail; goto fail;

View File

@ -483,10 +483,10 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
if (!ffmpeg_data) goto fail; if (!ffmpeg_data) goto fail;
if (vgmstream->num_samples == 0) if (vgmstream->num_samples == 0)
vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */ vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); /* sometimes works */
} }
else if (txth.codec == AAC) { else if (txth.codec == AAC) {
ffmpeg_data = init_ffmpeg_aac(txth.sf_body, txth.start_offset, txth.data_size); ffmpeg_data = init_ffmpeg_aac(txth.sf_body, txth.start_offset, txth.data_size, 0);
if (!ffmpeg_data) goto fail; if (!ffmpeg_data) goto fail;
} }
else { else {
@ -1553,7 +1553,7 @@ static int read_name_table_keyval(txth_header* txth, const char* line, char* key
//todo names with # and subsongs don't work //todo names with # and subsongs don't work
/* ignore comments (that aren't subsongs) */ /* ignore comments (that aren't subsongs) */
if (line[0] == '#' && strchr(line,':') < 0) if (line[0] == '#' && strchr(line,':') == NULL)
return 0; return 0;
/* try "(name): (val))" */ /* try "(name): (val))" */

View File

@ -599,7 +599,7 @@ fail:
} }
static VGMSTREAM* init_vgmstream_ubi_bao_silence(ubi_bao_header* bao, STREAMFILE* sf) { static VGMSTREAM* init_vgmstream_ubi_bao_silence(ubi_bao_header* bao) {
VGMSTREAM* vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
int channels, sample_rate; int channels, sample_rate;
int32_t num_samples; int32_t num_samples;
@ -660,7 +660,7 @@ static VGMSTREAM* init_vgmstream_ubi_bao_header(ubi_bao_header* bao, STREAMFILE*
break; break;
case UBI_SILENCE: case UBI_SILENCE:
vgmstream = init_vgmstream_ubi_bao_silence(bao, sf); vgmstream = init_vgmstream_ubi_bao_silence(bao);
break; break;
default: default:
@ -990,7 +990,7 @@ fail:
} }
/* adjust some common values */ /* adjust some common values */
static int parse_values(ubi_bao_header* bao, STREAMFILE* sf) { static int parse_values(ubi_bao_header* bao) {
if (bao->type == UBI_SEQUENCE || bao->type == UBI_SILENCE) if (bao->type == UBI_SEQUENCE || bao->type == UBI_SILENCE)
return 1; return 1;
@ -1228,7 +1228,7 @@ static int parse_header(ubi_bao_header* bao, STREAMFILE* sf, off_t offset) {
goto fail; goto fail;
} }
if (!parse_values(bao, sf)) if (!parse_values(bao))
goto fail; goto fail;
if (!parse_offsets(bao, sf)) if (!parse_offsets(bao, sf))

View File

@ -1,11 +1,11 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
static int get_loop_points(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end); static int get_loop_points(STREAMFILE* sf, int* p_loop_start, int* p_loop_end);
/* Jade RIFF - from Ubisoft Jade engine games [Beyond Good & Evil (multi), Rayman Raving Rabbids 1/2 (multi)] */ /* Jade RIFF - from Ubisoft Jade engine games [Beyond Good & Evil (multi), Rayman Raving Rabbids 1/2 (multi)] */
VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ubi_jade(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, first_offset = 0xc; off_t start_offset, first_offset = 0xc;
off_t fmt_offset, data_offset; off_t fmt_offset, data_offset;
size_t fmt_size, data_size; size_t fmt_size, data_size;
@ -16,27 +16,29 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
/* checks */ /* checks */
/* .waa: ambiances, .wam: music, .wac: sfx, .wad: dialogs (usually) /* .waa: ambiances, .wam: music, .wac: sfx, .wad: dialogs (usually)
* .wav: Beyond Good & Evil HD (PS3), .psw: fake/badly extracted names [ex. Rayman Raving Rabbids (PS2)] */ * .wav: Beyond Good & Evil HD (PS3)
if (!check_extensions(streamFile,"waa,wac,wad,wam,wav,lwav,psw")) * .psw: fake/badly extracted names [ex. Rayman Raving Rabbids (PS2)] */
if (!check_extensions(sf,"waa,wac,wad,wam,wav,lwav,psw"))
goto fail; goto fail;
/* a slightly twisted RIFF with custom codecs */ /* a slightly twisted RIFF with custom codecs */
if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */ if (!is_id32be(0x00,sf, "RIFF") ||
read_32bitBE(0x08,streamFile) != 0x57415645) /* "WAVE" */ !is_id32be(0x08,sf, "WAVE"))
goto fail; goto fail;
if (check_extensions(streamFile,"psw")) { /* .psw are incorrectly extracted missing 0x04 at the end */
if (read_32bitLE(0x04,streamFile)+0x04 != get_streamfile_size(streamFile)) if (check_extensions(sf,"psw")) { /* .psw are incorrectly extracted missing 0x04 at the end */
if (read_32bitLE(0x04,sf)+0x04 != get_streamfile_size(sf))
goto fail; goto fail;
} }
else { else {
if (read_32bitLE(0x04,streamFile)+0x04+0x04 != get_streamfile_size(streamFile)) if (read_32bitLE(0x04,sf)+0x04+0x04 != get_streamfile_size(sf))
goto fail; goto fail;
} }
if (!find_chunk(streamFile, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size, 0, 0)) /* "fmt " */ if (!find_chunk(sf, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size, 0, 0)) /* "fmt " */
goto fail; goto fail;
if (!find_chunk(streamFile, 0x64617461,first_offset,0, &data_offset,&data_size, 0, 0)) /* "data" */ if (!find_chunk(sf, 0x64617461,first_offset,0, &data_offset,&data_size, 0, 0)) /* "data" */
goto fail; goto fail;
/* ignore LyN RIFF (needed as codec 0xFFFE is reused) */ /* ignore LyN RIFF (needed as codec 0xFFFE is reused) */
@ -44,8 +46,8 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
off_t fact_offset; off_t fact_offset;
size_t fact_size; size_t fact_size;
if (find_chunk(streamFile, 0x66616374,first_offset,0, &fact_offset,&fact_size, 0, 0)) { /* "fact" */ if (find_chunk(sf, 0x66616374,first_offset,0, &fact_offset,&fact_size, 0, 0)) { /* "fact" */
if (fact_size == 0x10 && read_32bitBE(fact_offset+0x04, streamFile) == 0x4C794E20) /* "LyN " */ if (fact_size == 0x10 && read_32bitBE(fact_offset+0x04, sf) == 0x4C794E20) /* "LyN " */
goto fail; /* parsed elsewhere */ goto fail; /* parsed elsewhere */
/* Jade doesn't use "fact", though */ /* Jade doesn't use "fact", though */
} }
@ -56,10 +58,10 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
{ {
if (fmt_size < 0x10) if (fmt_size < 0x10)
goto fail; goto fail;
codec = (uint16_t)read_16bitLE(fmt_offset+0x00,streamFile); codec = (uint16_t)read_16bitLE(fmt_offset+0x00,sf);
channel_count = read_16bitLE(fmt_offset+0x02,streamFile); channel_count = read_16bitLE(fmt_offset+0x02,sf);
sample_rate = read_32bitLE(fmt_offset+0x04,streamFile); sample_rate = read_32bitLE(fmt_offset+0x04,sf);
block_size = (uint16_t)read_16bitLE(fmt_offset+0x0c,streamFile); block_size = (uint16_t)read_16bitLE(fmt_offset+0x0c,sf);
/* 0x08: average bytes, 0x0e: bps, etc */ /* 0x08: average bytes, 0x0e: bps, etc */
/* autodetect Jade "v2", uses a different interleave [Rayman Raving Rabbids (PS2/Wii)] */ /* autodetect Jade "v2", uses a different interleave [Rayman Raving Rabbids (PS2/Wii)] */
@ -70,10 +72,10 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
/* half interleave check as there is no flag (ends with the PS-ADPCM stop frame) */ /* half interleave check as there is no flag (ends with the PS-ADPCM stop frame) */
for (i = 0; i < channel_count; i++) { for (i = 0; i < channel_count; i++) {
off_t end_frame = data_offset + (data_size / channel_count) * (i+1) - 0x10; off_t end_frame = data_offset + (data_size / channel_count) * (i+1) - 0x10;
if (read_32bitBE(end_frame+0x00,streamFile) != 0x07007777 || if (read_32bitBE(end_frame+0x00,sf) != 0x07007777 ||
read_32bitBE(end_frame+0x04,streamFile) != 0x77777777 || read_32bitBE(end_frame+0x04,sf) != 0x77777777 ||
read_32bitBE(end_frame+0x08,streamFile) != 0x77777777 || read_32bitBE(end_frame+0x08,sf) != 0x77777777 ||
read_32bitBE(end_frame+0x0c,streamFile) != 0x77777777) { read_32bitBE(end_frame+0x0c,sf) != 0x77777777) {
is_jade_v2 = 1; is_jade_v2 = 1;
break; break;
} }
@ -82,12 +84,15 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
} }
case 0xFFFE: /* GC/Wii */ case 0xFFFE: /* GC/Wii */
is_jade_v2 = (read_16bitLE(fmt_offset+0x10,streamFile) == 0); /* extra data size (0x2e*channels) */ is_jade_v2 = (read_16bitLE(fmt_offset+0x10,sf) == 0); /* extra data size (0x2e*channels) */
break;
default:
break; break;
} }
/* hopefully catches PC Rabbids */ /* hopefully catches PC Rabbids */
if (find_chunk(streamFile, 0x63756520,first_offset,0, NULL,NULL, 0, 0)) { /* "cue " */ if (find_chunk(sf, 0x63756520,first_offset,0, NULL,NULL, 0, 0)) { /* "cue " */
is_jade_v2 = 1; is_jade_v2 = 1;
} }
} }
@ -95,13 +100,13 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
/* get loop points */ /* get loop points */
if (is_jade_v2) { if (is_jade_v2) {
loop_flag = get_loop_points(streamFile, &loop_start, &loop_end); /* loops in "LIST" */ loop_flag = get_loop_points(sf, &loop_start, &loop_end); /* loops in "LIST" */
} }
else { else {
/* BG&E files don't contain looping information, so the looping is done by extension. /* BG&E files don't contain looping information, so the looping is done by extension.
* wam and waa contain ambient sounds and music, so often they contain looped music. * wam and waa contain ambient sounds and music, so often they contain looped music.
* Later, if the file is too short looping will be disabled. */ * Later, if the file is too short looping will be disabled. */
loop_flag = check_extensions(streamFile,"waa,wam"); loop_flag = check_extensions(sf,"waa,wam");
} }
start_offset = data_offset; start_offset = data_offset;
@ -197,8 +202,8 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
/* has extra 0x2e coefs before each channel, not counted in data_size */ /* has extra 0x2e coefs before each channel, not counted in data_size */
vgmstream->interleave_block_size = (data_size + 0x2e*channel_count) / channel_count; vgmstream->interleave_block_size = (data_size + 0x2e*channel_count) / channel_count;
dsp_read_coefs_be(vgmstream, streamFile, start_offset+0x00, vgmstream->interleave_block_size); dsp_read_coefs_be(vgmstream, sf, start_offset+0x00, vgmstream->interleave_block_size);
dsp_read_hist_be (vgmstream, streamFile, start_offset+0x20, vgmstream->interleave_block_size); dsp_read_hist_be (vgmstream, sf, start_offset+0x20, vgmstream->interleave_block_size);
start_offset += 0x2e; start_offset += 0x2e;
} }
break; break;
@ -227,10 +232,10 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
if (block_size != 0x02*channel_count) goto fail; if (block_size != 0x02*channel_count) goto fail;
/* a MSF (usually ATRAC3) masquerading as PCM */ /* a MSF (usually ATRAC3) masquerading as PCM */
if (read_32bitBE(start_offset, streamFile) != 0x4D534643) /* "MSF\43" */ if (read_32bitBE(start_offset, sf) != 0x4D534643) /* "MSF\43" */
goto fail; goto fail;
temp_sf = setup_subfile_streamfile(streamFile, start_offset, data_size, "msf"); temp_sf = setup_subfile_streamfile(sf, start_offset, data_size, "msf");
if (!temp_sf) goto fail; if (!temp_sf) goto fail;
temp_vgmstream = init_vgmstream_msf(temp_sf); temp_vgmstream = init_vgmstream_msf(temp_sf);
@ -255,7 +260,7 @@ VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE *streamFile) {
} }
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) if (!vgmstream_open_stream(vgmstream, sf,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -265,7 +270,7 @@ fail:
} }
/* extract loops from "cue /LIST", returns if loops (info from Droolie) */ /* extract loops from "cue /LIST", returns if loops (info from Droolie) */
static int get_loop_points(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end) { static int get_loop_points(STREAMFILE *sf, int *out_loop_start, int *out_loop_end) {
off_t cue_offset, list_offset; off_t cue_offset, list_offset;
size_t cue_size, list_size; size_t cue_size, list_size;
off_t offset, first_offset = 0x0c; off_t offset, first_offset = 0x0c;
@ -273,26 +278,26 @@ static int get_loop_points(STREAMFILE *streamFile, int *out_loop_start, int *out
/* unlooped files may contain LIST, but also may not */ /* unlooped files may contain LIST, but also may not */
if (!find_chunk(streamFile, 0x63756520,first_offset,0, &cue_offset,&cue_size, 0, 0)) /* "cue " */ if (!find_chunk(sf, 0x63756520,first_offset,0, &cue_offset,&cue_size, 0, 0)) /* "cue " */
goto fail; goto fail;
if (!find_chunk(streamFile, 0x4C495354,first_offset,0, &list_offset,&list_size, 0, 0)) /* "LIST" */ if (!find_chunk(sf, 0x4C495354,first_offset,0, &list_offset,&list_size, 0, 0)) /* "LIST" */
goto fail; goto fail;
offset = list_offset + 0x04; offset = list_offset + 0x04;
while (offset < list_offset + list_size) { while (offset < list_offset + list_size) {
uint32_t chunk_id = read_32bitBE(offset+0x00, streamFile); uint32_t chunk_id = read_32bitBE(offset+0x00, sf);
uint32_t chunk_size = read_32bitLE(offset+0x04, streamFile); uint32_t chunk_size = read_32bitLE(offset+0x04, sf);
offset += 0x08; offset += 0x08;
switch(chunk_id) { switch(chunk_id) {
case 0x6C61626C: /* "labl" */ case 0x6C61626C: /* "labl" */
if (read_32bitBE(offset+0x04, streamFile) == 0x6C6F6F70) /* "loop", actually an string tho */ if (read_32bitBE(offset+0x04, sf) == 0x6C6F6F70) /* "loop", actually an string tho */
loop_id = read_32bitLE(offset+0x00, streamFile); loop_id = read_32bitLE(offset+0x00, sf);
chunk_size += (chunk_size % 2) ? 1 : 0; /* string is even-padded after size */ chunk_size += (chunk_size % 2) ? 1 : 0; /* string is even-padded after size */
break; break;
case 0x6C747874: /* "ltxt" */ case 0x6C747874: /* "ltxt" */
if (loop_id == read_32bitLE(offset+0x00, streamFile)) if (loop_id == read_32bitLE(offset+0x00, sf))
loop_end = read_32bitLE(offset+0x04, streamFile); loop_end = read_32bitLE(offset+0x04, sf);
break; break;
default: default:
@ -306,10 +311,10 @@ static int get_loop_points(STREAMFILE *streamFile, int *out_loop_start, int *out
if (!loop_end) if (!loop_end)
return 0; return 0;
cue_count = read_32bitLE(cue_offset+0x00, streamFile); cue_count = read_32bitLE(cue_offset+0x00, sf);
for (i = 0; i < cue_count; i++) { for (i = 0; i < cue_count; i++) {
if (loop_id == read_32bitLE(cue_offset+0x04 + i*0x18 + 0x00, streamFile)) { if (loop_id == read_32bitLE(cue_offset+0x04 + i*0x18 + 0x00, sf)) {
loop_start = read_32bitLE(cue_offset+0x04 + i*0x18 + 0x04, streamFile); loop_start = read_32bitLE(cue_offset+0x04 + i*0x18 + 0x04, sf);
loop_end += loop_start; loop_end += loop_start;
break; break;
} }
@ -325,9 +330,9 @@ fail:
/* Jade RIFF in containers */ /* Jade RIFF in containers */
VGMSTREAM * init_vgmstream_ubi_jade_container(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_ubi_jade_container(STREAMFILE* sf) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM *vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL; STREAMFILE *temp_sf = NULL;
off_t subfile_offset; off_t subfile_offset;
size_t subfile_size; size_t subfile_size;
@ -336,22 +341,22 @@ VGMSTREAM * init_vgmstream_ubi_jade_container(STREAMFILE *streamFile) {
/* checks */ /* checks */
/* standard Jade exts + .xma for padded XMA used in Beyond Good & Evil HD (X360) */ /* standard Jade exts + .xma for padded XMA used in Beyond Good & Evil HD (X360) */
if (!check_extensions(streamFile,"waa,wac,wad,wam,wav,lwav,xma")) if (!check_extensions(sf,"waa,wac,wad,wam,wav,lwav,xma"))
goto fail; goto fail;
if (read_32bitBE(0x04,streamFile) == 0x52494646 && if (read_32bitBE(0x04,sf) == 0x52494646 &&
read_32bitLE(0x00,streamFile)+0x04 == get_streamfile_size(streamFile)) { read_32bitLE(0x00,sf)+0x04 == get_streamfile_size(sf)) {
/* data size + RIFF + padding */ /* data size + RIFF + padding */
subfile_offset = 0x04; subfile_offset = 0x04;
} }
else if (read_32bitBE(0x00,streamFile) == 0x52494646 && else if (read_32bitBE(0x00,sf) == 0x52494646 &&
read_32bitLE(0x04,streamFile)+0x04+0x04 < get_streamfile_size(streamFile) && read_32bitLE(0x04,sf)+0x04+0x04 < get_streamfile_size(sf) &&
(get_streamfile_size(streamFile) + 0x04) % 0x800 == 0) { (get_streamfile_size(sf) + 0x04) % 0x800 == 0) {
/* RIFF + padding with data size removed (bad extraction) */ /* RIFF + padding with data size removed (bad extraction) */
subfile_offset = 0x00; subfile_offset = 0x00;
} }
else if (read_32bitBE(0x04,streamFile) == 0x52494646 && else if (read_32bitBE(0x04,sf) == 0x52494646 &&
read_32bitLE(0x00,streamFile) == get_streamfile_size(streamFile)) { read_32bitLE(0x00,sf) == get_streamfile_size(sf)) {
/* data_size + RIFF + padding - 0x04 (bad extraction) */ /* data_size + RIFF + padding - 0x04 (bad extraction) */
subfile_offset = 0x04; subfile_offset = 0x04;
} }
@ -359,22 +364,22 @@ VGMSTREAM * init_vgmstream_ubi_jade_container(STREAMFILE *streamFile) {
goto fail; goto fail;
} }
subfile_size = read_32bitLE(subfile_offset+0x04,streamFile) + 0x04+0x04; subfile_size = read_32bitLE(subfile_offset+0x04,sf) + 0x04+0x04;
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL);
if (!temp_streamFile) goto fail; if (!temp_sf) goto fail;
if (check_extensions(streamFile,"xma")) { if (check_extensions(sf,"xma")) {
vgmstream = init_vgmstream_xma(temp_streamFile); vgmstream = init_vgmstream_xma(temp_sf);
} else { } else {
vgmstream = init_vgmstream_ubi_jade(temp_streamFile); vgmstream = init_vgmstream_ubi_jade(temp_sf);
} }
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
return vgmstream; return vgmstream;
fail: fail:
close_streamfile(temp_streamFile); close_streamfile(temp_sf);
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -207,7 +207,7 @@ static int parse_dat_header(ubi_sb_header *sb, STREAMFILE *sf);
static int parse_header(ubi_sb_header* sb, STREAMFILE* sf, off_t offset, int index); static int parse_header(ubi_sb_header* sb, STREAMFILE* sf, off_t offset, int index);
static int parse_sb(ubi_sb_header* sb, STREAMFILE* sf, int target_subsong); static int parse_sb(ubi_sb_header* sb, STREAMFILE* sf, int target_subsong);
static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf_index, STREAMFILE* sf); static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf_index, STREAMFILE* sf);
static VGMSTREAM *init_vgmstream_ubi_sb_silence(ubi_sb_header *sb, STREAMFILE *sf_index, STREAMFILE *sf); static VGMSTREAM *init_vgmstream_ubi_sb_silence(ubi_sb_header *sb);
static int config_sb_platform(ubi_sb_header* sb, STREAMFILE* sf); static int config_sb_platform(ubi_sb_header* sb, STREAMFILE* sf);
static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf); static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf);
@ -542,7 +542,7 @@ static int parse_ubi_bank_header(ubi_sb_header *sb, ubi_sb_header *sb_other, STR
return 0; return 0;
} }
static void get_ubi_bank_name(ubi_sb_header *sb, STREAMFILE *sf, int bank_number, char *bank_name) { static void get_ubi_bank_name(ubi_sb_header *sb, int bank_number, char *bank_name) {
if (sb->is_bnm) { if (sb->is_bnm) {
sprintf(bank_name, "Bnk_%d.bnm", bank_number); sprintf(bank_name, "Bnk_%d.bnm", bank_number);
} else if (sb->is_dat) { } else if (sb->is_dat) {
@ -559,7 +559,7 @@ static int is_other_bank(ubi_sb_header *sb, STREAMFILE *sf, int bank_number) {
char bank_name[255]; char bank_name[255];
get_streamfile_filename(sf, current_name, PATH_LIMIT); get_streamfile_filename(sf, current_name, PATH_LIMIT);
get_ubi_bank_name(sb, sf, bank_number, bank_name); get_ubi_bank_name(sb, bank_number, bank_name);
return strcmp(current_name, bank_name) != 0; return strcmp(current_name, bank_name) != 0;
} }
@ -647,7 +647,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_
VGM_LOG("UBI DAT: external stream '%s' not found\n", sb->resource_name); VGM_LOG("UBI DAT: external stream '%s' not found\n", sb->resource_name);
strncat(sb->readable_name, " (missing)", sizeof(sb->readable_name)); strncat(sb->readable_name, " (missing)", sizeof(sb->readable_name));
sb->duration = (float)pcm_bytes_to_samples(sb->stream_size, sb->channels, 16) / (float)sb->sample_rate; sb->duration = (float)pcm_bytes_to_samples(sb->stream_size, sb->channels, 16) / (float)sb->sample_rate;
return init_vgmstream_ubi_sb_silence(sb, sf_index, sf); return init_vgmstream_ubi_sb_silence(sb);
} }
} }
@ -1438,7 +1438,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_sequence(ubi_sb_header* sb, STREAMFILE*
if (sf_bank != sf_index) if (sf_bank != sf_index)
close_streamfile(sf_bank); close_streamfile(sf_bank);
get_ubi_bank_name(sb, sf, sb->sequence_banks[i], bank_name); get_ubi_bank_name(sb, sb->sequence_banks[i], bank_name);
sf_bank = open_streamfile_by_filename(sf, bank_name); sf_bank = open_streamfile_by_filename(sf, bank_name);
/* may be worth trying in localized folder? */ /* may be worth trying in localized folder? */
@ -1529,7 +1529,7 @@ fail:
} }
static VGMSTREAM* init_vgmstream_ubi_sb_silence(ubi_sb_header* sb, STREAMFILE* sf_index, STREAMFILE* sf) { static VGMSTREAM* init_vgmstream_ubi_sb_silence(ubi_sb_header* sb) {
VGMSTREAM* vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
int channels, sample_rate; int channels, sample_rate;
int32_t num_samples; int32_t num_samples;
@ -1585,7 +1585,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf
break; break;
case UBI_SILENCE: case UBI_SILENCE:
vgmstream = init_vgmstream_ubi_sb_silence(sb, sf_index, sf); vgmstream = init_vgmstream_ubi_sb_silence(sb);
break; break;
case UBI_NONE: case UBI_NONE:

View File

@ -3,33 +3,33 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* .VS - from Melbourne House games [Men in Black II (PS2), Grand Prix Challenge (PS2) */ /* .VS - from Melbourne House games [Men in Black II (PS2), Grand Prix Challenge (PS2) */
VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_vs(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count; int loop_flag, channels;
/* checks */ /* checks */
if (!check_extensions(streamFile, "vs")) if (!check_extensions(sf, "vs"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0xC8000000) if (read_u32be(0x00,sf) != 0xC8000000)
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
channel_count = 2; channels = 2;
start_offset = 0x08; start_offset = 0x08;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_VS; vgmstream->meta_type = meta_VS;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile); vgmstream->sample_rate = read_s32le(0x04,sf);
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_blocked_vs; vgmstream->layout_type = layout_blocked_vs;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
/* calc num_samples */ /* calc num_samples */
@ -39,7 +39,7 @@ VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile) {
block_update(vgmstream->next_block_offset,vgmstream); block_update(vgmstream->next_block_offset,vgmstream);
vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1);
} }
while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); while (vgmstream->next_block_offset < get_streamfile_size(sf));
block_update(start_offset, vgmstream); block_update(start_offset, vgmstream);
} }

View File

@ -3,7 +3,7 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* .vs/STRx - from The Bouncer (PS2) */ /* .vs/STRx - from The Bouncer (PS2) */
VGMSTREAM * init_vgmstream_vs_str(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_vs_str(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
int channel_count, loop_flag; int channel_count, loop_flag;
off_t start_offset; off_t start_offset;
@ -12,17 +12,17 @@ VGMSTREAM * init_vgmstream_vs_str(STREAMFILE *streamFile) {
/* checks */ /* checks */
/* .vs: real extension (from .nam container) /* .vs: real extension (from .nam container)
* .str: fake, partial header id */ * .str: fake, partial header id */
if (!check_extensions(streamFile, "vs,str")) if (!check_extensions(sf, "vs,str"))
goto fail; goto fail;
if (!(read_32bitBE(0x000,streamFile) == 0x5354524C && /* "STRL" */ if (!(read_32bitBE(0x000,sf) == 0x5354524C && /* "STRL" */
read_32bitBE(0x800,streamFile) == 0x53545252) && /* "STRR" */ read_32bitBE(0x800,sf) == 0x53545252) && /* "STRR" */
read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */ read_32bitBE(0x00,sf) != 0x5354524D) /* "STRM" */
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
channel_count = (read_32bitBE(0x00,streamFile) == 0x5354524D) ? 1 : 2; /* "STRM"=mono (voices) */ channel_count = (read_32bitBE(0x00,sf) == 0x5354524D) ? 1 : 2; /* "STRM"=mono (voices) */
start_offset = 0x00; start_offset = 0x00;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
@ -34,7 +34,7 @@ VGMSTREAM * init_vgmstream_vs_str(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_blocked_vs_str; vgmstream->layout_type = layout_blocked_vs_str;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail; goto fail;
/* calc num_samples */ /* calc num_samples */
@ -44,7 +44,7 @@ VGMSTREAM * init_vgmstream_vs_str(STREAMFILE *streamFile) {
block_update(vgmstream->next_block_offset,vgmstream); block_update(vgmstream->next_block_offset,vgmstream);
vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1);
} }
while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); while (vgmstream->next_block_offset < get_streamfile_size(sf));
block_update(start_offset, vgmstream); block_update(start_offset, vgmstream);
} }

View File

@ -2,42 +2,43 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* WAF - KID's earlier PC games [ever17 (PC)] (for RLE-compressed WAFs see https://github.com/dsp2003/e17p) */ /* WAF - KID's earlier PC games [ever17 (PC)] (for RLE-compressed WAFs see https://github.com/dsp2003/e17p) */
VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_waf(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count; int loop_flag, channels;
/* checks */ /* checks */
if (!check_extensions(streamFile, "waf")) if (!check_extensions(sf, "waf"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x57414600) /* "WAF\0" */ if (!is_id32be(0x00,sf, "WAF\0"))
goto fail; goto fail;
if (read_32bitLE(0x34,streamFile) + 0x38 != get_streamfile_size(streamFile)) if (read_u32le(0x34,sf) + 0x38 != get_streamfile_size(sf))
goto fail; goto fail;
channel_count = read_16bitLE(0x06,streamFile); channels = read_u16le(0x06,sf);
loop_flag = 0; loop_flag = 0;
start_offset = 0x38; start_offset = 0x38;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_WAF; vgmstream->meta_type = meta_WAF;
vgmstream->sample_rate = read_32bitLE(0x08, streamFile); vgmstream->sample_rate = read_s32le(0x08, sf);
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->frame_size = read_16bitLE(0x10, streamFile); vgmstream->frame_size = read_u16le(0x10, sf);
/* 0x04: null?, 0x0c: avg br, 0x12: bps, 0x14: s_p_f, 0x16~34: coefs (a modified RIFF fmt) */ /* 0x04: null?, 0x0c: avg br, 0x12: bps, 0x14: s_p_f, 0x16~34: coefs (a modified RIFF fmt) */
if (!msadpcm_check_coefs(streamFile, 0x16)) if (!msadpcm_check_coefs(sf, 0x16))
goto fail; goto fail;
vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bitLE(0x34,streamFile), vgmstream->frame_size, channel_count); vgmstream->num_samples = msadpcm_bytes_to_samples(read_u32le(0x34,sf), vgmstream->frame_size, channels);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -5,7 +5,7 @@
#define MAX_SEGMENTS 4 #define MAX_SEGMENTS 4
/* .WAVE - "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC/3DS), TMNT: Danger of the Ooze (PS3/3DS)] */ /* .WAVE - "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC/3DS), TMNT: Danger of the Ooze (PS3/3DS)] */
VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t segments_offset; off_t segments_offset;
int loop_flag = 0, channel_count, sample_rate; int loop_flag = 0, channel_count, sample_rate;
@ -20,17 +20,17 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
/* checks */ /* checks */
if (!check_extensions(streamFile, "wave")) if (!check_extensions(sf, "wave"))
goto fail; goto fail;
if (read_32bitLE(0x00,streamFile) != 0x4DF72D4A && /* header id */ if (read_32bitLE(0x00,sf) != 0x4DF72D4A && /* header id */
read_32bitBE(0x00,streamFile) != 0x4DF72D4A) read_32bitBE(0x00,sf) != 0x4DF72D4A)
goto fail; goto fail;
if (read_8bit(0x04,streamFile) != 0x01) /* version? */ if (read_8bit(0x04,sf) != 0x01) /* version? */
goto fail; goto fail;
/* PS3/X360 games */ /* PS3/X360 games */
big_endian = read_32bitBE(0x00,streamFile) == 0x4DF72D4A; big_endian = read_32bitBE(0x00,sf) == 0x4DF72D4A;
if (big_endian) { if (big_endian) {
read_32bit = read_32bitBE; read_32bit = read_32bitBE;
read_16bit = read_16bitBE; read_16bit = read_16bitBE;
@ -39,16 +39,16 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
read_16bit = read_16bitLE; read_16bit = read_16bitLE;
} }
channel_count = read_8bit(0x05,streamFile); channel_count = read_8bit(0x05,sf);
segment_count = read_16bit(0x06,streamFile); segment_count = read_16bit(0x06,sf);
if (segment_count > MAX_SEGMENTS || segment_count <= 0) goto fail; if (segment_count > MAX_SEGMENTS || segment_count <= 0) goto fail;
loop_start_segment = read_16bit(0x08, streamFile); loop_start_segment = read_16bit(0x08, sf);
loop_end_segment = read_16bit(0x0a, streamFile); loop_end_segment = read_16bit(0x0a, sf);
segments_offset = read_32bit(0x0c, streamFile); segments_offset = read_32bit(0x0c, sf);
sample_rate = read_32bit(0x10, streamFile); sample_rate = read_32bit(0x10, sf);
num_samples = read_32bit(0x14, streamFile); num_samples = read_32bit(0x14, sf);
/* 0x18: unknown (usually 0, maybe some count) */ /* 0x18: unknown (usually 0, maybe some count) */
@ -67,17 +67,17 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
/* open each segment subfile */ /* open each segment subfile */
for (i = 0; i < segment_count; i++) { for (i = 0; i < segment_count; i++) {
codec = read_8bit(segments_offset+0x10*i+0x00, streamFile); codec = read_8bit(segments_offset+0x10*i+0x00, sf);
/* 0x01(1): unknown (flag? usually 0x00/0x01/0x02) */ /* 0x01(1): unknown (flag? usually 0x00/0x01/0x02) */
if (read_8bit(segments_offset+0x10*i+0x02, streamFile) != 0x01) goto fail; /* unknown */ if (read_8bit(segments_offset+0x10*i+0x02, sf) != 0x01) goto fail; /* unknown */
if (read_8bit(segments_offset+0x10*i+0x03, streamFile) != 0x00) goto fail; /* unknown */ if (read_8bit(segments_offset+0x10*i+0x03, sf) != 0x00) goto fail; /* unknown */
segment_samples = read_32bit(segments_offset+0x10*i+0x04, streamFile); segment_samples = read_32bit(segments_offset+0x10*i+0x04, sf);
extradata_offset = read_32bit(segments_offset+0x10*i+0x08, streamFile); extradata_offset = read_32bit(segments_offset+0x10*i+0x08, sf);
table_offset = read_32bit(segments_offset+0x10*i+0x0c, streamFile); table_offset = read_32bit(segments_offset+0x10*i+0x0c, sf);
/* create a sub-VGMSTREAM per segment /* create a sub-VGMSTREAM per segment
* (we'll reopen this streamFile as needed, so each sub-VGMSTREAM is fully independent) */ * (we'll reopen this sf as needed, so each sub-VGMSTREAM is fully independent) */
switch(codec) { switch(codec) {
case 0x02: { /* "adpcm" */ case 0x02: { /* "adpcm" */
data->segments[i] = allocate_vgmstream(channel_count, 0); data->segments[i] = allocate_vgmstream(channel_count, 0);
@ -89,18 +89,18 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
data->segments[i]->layout_type = layout_none; data->segments[i]->layout_type = layout_none;
data->segments[i]->num_samples = segment_samples; data->segments[i]->num_samples = segment_samples;
if (!vgmstream_open_stream(data->segments[i],streamFile,0x00)) if (!vgmstream_open_stream(data->segments[i],sf,0x00))
goto fail; goto fail;
/* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */ /* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */
for (ch = 0; ch < channel_count; ch++) { for (ch = 0; ch < channel_count; ch++) {
segment_offset = read_32bit(table_offset + 0x04*ch, streamFile); segment_offset = read_32bit(table_offset + 0x04*ch, sf);
data->segments[i]->ch[ch].channel_start_offset = data->segments[i]->ch[ch].channel_start_offset =
data->segments[i]->ch[ch].offset = segment_offset; data->segments[i]->ch[ch].offset = segment_offset;
/* ADPCM setup */ /* ADPCM setup */
data->segments[i]->ch[ch].adpcm_history1_32 = read_16bit(extradata_offset+0x04*ch+0x00, streamFile); data->segments[i]->ch[ch].adpcm_history1_32 = read_16bit(extradata_offset+0x04*ch+0x00, sf);
data->segments[i]->ch[ch].adpcm_step_index = read_8bit(extradata_offset+0x04*ch+0x02, streamFile); data->segments[i]->ch[ch].adpcm_step_index = read_8bit(extradata_offset+0x04*ch+0x02, sf);
/* 0x03: reserved */ /* 0x03: reserved */
} }
@ -117,19 +117,19 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
data->segments[i]->layout_type = layout_none; data->segments[i]->layout_type = layout_none;
data->segments[i]->num_samples = segment_samples; data->segments[i]->num_samples = segment_samples;
if (!vgmstream_open_stream(data->segments[i],streamFile,0x00)) if (!vgmstream_open_stream(data->segments[i],sf,0x00))
goto fail; goto fail;
/* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */ /* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */
for (ch = 0; ch < channel_count; ch++) { for (ch = 0; ch < channel_count; ch++) {
segment_offset = read_32bit(table_offset + 0x04*ch, streamFile); segment_offset = read_32bit(table_offset + 0x04*ch, sf);
data->segments[i]->ch[ch].channel_start_offset = data->segments[i]->ch[ch].channel_start_offset =
data->segments[i]->ch[ch].offset = segment_offset; data->segments[i]->ch[ch].offset = segment_offset;
} }
/* ADPCM setup: 0x06 initial ps/hist1/hist2 (per channel) + 0x20 coefs (per channel) */ /* ADPCM setup: 0x06 initial ps/hist1/hist2 (per channel) + 0x20 coefs (per channel) */
dsp_read_hist(data->segments[i], streamFile, extradata_offset+0x02, 0x06, big_endian); dsp_read_hist(data->segments[i], sf, extradata_offset+0x02, 0x06, big_endian);
dsp_read_coefs(data->segments[i], streamFile, extradata_offset+0x06*channel_count+0x00, 0x20, big_endian); dsp_read_coefs(data->segments[i], sf, extradata_offset+0x06*channel_count+0x00, 0x20, big_endian);
break; break;
} }
@ -138,13 +138,13 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
case 0x04: { /* "vorbis" */ case 0x04: { /* "vorbis" */
ogg_vorbis_meta_info_t ovmi = {0}; ogg_vorbis_meta_info_t ovmi = {0};
segment_offset = read_32bit(table_offset, streamFile); segment_offset = read_32bit(table_offset, sf);
segment_size = read_32bitBE(segment_offset, streamFile); /* always BE */ segment_size = read_32bitBE(segment_offset, sf); /* always BE */
ovmi.meta_type = meta_WAVE; ovmi.meta_type = meta_WAVE;
ovmi.stream_size = segment_size; ovmi.stream_size = segment_size;
data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, segment_offset+0x04, &ovmi); data->segments[i] = init_vgmstream_ogg_vorbis_config(sf, segment_offset+0x04, &ovmi);
if (!data->segments[i]) goto fail; if (!data->segments[i]) goto fail;
if (data->segments[i]->num_samples != segment_samples) { if (data->segments[i]->num_samples != segment_samples) {
@ -204,7 +204,7 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = loop_end_sample; vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_WAVE_segmented; vgmstream->meta_type = meta_WAVE_segmented;
vgmstream->stream_size = get_streamfile_size(streamFile); /* wrong kbps otherwise */ vgmstream->stream_size = get_streamfile_size(sf); /* wrong kbps otherwise */
/* .wave can mix codecs, usually first segment is a small ADPCM section) */ /* .wave can mix codecs, usually first segment is a small ADPCM section) */
vgmstream->coding_type = (segment_count == 1 ? data->segments[0]->coding_type : data->segments[1]->coding_type); vgmstream->coding_type = (segment_count == 1 ? data->segments[0]->coding_type : data->segments[1]->coding_type);

View File

@ -2,25 +2,25 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* WBAT - Firebrand Games header [Need for Speed: The Run (3DS), Fast & Furious: Showdown (3DS)] */ /* WBAT - Firebrand Games header [Need for Speed: The Run (3DS), Fast & Furious: Showdown (3DS)] */
VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, name_offset, offset, stream_offset; off_t start_offset, name_offset, offset, stream_offset;
size_t names_size, stream_size; size_t names_size, stream_size;
int loop_flag, channel_count, sample_rate, num_samples; int loop_flag, channel_count, sample_rate, num_samples;
int big_endian, version, codec; int big_endian, version, codec;
int total_subsongs, target_subsong = streamFile->stream_index; int total_subsongs, target_subsong = sf->stream_index;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* checks */ /* checks */
if (!check_extensions(streamFile, "wavebatch")) if (!check_extensions(sf, "wavebatch"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x54414257) /* "TABW" */ if (!is_id32be(0x00,sf, "TABW"))
goto fail; goto fail;
/* section0: base header */ /* section0: base header */
big_endian = ((uint16_t)read_16bitBE(0x04,streamFile) == 0xFEFF); /* BOM (always LE on 3DS/Android) */ big_endian = (read_u16be(0x04,sf) == 0xFEFF); /* BOM (always LE on 3DS/Android) */
if (big_endian) { if (big_endian) {
read_32bit = read_32bitBE; read_32bit = read_32bitBE;
read_16bit = read_16bitBE; read_16bit = read_16bitBE;
@ -30,15 +30,15 @@ VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) {
} }
version = read_16bit(0x06, streamFile); /* assumed */ version = read_16bit(0x06, sf); /* assumed */
if (version != 0x06 && version != 0x07) /* v6 = NFS: The Run , v7 = F&F Showndown */ if (version != 0x06 && version != 0x07) /* v6 = NFS: The Run , v7 = F&F Showndown */
goto fail; goto fail;
total_subsongs = read_32bit(0x08,streamFile); total_subsongs = read_32bit(0x08,sf);
if (target_subsong == 0) target_subsong = 1; if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
names_size = read_32bit(0x0c,streamFile); names_size = read_32bit(0x0c,sf);
/* 0x10/14: see below */ /* 0x10/14: see below */
/* 0x18: data size (all subsongs) */ /* 0x18: data size (all subsongs) */
offset = 0x1c + names_size; /* skip names table */ offset = 0x1c + names_size; /* skip names table */
@ -47,14 +47,14 @@ VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) {
/* section1: unknown */ /* section1: unknown */
{ {
size_t unknown_size = read_32bit(0x10,streamFile); size_t unknown_size = read_32bit(0x10,sf);
/* 0x00: usually 0, rarely 0x20? */ /* 0x00: usually 0, rarely 0x20? */
offset += unknown_size*0x04; offset += unknown_size*0x04;
} }
/* section2: samples */ /* section2: samples */
{ {
size_t samples_size = read_32bit(0x14,streamFile); size_t samples_size = read_32bit(0x14,sf);
/* 0x00: num_samples */ /* 0x00: num_samples */
offset += samples_size*0x04; offset += samples_size*0x04;
} }
@ -63,15 +63,15 @@ VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) {
{ {
off_t header_offset = offset+(target_subsong-1)*0x24; off_t header_offset = offset+(target_subsong-1)*0x24;
name_offset = read_32bit(header_offset+0x00, streamFile) + 0x1c; /* within name table */ name_offset = read_32bit(header_offset+0x00, sf) + 0x1c; /* within name table */
codec = read_32bit(header_offset+0x04, streamFile); codec = read_32bit(header_offset+0x04, sf);
sample_rate = read_32bit(header_offset+0x08, streamFile); sample_rate = read_32bit(header_offset+0x08, sf);
channel_count = read_32bit(header_offset+0x0c, streamFile); channel_count = read_32bit(header_offset+0x0c, sf);
/* 0x10: index within section1/2? */ /* 0x10: index within section1/2? */
/* 0x14: flags? 0x01 or (rarely) 0x02 */ /* 0x14: flags? 0x01 or (rarely) 0x02 */
stream_offset = read_32bit(header_offset+0x18, streamFile); stream_offset = read_32bit(header_offset+0x18, sf);
stream_size = read_32bit(header_offset+0x1c, streamFile); /* including DSP config */ stream_size = read_32bit(header_offset+0x1c, sf); /* including DSP config */
num_samples = read_32bit(header_offset+0x20, streamFile) / channel_count; /* nibble/PCMs */ num_samples = read_32bit(header_offset+0x20, sf) / channel_count; /* nibble/PCMs */
offset += total_subsongs*0x24; offset += total_subsongs*0x24;
} }
@ -111,8 +111,8 @@ VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = (stream_size - config_size) / channel_count; /* full interleave*/; vgmstream->interleave_block_size = (stream_size - config_size) / channel_count; /* full interleave*/;
dsp_read_coefs(vgmstream,streamFile,start_offset+0x00,0x20+0x14,big_endian); dsp_read_coefs(vgmstream,sf,start_offset+0x00,0x20+0x14,big_endian);
dsp_read_hist (vgmstream,streamFile,start_offset+0x20,0x14+0x20,big_endian); dsp_read_hist (vgmstream,sf,start_offset+0x20,0x14+0x20,big_endian);
start_offset += config_size; start_offset += config_size;
break; break;
@ -123,12 +123,9 @@ VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) {
goto fail; goto fail;
} }
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf); /* always null-terminated */
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamFile); /* always null-terminated */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -412,7 +412,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) {
vgmstream->num_samples = msd.num_samples; vgmstream->num_samples = msd.num_samples;
if (!vgmstream->num_samples) if (!vgmstream->num_samples)
vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; /* very wrong, from avg-br */ vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); /* very wrong, from avg-br */
//num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2 //num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2
} }
@ -433,7 +433,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) {
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); //todo correct?
break; break;
} }
@ -518,7 +518,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* FFmpeg's samples seem correct, otherwise see ogg_opus.c for getting samples. */ /* FFmpeg's samples seem correct, otherwise see ogg_opus.c for getting samples. */
vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; vgmstream->num_samples = ffmpeg_get_samples(vgmstream->codec_data);
break; break;
} }

View File

@ -62,10 +62,10 @@ VGMSTREAM* init_vgmstream_xnb(STREAMFILE* sf) {
char reader_name[255+1]; char reader_name[255+1];
size_t string_len; size_t string_len;
uint8_t type_count; uint8_t type_count;
const static char* type_sound = "Microsoft.Xna.Framework.Content.SoundEffectReader"; /* partial "fmt" chunk or XMA */ static const char* type_sound = "Microsoft.Xna.Framework.Content.SoundEffectReader"; /* partial "fmt" chunk or XMA */
const static char* type_ogg = "SoundEffectFromOggReader"; /* has extra text info after base part */ static const char* type_ogg = "SoundEffectFromOggReader"; /* has extra text info after base part */
const static char* type_song = "Microsoft.Xna.Framework.Content.SongReader"; /* references a companion .wma */ static const char* type_song = "Microsoft.Xna.Framework.Content.SongReader"; /* references a companion .wma */
const static char* type_int32 = "Microsoft.Xna.Framework.Content.Int32Reader"; /* extra crap */ static const char* type_int32 = "Microsoft.Xna.Framework.Content.Int32Reader"; /* extra crap */
type_count = read_u8(offset++, sf_h); type_count = read_u8(offset++, sf_h);

View File

@ -128,6 +128,9 @@ VGMSTREAM* init_vgmstream_xssb(STREAMFILE *sf) {
vgmstream->num_samples = xbox_ima_bytes_to_samples(h.stream_size, h.channels); vgmstream->num_samples = xbox_ima_bytes_to_samples(h.stream_size, h.channels);
break; break;
default:
goto fail;
} }
if (!vgmstream_open_stream(vgmstream, sf, h.stream_start)) if (!vgmstream_open_stream(vgmstream, sf, h.stream_start))

View File

@ -530,7 +530,7 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
/* no wma_bytes_to_samples, this should be ok */ /* no wma_bytes_to_samples, this should be ok */
if (!vgmstream->num_samples) if (!vgmstream->num_samples)
vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data);
break; break;
} }

View File

@ -71,7 +71,7 @@ VGMSTREAM * init_vgmstream_xwma(STREAMFILE *streamFile) {
vgmstream->num_samples = msd.num_samples; vgmstream->num_samples = msd.num_samples;
if (vgmstream->num_samples == 0) if (vgmstream->num_samples == 0)
vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; /* from avg-br */ vgmstream->num_samples = ffmpeg_get_samples(vgmstream->codec_data); /* from avg-br */
//num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2 //num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2
} }
} }

View File

@ -68,7 +68,7 @@ VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) {
vgmstream->num_samples = msd.num_samples; vgmstream->num_samples = msd.num_samples;
if (vgmstream->num_samples == 0) if (vgmstream->num_samples == 0)
vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; /* from avg-br */ vgmstream->num_samples = ffmpeg_get_samples(vgmstream->codec_data); /* from avg-br */
//num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2 //num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2
} }
} }

View File

@ -680,6 +680,7 @@ void mixing_push_fade(VGMSTREAM* vgmstream, int ch_dst, double vol_start, double
} }
else if (mix_prev->time_post < 0 || mix.time_pre < 0) { else if (mix_prev->time_post < 0 || mix.time_pre < 0) {
int is_prev = 1; int is_prev = 1;
/* test if prev is really cancelled by this */
if ((mix_prev->time_end > mix.time_start) || if ((mix_prev->time_end > mix.time_start) ||
(mix_prev->time_post >= 0 && mix_prev->time_post > mix.time_start) || (mix_prev->time_post >= 0 && mix_prev->time_post > mix.time_start) ||
(mix.time_pre >= 0 && mix.time_pre < mix_prev->time_end)) (mix.time_pre >= 0 && mix.time_pre < mix_prev->time_end))
@ -687,12 +688,12 @@ void mixing_push_fade(VGMSTREAM* vgmstream, int ch_dst, double vol_start, double
if (is_prev) { if (is_prev) {
/* change negative values to actual points */ /* change negative values to actual points */
if (mix_prev->time_post < 0 && mix_prev->time_post < 0) { if (mix_prev->time_post < 0 && mix.time_pre < 0) {
mix_prev->time_post = mix_prev->time_end; mix_prev->time_post = mix_prev->time_end;
mix.time_pre = mix_prev->time_post; mix.time_pre = mix_prev->time_post;
} }
if (mix_prev->time_post >= 0 && mix.time_pre < 0) {
if (mix_prev->time_post >= 0 && mix.time_pre < 0) {
mix.time_pre = mix_prev->time_post; mix.time_pre = mix_prev->time_post;
} }
else if (mix_prev->time_post < 0 && mix.time_pre >= 0) { else if (mix_prev->time_post < 0 && mix.time_pre >= 0) {

View File

@ -525,6 +525,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_dsp_kwa, init_vgmstream_dsp_kwa,
init_vgmstream_ogv_3rdeye, init_vgmstream_ogv_3rdeye,
init_vgmstream_sspr, init_vgmstream_sspr,
init_vgmstream_piff_tpcm,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
@ -606,9 +607,9 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
/* check FFmpeg streams here, for lack of a better place */ /* check FFmpeg streams here, for lack of a better place */
if (vgmstream->coding_type == coding_FFmpeg) { if (vgmstream->coding_type == coding_FFmpeg) {
ffmpeg_codec_data *data = vgmstream->codec_data; int ffmpeg_subsongs = ffmpeg_get_subsong_count(vgmstream->codec_data);
if (data && data->streamCount && !vgmstream->num_streams) { if (ffmpeg_subsongs && !vgmstream->num_streams) {
vgmstream->num_streams = data->streamCount; vgmstream->num_streams = ffmpeg_subsongs;
} }
} }
#endif #endif
@ -1464,8 +1465,22 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t*
} }
if (is_unique) { if (is_unique) {
size_t stream_size;
if (br->count >= br->count_max) goto fail; if (br->count >= br->count_max) goto fail;
if (vgmstream->stream_size) {
/* stream_size applies to both channels but should add once and detect repeats (for current subsong) */
stream_size = get_vgmstream_file_bitrate_from_size(vgmstream->stream_size, vgmstream->sample_rate, vgmstream->num_samples);
}
else {
stream_size = get_vgmstream_file_bitrate_from_streamfile(sf_cur, vgmstream->sample_rate, vgmstream->num_samples);
}
/* possible in cases like using silence codec */
if (!stream_size)
break;
br->hash[br->count] = hash_cur; br->hash[br->count] = hash_cur;
br->subsong[br->count] = subsong_cur; br->subsong[br->count] = subsong_cur;
@ -1473,13 +1488,7 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t*
if (p_uniques) if (p_uniques)
(*p_uniques)++; (*p_uniques)++;
if (vgmstream->stream_size) { bitrate += stream_size;
/* stream_size applies to both channels but should add once and detect repeats (for current subsong) */
bitrate += get_vgmstream_file_bitrate_from_size(vgmstream->stream_size, vgmstream->sample_rate, vgmstream->num_samples);
}
else {
bitrate += get_vgmstream_file_bitrate_from_streamfile(sf_cur, vgmstream->sample_rate, vgmstream->num_samples);
}
break; break;
} }

View File

@ -31,14 +31,6 @@ enum { VGMSTREAM_MAX_NUM_SAMPLES = 1000000000 }; /* no ~5h vgm hopefully */
//#define VGM_USE_SPEEX //#define VGM_USE_SPEEX
#ifdef VGM_USE_VORBIS
#include <vorbis/vorbisfile.h>
#endif
#ifdef VGM_USE_MPEG
#include <mpg123/mpg123.h>
#endif
#ifdef VGM_USE_MP4V2 #ifdef VGM_USE_MP4V2
#define MP4V2_NO_STDINT_DEFS #define MP4V2_NO_STDINT_DEFS
#include <mp4v2/mp4v2.h> #include <mp4v2/mp4v2.h>
@ -48,24 +40,12 @@ enum { VGMSTREAM_MAX_NUM_SAMPLES = 1000000000 }; /* no ~5h vgm hopefully */
#include <aacdecoder_lib.h> #include <aacdecoder_lib.h>
#endif #endif
#ifdef VGM_USE_MAIATRAC3PLUS
#include <maiatrac3plus.h>
#endif
#ifdef VGM_USE_FFMPEG
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#endif
#include "clHCA.h" #include "clHCA.h"
#ifdef BUILD_VGMSTREAM #ifdef BUILD_VGMSTREAM
#include "coding/g72x_state.h" #include "coding/g72x_state.h"
#include "coding/nwa_decoder.h"
#else #else
#include "g72x_state.h" #include "g72x_state.h"
#include "nwa_decoder.h"
#endif #endif
@ -175,6 +155,7 @@ typedef enum {
coding_ASF, /* Argonaut ASF 4-bit ADPCM */ coding_ASF, /* Argonaut ASF 4-bit ADPCM */
coding_DSA, /* Ocean DSA 4-bit ADPCM */ coding_DSA, /* Ocean DSA 4-bit ADPCM */
coding_XMD, /* Konami XMD 4-bit ADPCM */ coding_XMD, /* Konami XMD 4-bit ADPCM */
coding_TANTALUS, /* Tantalus 4-bit ADPCM */
coding_PCFX, /* PC-FX 4-bit ADPCM */ coding_PCFX, /* PC-FX 4-bit ADPCM */
coding_OKI16, /* OKI 4-bit ADPCM with 16-bit output and modified expand */ coding_OKI16, /* OKI 4-bit ADPCM with 16-bit output and modified expand */
coding_OKI4S, /* OKI 4-bit ADPCM with 16-bit output and cuadruple step */ coding_OKI4S, /* OKI 4-bit ADPCM with 16-bit output and cuadruple step */
@ -763,6 +744,7 @@ typedef enum {
meta_IDSP_TOSE, meta_IDSP_TOSE,
meta_DSP_KWA, meta_DSP_KWA,
meta_OGV_3RDEYE, meta_OGV_3RDEYE,
meta_PIFF_TPCM,
} meta_t; } meta_t;
/* standard WAVEFORMATEXTENSIBLE speaker positions */ /* standard WAVEFORMATEXTENSIBLE speaker positions */
@ -1047,63 +1029,6 @@ typedef struct {
} acm_codec_data; } acm_codec_data;
#ifdef VGM_USE_FFMPEG
typedef struct {
/*** IO internals ***/
STREAMFILE* streamfile;
uint64_t start; // absolute start within the streamfile
uint64_t offset; // absolute offset within the streamfile
uint64_t size; // max size within the streamfile
uint64_t logical_offset; // computed offset FFmpeg sees (including fake header)
uint64_t logical_size; // computed size FFmpeg sees (including fake header)
uint64_t header_size; // fake header (parseable by FFmpeg) prepended on reads
uint8_t* header_block; // fake header data (ie. RIFF)
/*** "public" API (read-only) ***/
// stream info
int channels;
int sampleRate;
int bitrate;
// extra info: 0 if unknown or not fixed
int64_t totalSamples; // estimated count (may not be accurate for some demuxers)
int64_t skipSamples; // number of start samples that will be skipped (encoder delay), for looping adjustments
int streamCount; // number of FFmpeg audio streams
/*** internal state ***/
// config
int channel_remap_set;
int channel_remap[32]; /* map of channel > new position */
int invert_floats_set;
int skip_samples_set; /* flag to know skip samples were manually added from vgmstream */
int force_seek; /* flags for special seeking in faulty formats */
int bad_init;
// FFmpeg context used for metadata
AVCodec *codec;
// FFmpeg decoder state
unsigned char *buffer;
AVIOContext *ioCtx;
int streamIndex;
AVFormatContext *formatCtx;
AVCodecContext *codecCtx;
AVFrame *frame; /* last decoded frame */
AVPacket *packet; /* last read data packet */
int read_packet;
int end_of_stream;
int end_of_audio;
/* sample state */
int32_t samples_discard;
int32_t samples_consumed;
int32_t samples_filled;
} ffmpeg_codec_data;
#endif
#ifdef VGM_USE_MP4V2 #ifdef VGM_USE_MP4V2
typedef struct { typedef struct {
STREAMFILE* streamfile; STREAMFILE* streamfile;