diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index 9a45b9fb1..65679908e 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -175,6 +175,8 @@ 8349A91F1FE6258200E26435 /* naac.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A9061FE6258100E26435 /* naac.c */; }; 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */ = {isa = PBXBuildFile; fileRef = 834D3A6D19F47C98001C54F6 /* g1l.c */; }; 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 */; }; 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 */; }; @@ -967,6 +969,8 @@ 8349A9051FE6258100E26435 /* bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; 8349A9061FE6258100E26435 /* naac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naac.c; sourceTree = ""; }; 834D3A6D19F47C98001C54F6 /* g1l.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g1l.c; sourceTree = ""; }; + 834FBCE426BBC7D00095647F /* tantalus_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tantalus_decoder.c; sourceTree = ""; }; + 834FBCE926BBC7E50095647F /* piff_tpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = piff_tpcm.c; sourceTree = ""; }; 834FE0AA215C798A000A5D3D /* acm_decoder_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm_decoder_util.c; sourceTree = ""; }; 834FE0AB215C798A000A5D3D /* ffmpeg_decoder_custom_opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffmpeg_decoder_custom_opus.c; sourceTree = ""; }; 834FE0AC215C798B000A5D3D /* acm_decoder_libacm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acm_decoder_libacm.h; sourceTree = ""; }; @@ -1680,6 +1684,7 @@ 83E7FD5B25EF2B0C00683FD2 /* tac_decoder_lib.c */, 83E7FD5C25EF2B0C00683FD2 /* tac_decoder_lib.h */, 83E7FD5725EF2B0C00683FD2 /* tac_decoder.c */, + 834FBCE426BBC7D00095647F /* tantalus_decoder.c */, 8373341023F60C7A00DE14DC /* tgcadpcm_decoder.c */, 837CEA7623487E2400E62A4A /* ubi_adpcm_decoder.c */, 83F1EE2C245D4FB20076E182 /* vadpcm_decoder.c */, @@ -1989,6 +1994,7 @@ 836F6E8618BDC2180095E648 /* pc_mxst.c */, 8306B0D12098458F000302D4 /* pcm_sre.c */, 83D20076248DDB770048BD24 /* pcm_success.c */, + 834FBCE926BBC7E50095647F /* piff_tpcm.c */, 836F6E8B18BDC2180095E648 /* pona.c */, 836F6E8C18BDC2180095E648 /* pos.c */, 8306B0C52098458D000302D4 /* ppst_streamfile.h */, @@ -2741,6 +2747,7 @@ 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */, 836F703B18BDC2190095E648 /* vsf.c in Sources */, 836F6F8218BDC2190095E648 /* ea_schl.c in Sources */, + 834FBCE826BBC7D00095647F /* tantalus_decoder.c in Sources */, 836F6F7318BDC2190095E648 /* bcstm.c in Sources */, 83299FD11E7660C7003A3242 /* dsp_adx.c in Sources */, 836F704018BDC2190095E648 /* wii_sng.c in Sources */, @@ -2987,6 +2994,7 @@ 836F704F18BDC2190095E648 /* xwb.c in Sources */, 8346D98525BF83B300D1A8B0 /* compresswave_decoder_lib.c in Sources */, 8346D97D25BF838C00D1A8B0 /* compresswave.c in Sources */, + 834FBCEA26BBC7E50095647F /* piff_tpcm.c in Sources */, 8306B0AD20984552000302D4 /* blocked_caf.c in Sources */, 8306B0AA20984552000302D4 /* blocked_sthd.c in Sources */, 836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c index 7d48cd2f5..79ca3178a 100644 --- a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c +++ b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c @@ -364,7 +364,7 @@ static void clHCA_destructor(clHCA* hca) { hca->is_valid = 0; } -int clHCA_sizeof() { +int clHCA_sizeof(void) { return sizeof(clHCA); } @@ -376,7 +376,7 @@ void clHCA_done(clHCA* hca) { clHCA_destructor(hca); } -clHCA* clHCA_new() { +clHCA* clHCA_new(void) { clHCA* hca = malloc(clHCA_sizeof()); if (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) */ { - unsigned int i; const float* dct = ch->spectra; //ch->dct; const float* prev = ch->imdct_previous; diff --git a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h index df2b71a80..dc72d39a8 100644 --- a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h +++ b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.h @@ -14,12 +14,12 @@ int clHCA_isOurFile(const void *data, unsigned int size); typedef struct clHCA clHCA; /* 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_done(clHCA *); /* Or you could let the library allocate it. */ -clHCA * clHCA_new(); +clHCA * clHCA_new(void); void clHCA_delete(clHCA *); /* Parses the HCA header. Must be called before any decoding may be performed, diff --git a/Frameworks/vgmstream/vgmstream/src/coding/circus_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/circus_decoder.c index c85293655..c32e32e9f 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/circus_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/circus_decoder.c @@ -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++) { - int8_t code = read_8bit(frame_offset+i,stream->streamfile); + int8_t code = read_u8(frame_offset+i,stream->streamfile); hist += code << scale; if (code == 0) { @@ -102,6 +102,7 @@ void decode_circus_adpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channel scale++; } outbuf[sample_pos] = hist; + sample_pos += channelspacing; } stream->adpcm_history1_32 = hist; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index 360c4eb0d..2c40a2f34 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -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_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_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_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_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 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); @@ -118,13 +118,13 @@ size_t xa_bytes_to_samples(size_t bytes, int channels, int is_blocked, int is_fo /* 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_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); int32_t ea_xa_bytes_to_samples(size_t bytes, int channels); /* 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); @@ -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); +/* 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 */ 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 { //todo simplify STREAMFILE *streamfile; - ogg_int64_t start; /* file offset where the Ogg starts */ - ogg_int64_t offset; /* virtual offset, from 0 to size */ - ogg_int64_t size; /* virtual size of the Ogg */ + int64_t start; /* file offset where the Ogg starts */ + int64_t offset; /* virtual offset, from 0 to size */ + int64_t size; /* virtual size of the Ogg */ /* 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; off_t scd_xor_length; uint32_t xor_value; @@ -552,6 +557,8 @@ void free_speex(speex_codec_data* data); #ifdef VGM_USE_FFMPEG /* 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_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); @@ -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); const char* ffmpeg_get_codec_name(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); + +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); /* 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_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) */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c index d4bb27feb..275cf1d04 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c @@ -829,9 +829,7 @@ 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 * 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. */ - if (data->skipSamples == 0) { - ffmpeg_set_skip_samples(data, start_skip+64); - } + ffmpeg_set_skip_samples(data, start_skip+64); } #endif } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.c b/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.c index 3b2978b5d..770efc39b 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.c @@ -557,7 +557,7 @@ struct TCompressWaveData { //----------------------------------------------------------- //create -TCompressWaveData* TCompressWaveData_Create() { +TCompressWaveData* TCompressWaveData_Create(void) { TCompressWaveData* this = malloc(sizeof(TCompressWaveData)); if (!this) return NULL; #if 0 @@ -604,7 +604,7 @@ void TCompressWaveData_Free(TCompressWaveData* this) { //----------------------------------------------------------- //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) { *RFlg = THuff_Read(this->RH); //STEREO *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}; 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; } else { //without fade value - this->Ffade = round(PW_MAXVOLUME / fade / 44100); - this->FSetVolume = round(aaa * PW_MAXVOLUME); + this->Ffade = round((double)PW_MAXVOLUME / fade / 44100); + this->FSetVolume = round(aaa * (double)PW_MAXVOLUME); } } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.h b/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.h index c2e438c78..ae53e2ccd 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/compresswave_decoder_lib.h @@ -7,7 +7,7 @@ typedef struct TCompressWaveData TCompressWaveData; void TCompressWaveData_GetLoopState(TCompressWaveData* this); void TCompressWaveData_SetLoopState(TCompressWaveData* this); -TCompressWaveData* TCompressWaveData_Create(); +TCompressWaveData* TCompressWaveData_Create(void); void TCompressWaveData_Free(TCompressWaveData* this); int TCompressWaveData_Rendering(TCompressWaveData* this, int16_t* buf, uint32_t Len); int TCompressWaveData_LoadFromStream(TCompressWaveData* this, STREAMFILE* ss); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c index f09cdc14e..523f3731b 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ea_xa_decoder.c @@ -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?) */ -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; int32_t coef1, coef2; 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]; shift = (frame_info & 0x0F) + 8; - for (i=first_sample,sample_count=0; ioffset + 0x01 + i/2); @@ -84,7 +84,7 @@ void decode_ea_xa_v2(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspac } #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_K1[16] = { 0.0, 0.0, -0.8125, -0.859375 }; /* 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; -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; int i, sample_count, shift; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c index 37979dd1c..6aa57f973 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ea_xas_decoder.c @@ -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. */ -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}; off_t frame_offset; int i, frames_in, samples_done = 0, sample_count = 0; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c index ea79b5b34..ae17c0cf4 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder.c @@ -2,10 +2,61 @@ #include "coding.h" #ifdef VGM_USE_FFMPEG +#include +#include +#include + +/* 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 - static volatile int g_ffmpeg_initialized = 0; 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 */ -static void g_init_ffmpeg() { +static void g_init_ffmpeg(void) { if (g_ffmpeg_initialized == 1) { 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 distance = 0; /* always 0 ("duration") */ - AVStream * stream = data->formatCtx->streams[data->streamIndex]; - AVPacket * pkt = data->packet; + AVStream* stream = data->formatCtx->streams[data->stream_index]; + AVPacket* pkt = data->packet; /* 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); if (ret < 0) break; - if (pkt->stream_index != data->streamIndex) + if (pkt->stream_index != data->stream_index) 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); @@ -138,7 +189,7 @@ static int init_seek(ffmpeg_codec_data* data) { test_seek: /* 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 ) { //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 */ @@ -186,7 +237,7 @@ static int ffmpeg_read(void* opaque, uint8_t* buf, int read_size) { } /* 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->offset += bytes; 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) */ offset += data->logical_size; break; + + default: + break; } /* 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); } -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); } @@ -281,8 +335,8 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he data = calloc(1, sizeof(ffmpeg_codec_data)); if (!data) return NULL; - data->streamfile = reopen_streamfile(sf, 0); - if (!data->streamfile) goto fail; + data->sf = reopen_streamfile(sf, 0); + if (!data->sf) goto fail; /* fake header to trick FFmpeg into demuxing/decoding the stream */ if (header_size > 0) { @@ -307,14 +361,16 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he /* setup other values */ { - AVStream *stream = data->formatCtx->streams[data->streamIndex]; + AVStream* stream = data->formatCtx->streams[data->stream_index]; AVRational tb = {0}; + tb.num = 1; tb.den = data->codecCtx->sample_rate; + +#if 0 /* derive info */ data->sampleRate = data->codecCtx->sample_rate; data->channels = data->codecCtx->channels; data->bitrate = (int)(data->codecCtx->bit_rate); -#if 0 data->blockAlign = data->codecCtx->block_align; 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 */ @@ -322,40 +378,40 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he #endif /* try to guess frames/samples (duration isn't always set) */ - tb.num = 1; tb.den = data->codecCtx->sample_rate; - data->totalSamples = av_rescale_q(stream->duration, stream->time_base, tb); - if (data->totalSamples < 0) - data->totalSamples = 0; /* caller must consider this */ + data->total_samples = av_rescale_q(stream->duration, stream->time_base, tb); + if (data->total_samples < 0) + data->total_samples = 0; - /* expose start samples to be skipped (encoder delay, usually added by MDCT-based encoders like AAC/MP3/ATRAC3/XMA/etc) - * get after init_seek because some demuxers like AAC only fill skip_samples for the first packet */ -#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100) - if (stream->start_skip_samples) /* samples to skip in the first packet */ - data->skipSamples = stream->start_skip_samples; + /* read start samples to be skipped (encoder delay), info only. + * Not too reliable though, see ffmpeg_set_skip_samples */ + if (stream->start_time && stream->start_time != AV_NOPTS_VALUE) + data->skip_samples = av_rescale_q(stream->start_time, stream->time_base, tb); + 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) */ - data->skipSamples = stream->skip_samples; -#else - if (stream->start_time) - data->skipSamples = av_rescale_q(stream->start_time, stream->time_base, tb); + data->skip_samples = stream->skip_samples; #endif /* 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->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->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->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) 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 -#else - VGM_ASSERT(stream->start_time > 0, "FFMPEG: start_time %i\n", (int)stream->start_time); //delay #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 */ /* 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 */ { - int i, streamIndex, streamCount; + int i, stream_index, stream_count; - streamIndex = -1; - streamCount = 0; + stream_index = -1; + stream_count = 0; if (reset) - streamIndex = data->streamIndex; + stream_index = data->stream_index; 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) { - streamCount++; + stream_count++; /* select Nth audio stream if specified, or first one */ - if (streamIndex < 0 || (target_subsong > 0 && streamCount == target_subsong)) { - streamIndex = i; + if (stream_index < 0 || (target_subsong > 0 && stream_count == target_subsong)) { + stream_index = i; } } - if (i != streamIndex) + if (i != stream_index) stream->discard = AVDISCARD_ALL; /* disable demuxing for other streams */ } - if (streamCount < target_subsong) goto fail; - if (streamIndex < 0) goto fail; + if (stream_count < target_subsong) goto fail; + if (stream_index < 0) goto fail; - data->streamIndex = streamIndex; - data->streamCount = streamCount; + data->stream_index = stream_index; + data->stream_count = stream_count; } /* setup codec with stream info */ data->codecCtx = avcodec_alloc_context3(NULL); 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; - //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); if (!data->codec) goto fail; @@ -501,7 +559,7 @@ static int decode_ffmpeg_frame(ffmpeg_codec_data* data) { } /* ignore non-selected streams */ - if (data->packet->stream_index != data->streamIndex) + if (data->packet->stream_index != data->stream_index) continue; } @@ -788,7 +846,7 @@ void seek_ffmpeg(ffmpeg_codec_data* data, int32_t num_sample) { if (errcode < 0) goto fail; } 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); } @@ -800,18 +858,10 @@ void seek_ffmpeg(ffmpeg_codec_data* data, int32_t num_sample) { data->end_of_stream = 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) { - AVStream *stream = data->formatCtx->streams[data->streamIndex]; - /* sometimes (ex. AAC) after seeking to the first packet skip_samples is restored, but we want our value */ -#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; + data->samples_discard += data->skip_samples; + /* internally FFmpeg may skip (skip_samples/start_skip_samples) too */ } return; @@ -872,40 +922,53 @@ void free_ffmpeg(ffmpeg_codec_data* data) { data->header_block = NULL; } - close_streamfile(data->streamfile); + close_streamfile(data->sf); free(data); } /** - * Sets the number of samples to skip at the beginning of the stream, needed by some "gapless" formats. - * (encoder delay, usually added by MDCT-based encoders like AAC/MP3/ATRAC3/XMA/etc to "set up" the decoder). + * Sets the number of samples to skip at the beginning of the stream (encoder delay), needed by some "gapless" formats. * - 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 - * (FFmpeg's stream->(start_)skip_samples causes glitches in XMA). + * encoder delay in FFmpeg is handled in multiple ways: + * - 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) { - AVStream *stream = NULL; - if (!data || !data->formatCtx) + if (!data || !data->formatCtx || !skip_samples) return; - /* overwrite FFmpeg's skip samples */ - stream = data->formatCtx->streams[data->streamIndex]; + /* let FFmpeg handle (may need an option to force override?) */ + 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) - stream->start_skip_samples = 0; /* used for the first packet *if* pts=0 */ - stream->skip_samples = 0; /* skip_samples can be used for any packet */ + stream->start_skip_samples = 0; + stream->skip_samples = 0; #else - stream->start_time = 0; + //stream->start_time = 0; /* info only = useless */ +#endif + } #endif /* set skip samples with our internal discard */ data->skip_samples_set = 1; data->samples_discard = skip_samples; - - /* expose (info only) */ - data->skipSamples = skip_samples; + data->skip_samples = skip_samples; } /* 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) { int i; - if (data->channels > 32) + if (data->codecCtx->channels > 32) 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_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) { + if (!data) + return; /* 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). * whatever, we'll just kill and reconstruct FFmpeg's config every time */ data->force_seek = 1; 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) { @@ -955,7 +1026,7 @@ const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key) if (!data || !data->codec) 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) avd = data->formatCtx->metadata; /* per format (like Flac) */ if (!avd) @@ -968,8 +1039,33 @@ const char* ffmpeg_get_metadata_value(ffmpeg_codec_data* data, const char* key) 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) { if (!data) return NULL; - return data->streamfile; + return data->sf; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c index cc97594c5..d5d97a3d9 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_custom_opus.c @@ -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 + 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 */ - //if (ffmpeg_data->skipSamples <= 0) { - // ffmpeg_set_skip_samples(ffmpeg_data, skip); - //} + * FFmpeg + opus is audibly buggy with some low bitrate SSB Ultimate files */ + //ffmpeg_set_skip_samples(ffmpeg_data, skip); close_streamfile(temp_sf); 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); } -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}; cfg.channels = channels; cfg.skip = skip; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c index 31237a88e..c2d17088c 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c @@ -2,7 +2,7 @@ #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; 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; } -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; uint8_t buf[0x100]; 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 * 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) * 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_samples(sample_count); /* useful? */ /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ if (is_at3) { - ffmpeg_data->invert_floats_set = 1; + ffmpeg_set_invert_floats(ffmpeg_data); } return ffmpeg_data; @@ -76,7 +74,7 @@ fail: } /* 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; int is_at3 = 0, is_at3p = 0, codec; 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; } - /* 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) * 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_samples(sample_count); /* useful? */ /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ 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): * - 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 */ - if (is_at3p && ffmpeg_data->channels == 6) { + if (is_at3p && ffmpeg_get_channels(ffmpeg_data) == 6) { /* LFE BR BL > LFE BL BR > same */ int channel_remap[] = { 0, 1, 2, 5, 5, 5, }; 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 */ int channel_remap[] = { 0, 1, 2, 7, 7, 7, 7, 7}; ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap); } - if (out_samples) - *out_samples = fact_samples; + if (p_samples) + *p_samples = fact_samples; return ffmpeg_data; fail: @@ -187,7 +183,7 @@ fail: 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; 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, * but should be handled in container as each encoder uses its own value * (Apple: 2112, FAAD: probably 1024, etc) */ - //ffmpeg_set_skip_samples(data, 1024); + ffmpeg_set_skip_samples(data, skip_samples); return data; fail: diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.c b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.c index dfdfd4f06..7d3560c1a 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.c @@ -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)); if (!ctx) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.h b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.h index 7f8d6dbed..4176ae25b 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder_aes.h @@ -6,7 +6,7 @@ typedef struct s14aes_handle s14aes_handle; /* init/close handle (AES-192 in ECB mode) */ -s14aes_handle* s14aes_init(); +s14aes_handle* s14aes_init(void); void s14aes_close(s14aes_handle* ctx); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c index 122ca89af..023e0fdd4 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/hca_decoder.c @@ -1,4 +1,5 @@ #include "coding.h" +#include "clHCA.h" struct hca_codec_data { diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c index a0b4599f2..14f14a1db 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c @@ -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) */ -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; int32_t hist1 = stream->adpcm_history1_32; 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. * 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}; int i, frames_in, sample_pos = 0, block_samples, frame_size; int32_t hist1 = stream->adpcm_history1_32; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c index ab88416b7..9ce7c5460 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c @@ -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 bitpos; 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; } -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; switch(data->block_table[block_num].flags) { case 0x0D: 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; default: return 0; @@ -434,7 +434,7 @@ static int decode_block1(STREAMFILE* sf, imuse_codec_data* data, uint8_t* block, 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 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 bitpos; 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; } -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; switch(data->block_table[block_num].flags) { case 0x00: - decode_data2(sf, &data->sbuf, block, data_left, block_num); + decode_data2(&data->sbuf, block, data_left, block_num); break; case 0x01: - decode_vima2(sf, &data->sbuf, block, data_left, data->adpcm_table); + decode_vima2(&data->sbuf, block, data_left, data->adpcm_table); break; default: return 0; @@ -597,11 +597,11 @@ static int decode_block(STREAMFILE* sf, imuse_codec_data* data) { switch(data->type) { case COMP: - ok = decode_block1(sf, data, block, data_left); + ok = decode_block1(data, block, data_left); break; case MCMP: - ok = decode_block2(sf, data, block, data_left); + ok = decode_block2(data, block, data_left); break; default: diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c index 80d8e3c50..d158f823f 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c @@ -3,13 +3,12 @@ #include "../vgmstream.h" #ifdef VGM_USE_MPEG -#include #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) */ -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_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); @@ -185,7 +184,7 @@ fail: } -static mpg123_handle* init_mpg123_handle() { +static mpg123_handle* init_mpg123_handle(void) { mpg123_handle* m = NULL; int rc; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h index af8293c6f..721dabf29 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.h @@ -1,5 +1,6 @@ #ifndef _MPEG_DECODER_H_ #define _MPEG_DECODER_H_ +#include #include "../vgmstream.h" #include "../coding/coding.h" diff --git a/Frameworks/vgmstream/vgmstream/src/coding/tantalus_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/tantalus_decoder.c new file mode 100644 index 000000000..109164c1a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/tantalus_decoder.c @@ -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; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ubi_adpcm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ubi_adpcm_decoder.c index ab44efd16..0d7be9ef8 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ubi_adpcm_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ubi_adpcm_decoder.c @@ -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 * 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; size_t pos = 0; uint64_t bits = 0, input = 0; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c index 4dbcd8259..bf09b662c 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.c @@ -3,7 +3,6 @@ #include "vorbis_custom_decoder.h" #ifdef VGM_USE_VORBIS -#include #define VORBIS_DEFAULT_BUFFER_SIZE 0x8000 /* should be at least the size of the setup header, ~0x2000 */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h index b3fa05aef..c913d8bf1 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_decoder.h @@ -6,6 +6,7 @@ /* used by vorbis_custom_decoder.c, but scattered in other .c files */ #ifdef VGM_USE_VORBIS +#include /* custom Vorbis without Ogg layer */ struct vorbis_custom_codec_data { diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c index e93d9e603..6da8c264b 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_vid1.c @@ -77,7 +77,7 @@ int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL* stream, vorbis_custom_code /* 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 */ /* read raw block */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c index 1eeb38aff..cc7dc2858 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/vorbis_custom_utils_wwise.c @@ -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) */ 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 */ packet_type = 0; 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; -fail: - return 0; +//fail: +// return 0; } /*******************************************************************************/ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ws_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ws_decoder.c index b72193dc7..3dc530a2f 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ws_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ws_decoder.c @@ -135,6 +135,8 @@ void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channels samples_left_in_frame--) { /* done with reading a sample */ outbuf[sample_count]=(hist-0x80)*0x100; } + default: + break; } } } diff --git a/Frameworks/vgmstream/vgmstream/src/decode.c b/Frameworks/vgmstream/vgmstream/src/decode.c index db00ccea8..9038086d9 100644 --- a/Frameworks/vgmstream/vgmstream/src/decode.c +++ b/Frameworks/vgmstream/vgmstream/src/decode.c @@ -503,6 +503,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) { return 256; /* (0x8c - 0xc) * 2 */ case coding_ASF: return 32; /* (0x11 - 0x1) * 2 */ + case coding_TANTALUS: + return 30; /* (0x10 - 0x01) * 2 */ case coding_DSA: return 14; /* (0x08 - 0x1) * 2 */ case coding_XMD: @@ -716,6 +718,8 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) { return 0x8c; case coding_ASF: return 0x11; + case coding_TANTALUS: + return 0x10; case coding_DSA: return 0x08; case coding_XMD: @@ -1008,7 +1012,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ case coding_EA_XA_V2: for (ch = 0; ch < vgmstream->channels; 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; case coding_MAXIS_XA: @@ -1020,7 +1024,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ case coding_EA_XAS_V0: for (ch = 0; ch < vgmstream->channels; 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; case coding_EA_XAS_V1: @@ -1184,7 +1188,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ case coding_WWISE_IMA: for (ch = 0; ch < vgmstream->channels; 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; case coding_REF_IMA: @@ -1223,7 +1227,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ case coding_CD_IMA: for (ch = 0; ch < vgmstream->channels; 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; @@ -1386,6 +1390,12 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ vgmstream->channels, vgmstream->samples_into_block, samples_to_do); } 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: for (ch = 0; ch < vgmstream->channels; ch++) { decode_dsa(&vgmstream->ch[ch], buffer+ch, diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 0baa8965d..094cf344f 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -515,6 +515,7 @@ static const char* extension_list[] = { "sxd2", "sxd3", + "tad", "tec", "tgq", "thp", @@ -787,6 +788,7 @@ static const coding_info coding_info_list[] = { {coding_MC3, "Paradigm MC3 3-bit ADPCM"}, {coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"}, {coding_ASF, "Argonaut ASF 4-bit ADPCM"}, + {coding_TANTALUS, "Tantalus 4-bit ADPCM"}, {coding_DSA, "Ocean DSA 4-bit ADPCM"}, {coding_XMD, "Konami XMD 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_FILP, "Bio Hazard - Gun Survivor FILp Header"}, {meta_IKM, "MiCROViSiON IKM header"}, - {meta_SFS, "Baroque SFS Header"}, + {meta_SFS, "String .SFS header"}, {meta_SAT_DVI, "Konami KCEN DVI. header"}, {meta_DC_KCEY, "Konami KCEY KCEYCOMP header"}, {meta_BG00, "Falcom BG00 Header"}, @@ -1350,6 +1352,7 @@ static const meta_info meta_info_list[] = { {meta_IDSP_TOSE, "TOSE .IDSP header"}, {meta_DSP_KWA, "Kuju London .KWA 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) { diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_awc.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_awc.c index 3504e1d78..a2dda8154 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_awc.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_awc.c @@ -4,7 +4,7 @@ #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); /* 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) */ - 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); for (i = 0; i < vgmstream->channels; 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; /* later games have an smaller channel header, try to detect using diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xvag.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xvag.c index 1c1ab2d7b..4559ad9f5 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_xvag.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_xvag.c @@ -1,19 +1,19 @@ -#include "layout.h" -#include "../coding/coding.h" -#include "../vgmstream.h" - - -/* 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) { - int i; - size_t channel_size = 0x10; - - /* set offsets */ - for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = block_offset + channel_size*i; - } - - //vgmstream->current_block_size = ; /* fixed */ - vgmstream->current_block_offset = block_offset; - vgmstream->next_block_offset = block_offset + vgmstream->full_block_size; -} +#include "layout.h" +#include "../coding/coding.h" +#include "../vgmstream.h" + + +/* 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) { + int i; + size_t channel_size = 0x10; + + /* set offsets */ + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = block_offset + channel_size*i; + } + + //vgmstream->current_block_size = ; /* fixed */ + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + vgmstream->full_block_size; +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/layered.c b/Frameworks/vgmstream/vgmstream/src/layout/layered.c index 60c24f2a1..5e0570451 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/layered.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/layered.c @@ -240,6 +240,7 @@ VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data) { int i, channels, loop_flag, sample_rate, external_looping; int32_t num_samples, loop_start, loop_end; int delta = 1024; + coding_t coding_type = data->layers[0]->coding_type; /* get data */ channels = data->output_channels; @@ -250,6 +251,7 @@ VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data) { loop_end = data->layers[0]->loop_end_sample; external_looping = 0; sample_rate = 0; + for (i = 0; i < data->layer_count; i++) { int32_t layer_samples = vgmstream_get_samples(data->layers[i]); 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) sample_rate = layer_rate; + + if (coding_type == coding_SILENCE) + coding_type = data->layers[i]->coding_type; } data->external_looping = external_looping; @@ -289,12 +294,12 @@ VGMSTREAM* allocate_layered_vgmstream(layered_layout_data* data) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; + vgmstream->meta_type = data->layers[0]->meta_type; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = num_samples; vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; - vgmstream->meta_type = data->layers[0]->meta_type; /* info */ - vgmstream->coding_type = data->layers[0]->coding_type; /* info */ + vgmstream->coding_type = coding_type; vgmstream->layout_type = layout_layered; vgmstream->layout_data = data; diff --git a/Frameworks/vgmstream/vgmstream/src/layout/segmented.c b/Frameworks/vgmstream/vgmstream/src/layout/segmented.c index 609b653e5..e9bc492fa 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/segmented.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/segmented.c @@ -296,6 +296,7 @@ VGMSTREAM* allocate_segmented_vgmstream(segmented_layout_data* data, int loop_fl int channel_layout; int i, sample_rate; int32_t num_samples, loop_start, loop_end; + coding_t coding_type = data->segments[0]->coding_type; /* save data */ 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) 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 */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(data->output_channels, loop_flag); 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->loop_start_sample = loop_start; 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->layout_type = layout_segmented; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/208.c b/Frameworks/vgmstream/vgmstream/src/meta/208.c index 10e6461b2..3969d86dd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/208.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/208.c @@ -1,48 +1,47 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* .208 - from Ocean game(s?) [Last Rites (PC)] */ -VGMSTREAM * init_vgmstream_208(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count, sample_rate; - size_t data_size; - - - /* checks */ - if (!check_extensions(streamFile, "208")) - goto fail; - /* possible validation: (0x04 == 0 and 0xcc == 0x1F7D984D) or 0x04 == 0xf0 and 0xcc == 0) */ - if (!((read_32bitLE(0x04,streamFile) == 0x00 && read_32bitBE(0xcc,streamFile) == 0x1F7D984D) || - (read_32bitLE(0x04,streamFile) == 0xF0 && read_32bitBE(0xcc,streamFile) == 0x00000000))) - goto fail; - - start_offset = read_32bitLE(0x00,streamFile); - data_size = read_32bitLE(0x0c,streamFile); - sample_rate = read_32bitLE(0x34,streamFile); - channel_count = read_32bitLE(0x3C,streamFile); /* assumed */ - loop_flag = 0; - - if (start_offset + data_size != get_streamfile_size(streamFile)) - goto fail; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_208; - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 8); - vgmstream->coding_type = coding_PCM8_U; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x1; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .208 - from Ocean game(s?) [Last Rites (PC)] */ +VGMSTREAM* init_vgmstream_208(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset, data_size; + int loop_flag, channels, sample_rate; + + + /* checks */ + if (!check_extensions(sf, "208")) + goto fail; + /* possible validation: (0x04 == 0 and 0xcc == 0x1F7D984D) or 0x04 == 0xf0 and 0xcc == 0) */ + if (!((read_u32le(0x04,sf) == 0x00 && read_u32be(0xcc,sf) == 0x1F7D984D) || + (read_u32le(0x04,sf) == 0xF0 && read_u32be(0xcc,sf) == 0x00000000))) + goto fail; + + start_offset = read_s32le(0x00,sf); + data_size = read_s32le(0x0c,sf); + sample_rate = read_s32le(0x34,sf); + channels = read_s32le(0x3C,sf); /* assumed */ + loop_flag = 0; + + if (start_offset + data_size != get_streamfile_size(sf)) + goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_208; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = pcm8_bytes_to_samples(data_size, channels); + vgmstream->coding_type = coding_PCM8_U; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1; + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/acb.c b/Frameworks/vgmstream/vgmstream/src/meta/acb.c index 0acad0a83..697374949 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/acb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/acb.c @@ -91,7 +91,7 @@ fail: #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; /* buffer seems better than reopening when opening multiple subsongs at the same time with STDIO, diff --git a/Frameworks/vgmstream/vgmstream/src/meta/adx.c b/Frameworks/vgmstream/vgmstream/src/meta/adx.c index 111e10d03..3d1271453 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/adx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/adx.c @@ -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); 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 */ if (type == 8) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aif_asobo.c b/Frameworks/vgmstream/vgmstream/src/meta/aif_asobo.c index 9610dc67a..5a551727b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/aif_asobo.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/aif_asobo.c @@ -1,51 +1,51 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* .AIF - from Asobo Studio games [Ratatouille (PC), WALL-E (PC), Up (PC)] */ -VGMSTREAM * init_vgmstream_aif_asobo(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - size_t data_size; - int loop_flag, channel_count; - - - /* checks */ - /* aif: standard, .laif/aiffl: for plugins */ - if ( !check_extensions(streamFile,"aif,laif,aiffl") ) - goto fail; - if ((uint16_t)read_16bitLE(0x00,streamFile) != 0x69) /* Xbox codec */ - goto fail; - - channel_count = read_16bitLE(0x02,streamFile); /* assumed, only stereo is known */ - if (channel_count != 2) goto fail; - - /* 0x08: ? */ - if ((uint16_t)read_16bitLE(0x0c,streamFile) != 0x24*channel_count) /* Xbox block */ - goto fail; - if ((uint16_t)read_16bitLE(0x0e,streamFile) != 0x04) /* Xbox bps */ - goto fail; - loop_flag = 0; - - start_offset = 0x14; - data_size = get_streamfile_size(streamFile) - start_offset; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_AIF_ASOBO; - vgmstream->sample_rate = read_32bitLE(0x04,streamFile); - vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size,channel_count); - - vgmstream->coding_type = coding_XBOX_IMA; - vgmstream->layout_type = layout_none; - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .AIF - from Asobo Studio games [Ratatouille (PC), WALL-E (PC), Up (PC)] */ +VGMSTREAM* init_vgmstream_aif_asobo(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + size_t data_size; + int loop_flag, channel_count; + + + /* checks */ + /* aif: standard, .laif/aiffl: for plugins */ + if ( !check_extensions(sf,"aif,laif,aiffl") ) + goto fail; + if ((uint16_t)read_16bitLE(0x00,sf) != 0x69) /* Xbox codec */ + goto fail; + + channel_count = read_16bitLE(0x02,sf); /* assumed, only stereo is known */ + if (channel_count != 2) goto fail; + + /* 0x08: ? */ + if ((uint16_t)read_16bitLE(0x0c,sf) != 0x24*channel_count) /* Xbox block */ + goto fail; + if ((uint16_t)read_16bitLE(0x0e,sf) != 0x04) /* Xbox bps */ + goto fail; + loop_flag = 0; + + start_offset = 0x14; + data_size = get_streamfile_size(sf) - start_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_AIF_ASOBO; + vgmstream->sample_rate = read_32bitLE(0x04,sf); + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size,channel_count); + + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + + if ( !vgmstream_open_stream(vgmstream, sf, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/akb.c b/Frameworks/vgmstream/vgmstream/src/meta/akb.c index 15a12ea8f..e46471421 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/akb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/akb.c @@ -3,20 +3,20 @@ #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) /* 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; size_t filesize; 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_end = read_32bitLE(0x18, streamFile); + loop_start = read_32bitLE(0x14, sf); + 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 ( loop_start || loop_end ) { @@ -34,7 +34,7 @@ fail: /* AKB - found in SQEX iOS games */ -VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_akb(STREAMFILE *sf) { VGMSTREAM * vgmstream = NULL; off_t start_offset, extradata_offset = 0; size_t stream_size, header_size, subheader_size = 0, extradata_size = 0; @@ -44,28 +44,28 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { /* checks */ /* .akb.bytes is the usual extension in later games */ - if ( !check_extensions(streamFile, "akb,bytes") ) + if ( !check_extensions(sf, "akb,bytes") ) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x414B4220) /* "AKB " */ + if (read_32bitBE(0x00,sf) != 0x414B4220) /* "AKB " */ goto fail; - if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile)) + if (read_32bitLE(0x08,sf) != get_streamfile_size(sf)) goto fail; /* 0x04(1): version */ - header_size = read_16bitLE(0x06,streamFile); + header_size = read_16bitLE(0x06,sf); - codec = read_8bit(0x0c,streamFile); - channel_count = read_8bit(0x0d,streamFile); - sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile); - num_samples = read_32bitLE(0x10,streamFile); - loop_start = read_32bitLE(0x14,streamFile); - loop_end = read_32bitLE(0x18,streamFile); + codec = read_8bit(0x0c,sf); + channel_count = read_8bit(0x0d,sf); + sample_rate = (uint16_t)read_16bitLE(0x0e,sf); + num_samples = read_32bitLE(0x10,sf); + loop_start = read_32bitLE(0x14,sf); + loop_end = read_32bitLE(0x18,sf); /* possibly more complex, see AKB2 */ if (header_size >= 0x44) { /* v2+ */ - extradata_size = read_16bitLE(0x1c,streamFile); + extradata_size = read_16bitLE(0x1c,sf); /* 0x20+: config? (pan, volume) */ - subheader_size = read_16bitLE(0x28,streamFile); + subheader_size = read_16bitLE(0x28,sf); /* 0x24: file_id? */ /* 0x2b: encryption bitflag if version > 2? */ extradata_offset = header_size + subheader_size; @@ -75,7 +75,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { 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); @@ -91,14 +91,14 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { case 0x02: { /* MSADPCM [Dragon Quest II (iOS) sfx] */ vgmstream->coding_type = coding_MSADPCM; 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 * (base samples may have more than possible and read over file size otherwise, very strange) * loop_end seems to exist even with loop disabled */ - vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile); - vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile); - vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile); + vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, sf); + vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, sf); + vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, sf); break; } @@ -112,7 +112,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { /* extradata + 0x04: Ogg loop start offset */ /* 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) { close_vgmstream(vgmstream); return ogg_vgmstream; @@ -128,7 +128,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { /* Alt decoding without libvorbis (minor number of beginning samples difference). * 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)] */ - 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; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; @@ -145,7 +145,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { #ifdef VGM_USE_FFMPEG case 0x06: { /* M4A with AAC [The World Ends with You (iPad)] */ /* 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; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; @@ -168,7 +168,7 @@ VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { } /* open the file for reading */ - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + if ( !vgmstream_open_stream(vgmstream, sf, start_offset) ) goto fail; return vgmstream; @@ -180,22 +180,22 @@ fail: /* AKB2 - found in later SQEX iOS games */ -VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_akb2(STREAMFILE *sf) { VGMSTREAM * vgmstream = NULL; off_t start_offset, material_offset, extradata_offset; 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 total_subsongs, target_subsong = streamFile->stream_index; + int total_subsongs, target_subsong = sf->stream_index; /* check extensions */ /* .akb.bytes is the usual extension in later games */ - if ( !check_extensions(streamFile, "akb,bytes") ) + if ( !check_extensions(sf, "akb,bytes") ) goto fail; /* checks */ - if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */ + if (read_32bitBE(0x00,sf) != 0x414B4232) /* "AKB2" */ goto fail; - if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile)) + if (read_32bitLE(0x08,sf) != get_streamfile_size(sf)) goto fail; /* 0x04: version */ @@ -203,37 +203,37 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { { off_t table_offset; size_t table_size, entry_size; - off_t akb_header_size = read_16bitLE(0x06, streamFile); - int table_count = read_8bit(0x0c, streamFile); + off_t akb_header_size = read_16bitLE(0x06, sf); + int table_count = read_8bit(0x0c, sf); /* 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 */ goto fail; 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_size = read_16bitLE(table_offset + 0x02, streamFile); + table_offset = read_32bitLE(akb_header_size + (table_count-1)*entry_size + 0x04, sf); + 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 > 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) **/ /* 0x00: 0? */ - codec = read_8bit(material_offset+0x01,streamFile); - channel_count = read_8bit(material_offset+0x02,streamFile); - encryption_flag = read_8bit(material_offset+0x03,streamFile); - material_size = read_16bitLE(material_offset+0x04,streamFile); - sample_rate = (uint16_t)read_16bitLE(material_offset+0x06,streamFile); - stream_size = read_32bitLE(material_offset+0x08,streamFile); - num_samples = read_32bitLE(material_offset+0x0c,streamFile); + codec = read_8bit(material_offset+0x01,sf); + channel_count = read_8bit(material_offset+0x02,sf); + encryption_flag = read_8bit(material_offset+0x03,sf); + material_size = read_16bitLE(material_offset+0x04,sf); + sample_rate = (uint16_t)read_16bitLE(material_offset+0x06,sf); + stream_size = read_32bitLE(material_offset+0x08,sf); + num_samples = read_32bitLE(material_offset+0x0c,sf); - loop_start = read_32bitLE(material_offset+0x10,streamFile); - loop_end = read_32bitLE(material_offset+0x14,streamFile); - extradata_size = read_32bitLE(material_offset+0x18,streamFile); + loop_start = read_32bitLE(material_offset+0x10,sf); + loop_end = read_32bitLE(material_offset+0x14,sf); + extradata_size = read_32bitLE(material_offset+0x18,sf); /* rest: ? (empty or 0x3f80) */ 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)] */ vgmstream->coding_type = coding_MSADPCM; 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 * (base samples may have more than possible and read over file size otherwise, very strange) * loop_end seems to exist even with loop disabled */ - vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile); - vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile); - vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile); + vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, sf); + vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, sf); + vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, sf); break; } @@ -289,7 +289,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { ovmi.total_subsongs = total_subsongs; 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) { ogg_vgmstream->num_streams = vgmstream->num_streams; 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)] */ 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; 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) * 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->loop_start_sample = read_32bitLE(material_offset+0x10,streamFile);//loop_start; + vgmstream->num_samples = read_32bitLE(material_offset+0x0c,sf);//num_samples; + vgmstream->loop_start_sample = read_32bitLE(material_offset+0x10,sf);//loop_start; vgmstream->loop_end_sample = loop_end; break; } @@ -331,7 +331,7 @@ VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) { } /* open the file for reading */ - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + if ( !vgmstream_open_stream(vgmstream, sf, start_offset) ) goto fail; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ao.c b/Frameworks/vgmstream/vgmstream/src/meta/ao.c index c8af91d39..5c151ff9e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ao.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ao.c @@ -27,7 +27,7 @@ VGMSTREAM* init_vgmstream_ao(STREAMFILE *sf) { /* AlphaOgg defines up to 16 loop points for some reason */ 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 goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h index fbe455952..aed4fd907 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/bar_streamfile.h @@ -1,82 +1,82 @@ -#ifndef _BAR_STREAMFILE_H_ -#define _BAR_STREAMFILE_H_ -#include "../streamfile.h" - -/* a streamfile wrapping another for decryption */ - -enum {BAR_KEY_LENGTH = 16}; - -// don't know if this is unique, but seems accurate -static const uint8_t bar_key[BAR_KEY_LENGTH] = { - 0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6, - 0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80 -}; - -typedef struct _BARSTREAMFILE { - STREAMFILE sf; - STREAMFILE *real_file; -} BARSTREAMFILE; - - -/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file); - - -static size_t read_bar(BARSTREAMFILE *streamFile, uint8_t *dest, off_t offset, size_t length) { - off_t i; - size_t read_length = streamFile->real_file->read(streamFile->real_file, dest, offset, length); - - for (i = 0; i < read_length; i++) { - dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH]; - } - - return read_length; -} - -static size_t get_size_bar(BARSTREAMFILE *streamFile) { - return streamFile->real_file->get_size(streamFile->real_file); -} - -static size_t get_offset_bar(BARSTREAMFILE *streamFile) { - return streamFile->real_file->get_offset(streamFile->real_file); -} - -static void get_name_bar(BARSTREAMFILE *streamFile, char *name, size_t length) { - streamFile->real_file->get_name(streamFile->real_file, name, length); -} - -STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) { - STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize); - if (!newfile) - return NULL; - - return wrap_bar_STREAMFILE(newfile); -} - -static void close_bar(BARSTREAMFILE *streamFile) { - streamFile->real_file->close(streamFile->real_file); - free(streamFile); - return; -} - - -/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) { - BARSTREAMFILE *streamfile = malloc(sizeof(BARSTREAMFILE)); - - if (!streamfile) - return NULL; - - memset(streamfile, 0, sizeof(BARSTREAMFILE)); - - streamfile->sf.read = (void*)read_bar; - streamfile->sf.get_size = (void*)get_size_bar; - streamfile->sf.get_offset = (void*)get_offset_bar; - streamfile->sf.get_name = (void*)get_name_bar; - streamfile->sf.open = (void*)open_bar; - streamfile->sf.close = (void*)close_bar; - - streamfile->real_file = file; - - return &streamfile->sf; -} - -#endif /* _BAR_STREAMFILE_H_ */ +#ifndef _BAR_STREAMFILE_H_ +#define _BAR_STREAMFILE_H_ +#include "../streamfile.h" + +/* a streamfile wrapping another for decryption */ + +enum {BAR_KEY_LENGTH = 16}; + +// don't know if this is unique, but seems accurate +static const uint8_t bar_key[BAR_KEY_LENGTH] = { + 0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6, + 0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80 +}; + +typedef struct _BARSTREAMFILE { + STREAMFILE sf; + STREAMFILE *real_file; +} BARSTREAMFILE; + + +/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file); + + +static size_t read_bar(BARSTREAMFILE *streamFile, uint8_t *dest, off_t offset, size_t length) { + off_t i; + size_t read_length = streamFile->real_file->read(streamFile->real_file, dest, offset, length); + + for (i = 0; i < read_length; i++) { + dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH]; + } + + return read_length; +} + +static size_t get_size_bar(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_size(streamFile->real_file); +} + +static size_t get_offset_bar(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_offset(streamFile->real_file); +} + +static void get_name_bar(BARSTREAMFILE *streamFile, char *name, size_t length) { + streamFile->real_file->get_name(streamFile->real_file, name, length); +} + +static STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) { + STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize); + if (!newfile) + return NULL; + + return wrap_bar_STREAMFILE(newfile); +} + +static void close_bar(BARSTREAMFILE *streamFile) { + streamFile->real_file->close(streamFile->real_file); + free(streamFile); + return; +} + + +/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) { + BARSTREAMFILE *streamfile = malloc(sizeof(BARSTREAMFILE)); + + if (!streamfile) + return NULL; + + memset(streamfile, 0, sizeof(BARSTREAMFILE)); + + streamfile->sf.read = (void*)read_bar; + streamfile->sf.get_size = (void*)get_size_bar; + streamfile->sf.get_offset = (void*)get_offset_bar; + streamfile->sf.get_name = (void*)get_name_bar; + streamfile->sf.open = (void*)open_bar; + streamfile->sf.close = (void*)close_bar; + + streamfile->real_file = file; + + return &streamfile->sf; +} + +#endif /* _BAR_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dec.c b/Frameworks/vgmstream/vgmstream/src/meta/dec.c index 77ac6cd21..dbad8613a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/dec.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/dec.c @@ -2,11 +2,11 @@ #include "../layout/layout.h" #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) */ -VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; +VGMSTREAM* init_vgmstream_dec(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset; off_t riff_off = 0x00; size_t pcm_size = 0; @@ -16,42 +16,42 @@ VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) { /* checks * .dec: main, * .de2: Gurumin (PC) */ - if ( !check_extensions(streamFile,"dec,de2") ) + if (!check_extensions(sf,"dec,de2")) goto fail; /* 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 */ - if (read_32bitLE(0x04,streamFile) != 0x0b) goto fail; + if (read_32bitLE(0x04,sf) != 0x0b) goto fail; /* 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 */ - if (read_32bitBE(riff_off+0x00,streamFile) != 0x52494646 || /* "RIFF" */ - read_32bitBE(riff_off+0x08,streamFile) != 0x57415645) /* "WAVE" */ + if (!is_id32be(riff_off+0x00,sf, "RIFF") || + !is_id32be(riff_off+0x08,sf, "WAVE")) 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; 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 */ } - else if (read_32bitBE(riff_off+0x0c,streamFile) == 0x666D7420) { /* "fmt " (rest) */ - //if (read_32bitLE(riff_off+0x10,streamFile) != 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+0x20,streamFile) != 4 || - read_16bitLE(riff_off+0x22,streamFile) != 16) goto fail; /* 16-bit */ + else if (is_id32be(riff_off+0x0c,sf, "fmt ")) { + //if (read_32bitLE(riff_off+0x10,sf) != 0x12) goto fail; /* 0x10 in some */ + if (read_16bitLE(riff_off+0x14,sf) != 0x01) goto fail; /* PCM (actually MS-ADPCM) */ + if (read_16bitLE(riff_off+0x20,sf) != 4 || + read_16bitLE(riff_off+0x22,sf) != 16) goto fail; /* 16-bit */ - channel_count = read_16bitLE(riff_off+0x16,streamFile); - sample_rate = read_32bitLE(riff_off+0x18,streamFile); - if (read_32bitBE(riff_off+0x24,streamFile) == 0x64617461) { /* "data" size except in some Zwei!! */ - pcm_size = read_32bitLE(riff_off+0x28,streamFile); + channel_count = read_16bitLE(riff_off+0x16,sf); + sample_rate = read_32bitLE(riff_off+0x18,sf); + if (read_32bitBE(riff_off+0x24,sf) == 0x64617461) { /* "data" size except in some Zwei!! */ + pcm_size = read_32bitLE(riff_off+0x28,sf); } else { - pcm_size = read_32bitLE(riff_off+0x04,streamFile) - 0x24; + pcm_size = read_32bitLE(riff_off+0x04,sf) - 0x24; } } else { @@ -62,7 +62,7 @@ VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) { goto fail; 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 */ @@ -79,7 +79,7 @@ VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile) { vgmstream->frame_size = 0x800; vgmstream->layout_type = layout_blocked_dec; - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; return vgmstream; @@ -91,7 +91,7 @@ fail: /* Falcom loves loop points in external text files, here we parse them */ 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; off_t txt_offset = 0x00; 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 */ - if ((streamText = open_streamfile_by_filename(streamFile,"bgm.tbl")) != NULL) { + if ((streamText = open_streamfile_by_filename(sf,"bgm.tbl")) != NULL) { 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; } - 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; } - else if ((streamText = open_streamfile_by_filename(streamFile,"map.itm")) != NULL) { + else if ((streamText = open_streamfile_by_filename(sf,"map.itm")) != NULL) { type = GURUMIN; } else { goto end; } - get_streamfile_filename(streamFile,filename,TXT_LINE_MAX); + get_streamfile_filename(sf,filename,TXT_LINE_MAX); /* read line by line */ 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; } break; + + default: + break; } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c index 90296a555..814a4473a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -508,7 +508,7 @@ fail: } /* 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] = { /* standard cases, replace map part with mus part (from the end to preserve prefixes) */ {"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 */ - musFile = open_mapfile_pair(sf, i, num_tracks); + musFile = open_mapfile_pair(sf, i);//, num_tracks if (!musFile) 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); } break; + default: + goto fail; } /* 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.stream_offset = start_offset; break; + default: + goto fail; } } else { 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 - 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}; 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[1] = NULL; break; + default: + goto fail; } } else { data_size = calculate_eaac_size(sf_head, ea, ea->num_samples, ea->stream_offset, 0); @@ -1603,29 +1609,29 @@ static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *sf switch(eaac->codec) { #ifdef VGM_USE_FFMPEG - case EAAC_CODEC_EAXMA: { - eaac_header temp_eaac = *eaac; /* equivalent to memcpy... I think */ - temp_eaac.loop_flag = 0; - temp_eaac.num_samples = num_samples[i]; + case EAAC_CODEC_EAXMA: { + eaac_header temp_eaac = *eaac; /* equivalent to memcpy... I think */ + temp_eaac.loop_flag = 0; + temp_eaac.num_samples = num_samples[i]; - start_offset = 0x00; /* must point to the custom streamfile's beginning */ + start_offset = 0x00; /* must point to the custom streamfile's beginning */ - /* layers inside segments, how trippy */ - data->segments[i]->layout_data = build_layered_eaaudiocore(sf_data, &temp_eaac, offsets[i]); - if (!data->segments[i]->layout_data) goto fail; - data->segments[i]->coding_type = coding_FFmpeg; - data->segments[i]->layout_type = layout_layered; - break; - } + /* layers inside segments, how trippy */ + data->segments[i]->layout_data = build_layered_eaaudiocore(sf_data, &temp_eaac, offsets[i]); + if (!data->segments[i]->layout_data) goto fail; + data->segments[i]->coding_type = coding_FFmpeg; + data->segments[i]->layout_type = layout_layered; + break; + } #endif - case EAAC_CODEC_XAS1: { - start_offset = offsets[i]; + case EAAC_CODEC_XAS1: { + start_offset = offsets[i]; - data->segments[i]->coding_type = coding_EA_XAS_V1; - data->segments[i]->layout_type = layout_blocked_ea_sns; - break; - } + data->segments[i]->coding_type = coding_EA_XAS_V1; + data->segments[i]->layout_type = layout_blocked_ea_sns; + break; + } #ifdef VGM_USE_MPEG case EAAC_CODEC_EALAYER3_V1: @@ -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_end_sample = eaac->loop_end; -#ifdef VGM_USE_FFMPEG switch(eaac->codec) { +#ifdef VGM_USE_FFMPEG /* 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) */ 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; break; } - - } -#else - goto fail; #endif + default: + goto fail; + } if (!vgmstream_open_stream(data->layers[i], temp_sf, 0x00)) { goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index 34fb731a6..292f78a4c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -637,7 +637,7 @@ fail: /* 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] = { /* standard cases, replace map part with mus part (from the end to preserve prefixes) */ {"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); 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; /* @@ -994,7 +994,7 @@ VGMSTREAM* init_vgmstream_ea_mpf_mus(STREAMFILE* sf) { goto fail; /* 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) goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c index 0bade7e6a..606df9213 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c @@ -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* vgmstream = 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; int total_subsongs, target_subsong = sf->stream_index; @@ -35,9 +35,12 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { if (get_streamfile_size(sf) <= 0x1000) 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) */ if (check_extensions(sf, "at3")) goto fail; +#endif 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); 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; /* 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)) { - loop_start = get_s32le(posbuf+0); - loop_end = get_s32le(posbuf+4); + if (read_pos_file(posbuf, sizeof(posbuf), sf)) { + loop_start = get_s32le(posbuf+0x00); + loop_end = get_s32le(posbuf+0x04); 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 */ num_samples = get_s32le(posbuf+8); } @@ -82,6 +85,9 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { * .mus: Marc Ecko's Getting Up (PC) */ if (!num_samples && check_extensions(sf, "mp3,lmp3,mus")) { num_samples = mpeg_get_samples(sf, 0x00, get_streamfile_size(sf)); + + /* this seems correct thankfully */ + //ffmpeg_set_skip_samples(data, encoder_delay); } #endif @@ -100,18 +106,22 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { /* default but often inaccurate when calculated using bitrate (wrong for VBR) */ 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 */ - vgmstream = allocate_vgmstream(data->channels, loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = data->sampleRate; vgmstream->meta_type = meta_FFMPEG; - vgmstream->coding_type = coding_FFmpeg; + vgmstream->sample_rate = sample_rate; + vgmstream->codec_data = data; + vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; 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) { // 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) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb_encrypted_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/fsb_encrypted_streamfile.h index 7468f391d..1492366ae 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb_encrypted_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb_encrypted_streamfile.h @@ -1,5 +1,5 @@ #ifndef _FSB_ENCRYPTED_STREAMFILE_H_ -#define _FSB_ENCRYPTED_H_ +#define _FSB_ENCRYPTED_STREAMFILE_H_ #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; } -#endif /* _FSB5_STREAMFILE_H_ */ +#endif /* _FSB_ENCRYPTED_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/genh.c b/Frameworks/vgmstream/vgmstream/src/meta/genh.c index eb8a6f0a6..b7d1b82fd 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/genh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/genh.c @@ -307,7 +307,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { if ( !ffmpeg_data ) goto fail; //if (vgmstream->num_samples == 0) - // vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */ + // vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); /* sometimes works */ } else { /* fake header FFmpeg */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gin.c b/Frameworks/vgmstream/vgmstream/src/meta/gin.c index 08694536a..1ff4f71d3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/gin.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/gin.c @@ -2,16 +2,17 @@ #include "../coding/coding.h" /* .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; off_t start_offset; int loop_flag, channel_count, sample_rate, num_samples; - if (!check_extensions(streamFile, "gin")) + if (!check_extensions(sf, "gin")) goto fail; /* 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; /* 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 */ /* always LE even on X360/PS3 */ - num_samples = read_32bitLE(0x18, streamFile); - sample_rate = read_32bitLE(0x1c, streamFile); + num_samples = read_u32le(0x18, sf); + sample_rate = read_u32le(0x1c, sf); start_offset = 0x20 + - (read_32bitLE(0x10, streamFile) + 1) * 0x04 + - (read_32bitLE(0x14, streamFile) + 1) * 0x04; + (read_u32le(0x10, sf) + 1) * 0x04 + + (read_u32le(0x14, sf) + 1) * 0x04; channel_count = 1; loop_flag = 0; @@ -44,7 +45,7 @@ VGMSTREAM * init_vgmstream_gin(STREAMFILE *streamFile) { /* calculate size for TMX */ 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; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca.c b/Frameworks/vgmstream/vgmstream/src/meta/hca.c index 23f79066a..26db6871b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca.c @@ -1,6 +1,7 @@ #include "meta.h" #include "hca_keys.h" #include "../coding/coding.h" +#include "clHCA.h" //#define 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 * vgmstream = NULL; + VGMSTREAM* vgmstream = NULL; hca_codec_data* hca_data = NULL; clHCA_stInfo* hca_info; @@ -152,26 +153,32 @@ 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) { const size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info); int best_score = -1; - int i,j; + int i; *p_keycode = 0xCC55463930DBE1AB; /* defaults to PSO2 key, most common */ for (i = 0; i < keys_length; i++) { 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); if (best_score == 1) goto done; - if (subkeys_size > 0 && subkey == 0) { - for (j = 0; j < subkeys_size; j++) { - test_key(hca_data, key, subkeys[j], &best_score, p_keycode); - if (best_score == 1) - 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) { + for (j = 0; j < subkeys_size; j++) { + test_key(hca_data, key, subkeys[j], &best_score, p_keycode); + if (best_score == 1) + goto done; + } } } +#endif } done: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index 50aca5980..51ed01b36 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h @@ -5,8 +5,10 @@ typedef struct { 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 */ +#endif } hcakey_info; @@ -410,6 +412,9 @@ static const hcakey_info hcakey_list[] = { /* Dragon Quest Tact (Android) */ {3234477171400153310}, // 2CE32BD9B36A98DE + /* Alchemy Stars (Android) */ + {1564789515523}, // 0000016C54B92503 + /* D4DJ Groovy Mix (Android) [base files] */ {393410674916959300}, // 0575ACECA945A444 /* 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 {0x52c250eade92393b}, //music_9010001 {0xfea0d6adff136868}, //music_9050001 + + // Mini 4WD Hyper Dash Grand Prix (Android) + {7957824642808300098}, // 6E6FDF59AB704242 }; #endif/*_HCA_KEYS_H_*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/his.c b/Frameworks/vgmstream/vgmstream/src/meta/his.c index 121141e93..e9b9fdcd4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/his.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/his.c @@ -3,49 +3,49 @@ /* HIS - Her Interactive games [Nancy Drew series (PC)] */ -VGMSTREAM * init_vgmstream_his(STREAMFILE *streamFile) { +VGMSTREAM * init_vgmstream_his(STREAMFILE *sf) { VGMSTREAM * vgmstream = NULL; int channel_count, loop_flag = 0, bps, sample_rate, num_samples, version; off_t start_offset; /* checks */ - if (!check_extensions(streamFile, "his")) + if (!check_extensions(sf, "his")) 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) */ version = 0; - channel_count = read_16bitLE(0x16,streamFile); - sample_rate = read_32bitLE(0x18,streamFile); + channel_count = read_16bitLE(0x16,sf); + sample_rate = read_32bitLE(0x18,sf); /* 0x1c: bitrate */ /* 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; - 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; } - else if (read_32bitBE(0x00,streamFile) == 0x48495300) { /* HIS\0 */ + else if (read_32bitBE(0x00,sf) == 0x48495300) { /* HIS\0 */ /* most(?) others */ - version = read_32bitLE(0x04,streamFile); + version = read_32bitLE(0x04,sf); /* 0x08: codec */ - channel_count = read_16bitLE(0x0a,streamFile); - sample_rate = read_32bitLE(0x0c,streamFile); + channel_count = read_16bitLE(0x0a,sf); + sample_rate = read_32bitLE(0x0c,sf); /* 0x10: bitrate */ /* 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" */ if (version == 1) 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) */ - 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) */ else goto fail; @@ -60,7 +60,7 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *streamFile) { ogg_vorbis_meta_info_t ovmi = {0}; 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 goto fail; #endif @@ -89,7 +89,7 @@ VGMSTREAM * init_vgmstream_his(STREAMFILE *streamFile) { goto fail; } - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) goto fail; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ikm.c b/Frameworks/vgmstream/vgmstream/src/meta/ikm.c index 7c2456ebd..57962d15c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ikm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ikm.c @@ -80,7 +80,7 @@ VGMSTREAM* init_vgmstream_ikm_pc(STREAMFILE* sf) { ovmi.loop_flag = ovmi.loop_end > 0; 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 goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index c41216aec..6f0865220 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -137,9 +137,11 @@ typedef struct { off_t scd_xor_length; uint32_t xor_value; + //ov_callbacks *callbacks + } 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 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_piff_tpcm(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mogg.c b/Frameworks/vgmstream/vgmstream/src/meta/mogg.c index 9054d2350..40be9d998 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mogg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mogg.c @@ -10,12 +10,12 @@ #include "../coding/coding.h" /* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */ -VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) { +VGMSTREAM* init_vgmstream_mogg(STREAMFILE *sf) { #ifdef VGM_USE_VORBIS off_t start_offset; /* checks */ - if (!check_extensions(streamFile, "mogg")) + if (!check_extensions(sf, "mogg")) goto fail; { @@ -24,8 +24,8 @@ VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) { ovmi.meta_type = meta_MOGG; - start_offset = read_32bitLE(0x04, streamFile); - result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); + start_offset = read_32bitLE(0x04, sf); + result = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi); if (result != NULL) { return result; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mp4.c b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c index 473845c63..b1850f2e8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mp4.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c @@ -163,11 +163,14 @@ fail: #ifdef VGM_USE_FFMPEG typedef struct { + int channels; + int sample_rate; int32_t num_samples; int loop_flag; int32_t loop_start; int32_t loop_end; int32_t encoder_delay; + int subsongs; } mp4_header; 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); + /* 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 */ - vgmstream = allocate_vgmstream(ffmpeg_data->channels, mp4.loop_flag); + vgmstream = allocate_vgmstream(mp4.channels, mp4.loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_MP4; - vgmstream->sample_rate = ffmpeg_data->sampleRate; + vgmstream->sample_rate = mp4.sample_rate; 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_end_sample = mp4.loop_end; vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; 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); - if (mp4.encoder_delay) - ffmpeg_set_skip_samples(vgmstream->codec_data, mp4.encoder_delay); + vgmstream->channel_layout = ffmpeg_get_channel_layout(ffmpeg_data); + + /* needed for CRI MP4, otherwise FFmpeg usually reads standard delay */ + ffmpeg_set_skip_samples(vgmstream->codec_data, mp4.encoder_delay); return vgmstream; fail: - if (ffmpeg_data) { - free_ffmpeg(ffmpeg_data); - if (vgmstream) vgmstream->codec_data = NULL; + free_ffmpeg(ffmpeg_data); + if (vgmstream) { + vgmstream->codec_data = NULL; + close_vgmstream(vgmstream); } - if (vgmstream) close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msf.c b/Frameworks/vgmstream/vgmstream/src/meta/msf.c index a8d2ffb4f..5e3e21cb8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/msf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/msf.c @@ -108,7 +108,7 @@ VGMSTREAM* init_vgmstream_msf(STREAMFILE* sf) { encoder_delay = 1024 + 69*2; block_align = (codec==4 ? 0x60 : (codec==5 ? 0x98 : 0xC0)) * vgmstream->channels; 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->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) 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)); - if (!ffmpeg_data) goto fail; - vgmstream->codec_data = ffmpeg_data; + vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, 0);; + if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - //todo use same calcs as above - vgmstream->num_samples = (int64_t)data_size * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate; - if (loop_flag) { - 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; - } + vgmstream->num_samples = mpeg_get_samples_clean(sf, start_offset, data_size, &loop_start, &loop_end, is_vbr); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mus_vc.c b/Frameworks/vgmstream/vgmstream/src/meta/mus_vc.c index 1159b5ced..f992f5331 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mus_vc.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mus_vc.c @@ -1,79 +1,79 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* .MUS - Vicious Cycle games [Dinotopia: The Sunstone Odyssey (GC/Xbox), Robotech: Battlecry (PS2/Xbox)] */ -VGMSTREAM * init_vgmstream_mus_vc(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count, sample_rate; - int big_endian, type; - int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL; - - - /* checks */ - if (!check_extensions(streamFile, "mus")) - goto fail; - - if (read_32bitBE(0x08,streamFile) != 0xBBBBBBBB && - read_32bitBE(0x14,streamFile) != 0xBBBBBBBB && - read_32bitBE(0x2c,streamFile) != 0xBEBEBEBE) - goto fail; - - big_endian = (read_32bitBE(0x00,streamFile) == 0xFBBFFBBF); - read_32bit = big_endian ? read_32bitBE : read_32bitLE; - - type = read_32bit(0x04, streamFile); - /* 0x08: pseudo size? */ - /* other fields may be chunk sizes and lesser stuff */ - /* 0x88: codec header */ - - channel_count = read_32bit(0x54,streamFile); /* assumed */ - if (channel_count != 1) goto fail; - sample_rate = read_32bit(0x58,streamFile); - loop_flag = 1; /* most files repeat except small jingles, but smaller ambient tracks also repeat */ - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_MUS_VC; - vgmstream->sample_rate = sample_rate; - - switch(type) { - case 0x01: - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_none; - vgmstream->num_samples = dsp_bytes_to_samples(read_32bit(0xB0,streamFile), vgmstream->channels); - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - - start_offset = 0xB8; - dsp_read_coefs_be(vgmstream,streamFile,0x88,0x00); - dsp_read_hist_be (vgmstream,streamFile,0xac,0x00); - break; - - case 0x02: - vgmstream->coding_type = coding_XBOX_IMA; - vgmstream->layout_type = layout_none; - vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bit(0x9a,streamFile), vgmstream->channels); - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - - start_offset = 0x9e; - break; - - default: - goto fail; - } - - read_string(vgmstream->stream_name,0x14, 0x34,streamFile); /* repeated at 0x64, size at 0x30/0x60 */ - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .MUS - Vicious Cycle games [Dinotopia: The Sunstone Odyssey (GC/Xbox), Robotech: Battlecry (PS2/Xbox)] */ +VGMSTREAM* init_vgmstream_mus_vc(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels, sample_rate; + int big_endian, type; + int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL; + + + /* checks */ + if (!check_extensions(sf, "mus")) + goto fail; + + if (read_u32be(0x08,sf) != 0xBBBBBBBB && + read_u32be(0x14,sf) != 0xBBBBBBBB && + read_u32be(0x2c,sf) != 0xBEBEBEBE) + goto fail; + + big_endian = (read_u32be(0x00,sf) == 0xFBBFFBBF); + read_32bit = big_endian ? read_32bitBE : read_32bitLE; + + type = read_32bit(0x04, sf); + /* 0x08: pseudo size? */ + /* other fields may be chunk sizes and lesser stuff */ + /* 0x88: codec header */ + + channels = read_32bit(0x54,sf); /* assumed */ + if (channels != 1) goto fail; + sample_rate = read_32bit(0x58,sf); + loop_flag = 1; /* most files repeat except small jingles, but smaller ambient tracks also repeat */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MUS_VC; + vgmstream->sample_rate = sample_rate; + + switch(type) { + case 0x01: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = dsp_bytes_to_samples(read_32bit(0xB0,sf), vgmstream->channels); + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + + start_offset = 0xB8; + dsp_read_coefs_be(vgmstream,sf,0x88,0x00); + dsp_read_hist_be (vgmstream,sf,0xac,0x00); + break; + + case 0x02: + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bit(0x9a,sf), vgmstream->channels); + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + + start_offset = 0x9e; + break; + + default: + goto fail; + } + + read_string(vgmstream->stream_name,0x14, 0x34,sf); /* repeated at 0x64, size at 0x30/0x60 */ + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/naac.c b/Frameworks/vgmstream/vgmstream/src/meta/naac.c index 6069dd002..67ba55e43 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/naac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/naac.c @@ -6,7 +6,7 @@ VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag, channels; + int loop_flag, channels, skip_samples; size_t data_size; @@ -22,6 +22,7 @@ VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) { start_offset = 0x1000; loop_flag = (read_s32le(0x18,sf) != 0); channels = read_s32le(0x08,sf); + skip_samples = 1024; /* raw AAC doesn't set this */ /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels, loop_flag); @@ -42,15 +43,14 @@ VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) { #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; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; /* 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 -= 1024; - vgmstream->loop_end_sample -= 1024; + vgmstream->num_samples -= skip_samples; + vgmstream->loop_end_sample -= skip_samples; /* for some reason last frame is ignored/bugged in various decoders (gives EOF errors) */ } #else diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_str_cauldron.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_str_cauldron.c index 7ef70aeba..155648210 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_str_cauldron.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_str_cauldron.c @@ -1,46 +1,46 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* .str - Cauldron/Conan mini-header + interleaved dsp data [Conan (GC)] */ -VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int channel_count, loop_flag; - - - /* checks */ - if (!check_extensions(streamFile, "str")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0xFAAF0001) /* header id */ - goto fail; - - channel_count = 2; /* always loop & stereo */ - loop_flag = 1; - start_offset = 0x60; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitBE(0x04,streamFile); - vgmstream->num_samples = read_32bitBE(0x08,streamFile); - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->meta_type = meta_DSP_STR; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile); - - dsp_read_coefs_be(vgmstream, streamFile, 0x10, 0x20); - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .str - Cauldron/Conan mini-header + interleaved dsp data [Conan (GC)] */ +VGMSTREAM* init_vgmstream_ngc_str(STREAMFILE *sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int channels, loop_flag; + + + /* checks */ + if (!check_extensions(sf, "str")) + goto fail; + if (read_u32be(0x00,sf) != 0xFAAF0001) /* header id */ + goto fail; + + channels = 2; /* always loop & stereo */ + loop_flag = 1; + start_offset = 0x60; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_s32be(0x04,sf); + vgmstream->num_samples = read_s32be(0x08,sf); + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->meta_type = meta_DSP_STR; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_u32be(0x0C,sf); + + dsp_read_coefs_be(vgmstream, sf, 0x10, 0x20); + + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nus3bank_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/nus3bank_streamfile.h index a57dac781..1ba65bb0e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nus3bank_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/nus3bank_streamfile.h @@ -62,6 +62,7 @@ static STREAMFILE* setup_nus3bank_streamfile(STREAMFILE *sf, off_t start) { /* find "data" */ pos = 0x0c; + data_pos = 0; while(pos < sizeof(buf)) { chunk_type = get_u32be(buf + pos + 0x00) ^ chunk_key; chunk_size = get_u32be(buf + pos + 0x04) ^ chunk_key; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nwav.c b/Frameworks/vgmstream/vgmstream/src/meta/nwav.c index 3d2309e2c..a9557722d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nwav.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nwav.c @@ -1,57 +1,57 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* NWAV - from Chunsoft games [Fuurai no Shiren Gaiden: Onnakenshi Asuka Kenzan! (PC)] */ -VGMSTREAM * init_vgmstream_nwav(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - - - /* checks */ - /* .nwav: header id (no filenames in bigfiles) */ - if ( !check_extensions(streamFile,"nwav") ) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x4E574156) /* "NWAV" */ - goto fail; - - -#ifdef VGM_USE_VORBIS - { - ogg_vorbis_meta_info_t ovmi = {0}; - int channels; - - /* 0x04: version? */ - /* 0x08: crc? */ - ovmi.stream_size = read_32bitLE(0x0c, streamFile); - ovmi.loop_end = read_32bitLE(0x10, streamFile); /* num_samples, actually */ - /* 0x14: sample rate */ - /* 0x18: bps? (16) */ - channels = read_8bit(0x19, streamFile); - start_offset = read_16bitLE(0x1a, streamFile); - - ovmi.loop_flag = read_16bitLE(0x1c, streamFile) != 0; /* loop count? -1 = loops */ - /* 0x1e: always 2? */ - /* 0x20: always 1? */ - ovmi.loop_start = read_32bitLE(0x24, streamFile); - /* 0x28: always 1? */ - /* 0x2a: always 1? */ - /* 0x2c: always null? */ - - ovmi.meta_type = meta_NWAV; - - /* values are in resulting bytes */ - ovmi.loop_start = ovmi.loop_start / 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); - } -#else - goto fail; -#endif - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* NWAV - from Chunsoft games [Fuurai no Shiren Gaiden: Onnakenshi Asuka Kenzan! (PC)] */ +VGMSTREAM * init_vgmstream_nwav(STREAMFILE *sf) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + + + /* checks */ + /* .nwav: header id (no filenames in bigfiles) */ + if ( !check_extensions(sf,"nwav") ) + goto fail; + if (read_32bitBE(0x00,sf) != 0x4E574156) /* "NWAV" */ + goto fail; + + +#ifdef VGM_USE_VORBIS + { + ogg_vorbis_meta_info_t ovmi = {0}; + int channels; + + /* 0x04: version? */ + /* 0x08: crc? */ + ovmi.stream_size = read_32bitLE(0x0c, sf); + ovmi.loop_end = read_32bitLE(0x10, sf); /* num_samples, actually */ + /* 0x14: sample rate */ + /* 0x18: bps? (16) */ + channels = read_8bit(0x19, sf); + start_offset = read_16bitLE(0x1a, sf); + + ovmi.loop_flag = read_16bitLE(0x1c, sf) != 0; /* loop count? -1 = loops */ + /* 0x1e: always 2? */ + /* 0x20: always 1? */ + ovmi.loop_start = read_32bitLE(0x24, sf); + /* 0x28: always 1? */ + /* 0x2a: always 1? */ + /* 0x2c: always null? */ + + ovmi.meta_type = meta_NWAV; + + /* values are in resulting bytes */ + ovmi.loop_start = ovmi.loop_start / sizeof(int16_t) / channels; + ovmi.loop_end = ovmi.loop_end / sizeof(int16_t) / channels; + + vgmstream = init_vgmstream_ogg_vorbis_config(sf, start_offset, &ovmi); + } +#else + goto fail; +#endif + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c index 3df90c7a4..beb134158 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c @@ -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) * - .isl: looping table (encrypted like the files) */ 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 */ char isl_path[PATH_LIMIT]; 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; - dec_sf = setup_ogg_vorbis_streamfile(islFile, cfg); + dec_sf = setup_ogg_vorbis_streamfile(sf_isl, cfg); if (dec_sf) { off_t loop_offset; char basename[PATH_LIMIT]; @@ -327,7 +327,7 @@ VGMSTREAM* init_vgmstream_ogg_vorbis(STREAMFILE* 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 (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_len = 1; cfg.is_header_swap = 1; @@ -416,7 +416,7 @@ VGMSTREAM* init_vgmstream_ogg_vorbis(STREAMFILE* sf) { 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); return vgmstream; @@ -426,7 +426,7 @@ fail: 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; ogg_vorbis_codec_data* data = NULL; ogg_vorbis_io io = {0}; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogv_3rdeye.c b/Frameworks/vgmstream/vgmstream/src/meta/ogv_3rdeye.c index 9a930e581..553d5109c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogv_3rdeye.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogv_3rdeye.c @@ -27,7 +27,7 @@ VGMSTREAM* init_vgmstream_ogv_3rdeye(STREAMFILE* sf) { ovmi.meta_type = meta_OGV_3RDEYE; 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 goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/opus.c b/Frameworks/vgmstream/vgmstream/src/meta/opus.c index e7e28a303..454bd07bc 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/opus.c @@ -157,16 +157,16 @@ VGMSTREAM* init_vgmstream_opus_n1(STREAMFILE* sf) { int num_samples, loop_start, loop_end; /* checks */ - if ( !check_extensions(sf,"opus,lopus")) + if (!check_extensions(sf,"opus,lopus")) goto fail; - if (!((read_32bitBE(0x04,sf) == 0x00000000 && read_32bitBE(0x0c,sf) == 0x00000000) || - (read_32bitBE(0x04,sf) == 0xFFFFFFFF && read_32bitBE(0x0c,sf) == 0xFFFFFFFF))) + if (!((read_u32be(0x04,sf) == 0x00000000 && read_u32be(0x0c,sf) == 0x00000000) || + (read_u32be(0x04,sf) == 0xFFFFFFFF && read_u32be(0x0c,sf) == 0xFFFFFFFF))) goto fail; offset = 0x10; num_samples = 0; - loop_start = read_32bitLE(0x00,sf); - loop_end = read_32bitLE(0x08,sf); + loop_start = read_s32le(0x00,sf); + loop_end = read_s32le(0x08,sf); return init_vgmstream_opus(sf, meta_OPUS, offset, num_samples,loop_start,loop_end); fail: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/piff_tpcm.c b/Frameworks/vgmstream/vgmstream/src/meta/piff_tpcm.c new file mode 100644 index 000000000..c1c1b4bef --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/piff_tpcm.c @@ -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; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_sfs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sfs.c index ebe04561a..97de7a32b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_sfs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sfs.c @@ -1,64 +1,53 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* SFS (from Baroque) */ -VGMSTREAM * init_vgmstream_sfs(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; +/* SFS - from Sting games [Baroque (PS2)] */ +VGMSTREAM* init_vgmstream_sfs(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag; - int channel_count; + int loop_flag, channels, sample_rate; + 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 */ - if (read_32bitBE(0x00,streamFile) != 0x53544552) /* "STER" */ + /* checks */ + /* .sfs: bigfile extension (no apparent names) */ + if (!check_extensions(sf, "sfs")) goto fail; - loop_flag = (read_32bitLE(0x08,streamFile)!=0xFFFFFFFF); - channel_count = 2; - + if (!is_id32be(0x00,sf, "STER")) + 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 */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x30; - 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->meta_type = meta_SFS; + vgmstream->sample_rate = sample_rate; + 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->interleave_block_size = 0x10; - vgmstream->meta_type = meta_SFS; - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } + read_string(vgmstream->stream_name,0x10+1, 0x20,sf); + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vas.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vas.c index f2f3ed55d..d01c0561a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vas.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vas.c @@ -3,43 +3,43 @@ /* .VAS - from Konami Jikkyou Powerful Pro Yakyuu games */ -VGMSTREAM * init_vgmstream_ps2_vas(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; +VGMSTREAM* init_vgmstream_ps2_vas(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count; + int loop_flag, channels; /* checks */ - if (!check_extensions(streamFile, "vas")) + if (!check_extensions(sf, "vas")) goto fail; - if (read_32bitLE(0x00,streamFile) + 0x800 != get_streamfile_size(streamFile)) + if (read_u32le(0x00,sf) + 0x800 != get_streamfile_size(sf)) goto fail; - loop_flag = (read_32bitLE(0x10,streamFile) != 0); - channel_count = 2; + loop_flag = (read_u32le(0x10,sf) != 0); + channels = 2; start_offset = 0x800; /* 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; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; 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->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x200; - vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x00,streamFile), channel_count); - vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x14,streamFile), channel_count); + vgmstream->num_samples = ps_bytes_to_samples(read_u32le(0x00,sf), channels); + vgmstream->loop_start_sample = ps_bytes_to_samples(read_u32le(0x14,sf), channels); 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; return vgmstream; @@ -50,35 +50,35 @@ fail: /* .VAS in containers */ -VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; +VGMSTREAM* init_vgmstream_ps2_vas_container(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; off_t subfile_offset = 0; size_t subfile_size = 0; - int total_subsongs, target_subsong = streamFile->stream_index; + int total_subsongs, target_subsong = sf->stream_index; /* checks */ - if (!check_extensions(streamFile, "vas")) + if (!check_extensions(sf, "vas")) goto fail; - if (read_32bitBE(0x00, streamFile) == 0xAB8A5A00) { /* fixed value */ + if (read_u32be(0x00, sf) == 0xAB8A5A00) { /* fixed value */ /* 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; - 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 > total_subsongs || total_subsongs < 1) goto fail; /* 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); /* some values are repeats found in the file sub-header */ - subfile_offset = read_32bitLE(header_offset + 0x00,streamFile) * 0x800; - subfile_size = read_32bitLE(header_offset + 0x08,streamFile) + 0x800; + subfile_offset = read_32bitLE(header_offset + 0x00,sf) * 0x800; + subfile_size = read_32bitLE(header_offset + 0x08,sf) + 0x800; } else { /* a bunch of files */ @@ -86,7 +86,7 @@ VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) { int 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) { subfile_offset = offset; @@ -102,18 +102,18 @@ VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE *streamFile) { } else { /* 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; /* must have multiple .vas */ - if (read_32bitLE(0x00,streamFile) + 0x800 >= file_size) + if (read_32bitLE(0x00,sf) + 0x800 >= file_size) goto fail; total_subsongs = 0; if (target_subsong == 0) target_subsong = 1; 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 */ 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); - if (!temp_streamFile) goto fail; + temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL); + if (!temp_sf) goto fail; - vgmstream = init_vgmstream_ps2_vas(temp_streamFile); + vgmstream = init_vgmstream_ps2_vas(temp_sf); if (!vgmstream) goto fail; vgmstream->num_streams = total_subsongs; - close_streamfile(temp_streamFile); + close_streamfile(temp_sf); return vgmstream; fail: - close_streamfile(temp_streamFile); + close_streamfile(temp_sf); close_vgmstream(vgmstream); return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 6d157acbd..0f75b1bda 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -294,7 +294,7 @@ fail: 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); @@ -604,10 +604,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { /* ignore Beyond Good & Evil HD PS3 evil reuse of PCM codec */ if (fmt.coding_type == coding_PCM16LE && - read_32bitBE(start_offset+0x00, sf) == 0x4D534643 && /* "MSF\43" */ - read_32bitBE(start_offset+0x34, sf) == 0xFFFFFFFF && /* always */ - read_32bitBE(start_offset+0x38, sf) == 0xFFFFFFFF && - read_32bitBE(start_offset+0x3c, sf) == 0xFFFFFFFF) + read_u32be(start_offset+0x00, sf) == 0x4D534643 && /* "MSF\43" */ + read_u32be(start_offset+0x34, sf) == 0xFFFFFFFF && /* always */ + read_u32be(start_offset+0x38, sf) == 0xFFFFFFFF && + read_u32be(start_offset+0x3c, sf) == 0xFFFFFFFF) goto fail; /* 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 */ - 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->codec_config = 1; /* mark as UE4 MSADPCM */ 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_end_sample = vgmstream->num_samples; 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 */ -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 */ if (fmt->channel_count < 2) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rkv.c b/Frameworks/vgmstream/vgmstream/src/meta/rkv.c index a880c58db..544ae3b34 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rkv.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rkv.c @@ -1,115 +1,117 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* RKV - from Legacy of Kain - Blood Omen 2 (PS2) */ -VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, header_offset; - size_t data_size; - int loop_flag, channel_count; - - - /* checks */ - if (!check_extensions(streamFile, "rkv")) - goto fail; - if (read_32bitBE(0x24,streamFile) != 0x00) /* quick test vs GC rkv (coef position) */ - goto fail; - - /* some RKV got info at offset 0x00, some other at 0x0 4 */ - if (read_32bitLE(0x00,streamFile)==0) - header_offset = 0x04; - else - header_offset = 0x00; - - switch (read_32bitLE(header_offset+0x0c,streamFile)) { - case 0x00: channel_count = 1; break; - case 0x01: channel_count = 2; break; - default: goto fail; - } - loop_flag = (read_32bitLE(header_offset+0x04,streamFile) != 0xFFFFFFFF); - start_offset = 0x800; - data_size = get_streamfile_size(streamFile) - start_offset; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(header_offset,streamFile); - vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); - //vgmstream->num_samples = read_32bitLE(header_offset+0x08,streamFile); /* sometimes not set */ - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(header_offset+0x04,streamFile); - vgmstream->loop_end_sample = read_32bitLE(header_offset+0x08,streamFile); - } - - vgmstream->meta_type = meta_PS2_RKV; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x400; - if (vgmstream->interleave_block_size) - vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels; - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - -/* RKV - from Legacy of Kain - Blood Omen 2 (GC) */ -VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - - - /* checks */ - /* "": empty (files have names but no extensions), .rkv: container bigfile extension, .bo2: fake extension */ - if (!check_extensions(streamFile, ",rkv,bo2")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x00) - goto fail; - if (read_32bitBE(0x24,streamFile) == 0x00) /* quick test vs GC rkv (coef position) */ - goto fail; - - switch (read_32bitBE(0x10,streamFile)) { - case 0x00: channel_count = 1; break; - case 0x01: channel_count = 2; break; - default: goto fail; - } - loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF); - start_offset = 0x800; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitBE(0x04,streamFile); - vgmstream->num_samples = read_32bitBE(0x0C,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile); - } - - vgmstream->meta_type = meta_NGC_RKV; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x400; - - dsp_read_coefs_be(vgmstream,streamFile,0x24,0x2e); - /* hist at 0x44/0x72? */ - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* RKV - from Legacy of Kain - Blood Omen 2 (PS2) */ +VGMSTREAM* init_vgmstream_ps2_rkv(STREAMFILE *sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset, header_offset; + size_t data_size; + int loop_flag, channels; + + + /* checks */ + if (!check_extensions(sf, "rkv")) + goto fail; + if (read_u32be(0x24,sf) != 0x00) /* quick test vs GC rkv (coef position) */ + goto fail; + + /* some RKV got info at offset 0x00, some other at 0x0 4 */ + if (read_u32le(0x00,sf) == 0) + header_offset = 0x04; + else + header_offset = 0x00; + + switch (read_u32le(header_offset+0x0c,sf)) { + case 0x00: channels = 1; break; + case 0x01: channels = 2; break; + default: goto fail; + } + loop_flag = (read_u32le(header_offset+0x04,sf) != 0xFFFFFFFF); + start_offset = 0x800; + data_size = get_streamfile_size(sf) - start_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_s32le(header_offset,sf); + vgmstream->num_samples = ps_bytes_to_samples(data_size, channels); + //vgmstream->num_samples = read_32bitLE(header_offset+0x08,sf); /* sometimes not set */ + if (loop_flag) { + vgmstream->loop_start_sample = read_s32le(header_offset+0x04,sf); + vgmstream->loop_end_sample = read_s32le(header_offset+0x08,sf); + } + + vgmstream->meta_type = meta_PS2_RKV; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x400; + if (vgmstream->interleave_block_size) + vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels; + + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* RKV - from Legacy of Kain - Blood Omen 2 (GC) */ +VGMSTREAM* init_vgmstream_ngc_rkv(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels; + + + /* checks */ + /* "": empty (files have names but no extensions) + * .rkv: container bigfile extension + * .bo2: fake extension */ + if (!check_extensions(sf, ",rkv,bo2")) + goto fail; + if (read_u32be(0x00,sf) != 0x00) + goto fail; + if (read_u32be(0x24,sf) == 0x00) /* quick test vs GC rkv (coef position) */ + goto fail; + + switch (read_u32be(0x10,sf)) { + case 0x00: channels = 1; break; + case 0x01: channels = 2; break; + default: goto fail; + } + loop_flag = (read_u32be(0x08,sf) != 0xFFFFFFFF); + start_offset = 0x800; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_s32be(0x04,sf); + vgmstream->num_samples = read_s32be(0x0C,sf); + if (loop_flag) { + vgmstream->loop_start_sample = read_s32be(0x08,sf); + vgmstream->loop_end_sample = read_s32be(0x0C,sf); + } + + vgmstream->meta_type = meta_NGC_RKV; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x400; + + dsp_read_coefs_be(vgmstream,sf,0x24,0x2e); + /* hist at 0x44/0x72? */ + + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c index a4060adaa..cb47075f8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c @@ -3,11 +3,11 @@ /* RSD - from Radical Entertainment games */ -VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { - VGMSTREAM * vgmstream = NULL; +VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset, name_offset; size_t data_size; - int loop_flag, channel_count, sample_rate, interleave; + int loop_flag, channels, sample_rate, interleave; uint32_t codec; uint8_t version; @@ -15,22 +15,22 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { /* checks */ if (!check_extensions(sf,"rsd,rsp")) goto fail; - if ((read_32bitBE(0x00,sf) & 0xFFFFFF00) != 0x52534400) /* "RSD\00" */ + if ((read_u32be(0x00,sf) & 0xFFFFFF00) != 0x52534400) /* "RSD\00" */ goto fail; loop_flag = 0; - codec = (uint32_t)read_32bitBE(0x04,sf); - channel_count = read_32bitLE(0x08, sf); + codec = read_u32be(0x04,sf); + channels = read_s32le(0x08, sf); /* 0x0c: always 16? */ - sample_rate = read_32bitLE(0x10, sf); + sample_rate = read_s32le(0x10, sf); version = read_8bit(0x03, sf); switch(version) { case '2': /* known codecs: VAG/XADP/PCMB [The Simpsons: Road Rage] */ case '3': /* known codecs: VAG/PCM/PCMB/GADP? [Dark Summit] */ - interleave = read_32bitLE(0x14,sf); /* VAG only, 0x04 otherwise */ - start_offset = read_32bitLE(0x18,sf); + interleave = read_u32le(0x14,sf); /* VAG only, 0x04 otherwise */ + start_offset = read_u32le(0x18,sf); name_offset = 0; break; @@ -42,8 +42,8 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { name_offset = 0; /* PCMB/PCM/GADP normally start early but sometimes have padding [The Simpsons: Hit & Run (GC/Xbox)] */ - if ((codec == 0x50434D20 || codec == 0x550434D42 || codec == 0x47414450) - && read_32bitLE(0x80,sf) != 0x2D2D2D2D) + if ((codec == get_id32be("PCM ") || codec == get_id32be("PCMB") || codec == get_id32be("GADP")) + && read_u32le(0x80,sf) != 0x2D2D2D2D) start_offset = 0x80; break; @@ -62,7 +62,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_RSD; @@ -74,7 +74,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { vgmstream->layout_type = layout_interleave; 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; 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->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; 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->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; 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->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_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; 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_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; case 0x52414450: /* "RADP" [The Simpsons: Hit & Run (GC), Scarface (Wii)] */ vgmstream->coding_type = coding_RAD_IMA; 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; #ifdef VGM_USE_VORBIS @@ -134,7 +134,7 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { ovmi.meta_type = meta_RSD; 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; break; } @@ -142,17 +142,15 @@ VGMSTREAM * init_vgmstream_rsd(STREAMFILE *sf) { #ifdef VGM_USE_FFMPEG case 0x574D4120: { /* "WMA " [Scarface (Xbox)] */ - ffmpeg_codec_data *ffmpeg_data = NULL; /* mini header + WMA header at start_offset */ - ffmpeg_data = init_ffmpeg_offset(sf, start_offset+0x08,data_size); - if (!ffmpeg_data) goto fail; - vgmstream->codec_data = ffmpeg_data; + vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset+0x08,data_size); + if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; /* 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 = ffmpeg_get_samples(vgmstream->codec_data); /* an estimation, sometimes cuts files a bit early */ + //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); 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] */ - ffmpeg_codec_data *ffmpeg_data = NULL; uint8_t buf[0x100]; size_t bytes, xma_size, block_size, block_count; 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); - ffmpeg_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, xma_size); - if (!ffmpeg_data) goto fail; - vgmstream->codec_data = ffmpeg_data; + vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, xma_size); + if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; /* 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); - ffmpeg_set_skip_samples(ffmpeg_data, 512+64); + ffmpeg_set_skip_samples(vgmstream->codec_data, 512+64); break; } #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rxws.c b/Frameworks/vgmstream/vgmstream/src/meta/rxws.c index ba52a54d0..fd7ac5abb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/rxws.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rxws.c @@ -192,7 +192,7 @@ VGMSTREAM* init_vgmstream_rxws_badrip(STREAMFILE* sf) { (read_32bitBE(0x10,sf) == 0x464F524D))) goto fail; - loop_flag = (read_32bitLE(0x3C,sf)!=0xFFFFFFFF); + loop_flag = (read_u32le(0x3C,sf)!=0xFFFFFFFF); channels=2; /* Always stereo files */ /* build the VGMSTREAM */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c b/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c index 68a483d24..95dfb526f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c @@ -1,31 +1,33 @@ #include "meta.h" /* 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 * vgmstream = NULL; +VGMSTREAM* init_vgmstream_sat_dvi(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count; + int loop_flag, channels; - /* check extension (.pcm: original, .dvi: renamed to header id) */ - if ( !check_extensions(streamFile,"pcm,dvi") ) + /* checks + * .pcm: original + * .dvi: header id (to be removed )*/ + if (!check_extensions(sf,"pcm,dvi")) goto fail; - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x4456492E) /* "DVI." */ + if (!is_id32be(0x00,sf, "DVI.")) goto fail; - start_offset = read_32bitBE(0x04,streamFile); - loop_flag = (read_32bitBE(0x0C,streamFile) != 0xFFFFFFFF); - channel_count = 2; /* no mono files seem to exists */ + start_offset = read_s32be(0x04,sf); + loop_flag = (read_s32be(0x0C,sf) != -1); + channels = 2; /* no mono files seem to exists */ + /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = 44100; - vgmstream->num_samples = read_32bitBE(0x08,streamFile); - vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0x08,streamFile); + vgmstream->num_samples = read_s32be(0x08,sf); + vgmstream->loop_start_sample = read_s32be(0x0C,sf); + vgmstream->loop_end_sample = read_s32be(0x08,sf); vgmstream->coding_type = coding_DVI_IMA_int; 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) */ - /* open the file for reading */ - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + if (!vgmstream_open_stream(vgmstream, sf, start_offset) ) goto fail; /* 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; vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset = vgmstream->ch[1].offset; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sdf.c b/Frameworks/vgmstream/vgmstream/src/meta/sdf.c index a1c18ec03..267d0bc4e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sdf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sdf.c @@ -1,99 +1,126 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* SDF - from Beyond Reality games */ -VGMSTREAM * init_vgmstream_sdf(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - size_t data_size; - int loop_flag, channel_count, sample_rate, interleave, coefs_offset; - - - /* checks */ - if (!check_extensions(streamFile,"sdf")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x53444600) /* "SDF\0" */ - goto fail; - if (read_32bitBE(0x04,streamFile) != 0x03000000) /* version? */ - goto fail; - - data_size = read_32bitLE(0x08,streamFile); - start_offset = get_streamfile_size(streamFile) - data_size; - - switch(start_offset) { - case 0x18: /* Agent Hugo - Lemoon Twist (PS2)*/ - sample_rate = read_32bitLE(0x0c,streamFile); - channel_count = read_32bitLE(0x10,streamFile); - interleave = read_32bitLE(0x14,streamFile); - break; - - case 0x78: /* Gummy Bears Mini Golf (3DS) */ - sample_rate = read_32bitLE(0x10,streamFile); - channel_count = read_32bitLE(0x14,streamFile); - interleave = read_32bitLE(0x18,streamFile); - coefs_offset = 0x1c; - break; - - case 0x84: /* Mr. Bean's Wacky World (Wii) */ - sample_rate = read_32bitLE(0x10,streamFile); - channel_count = read_32bitLE(0x14,streamFile); - interleave = read_32bitLE(0x18,streamFile); - data_size = read_32bitLE(0x20,streamFile); /* usable size */ - coefs_offset = 0x28; - break; - - default: - goto fail; - } - - loop_flag = 1; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_SDF; - vgmstream->sample_rate = sample_rate; - - switch(start_offset) { - case 0x18: - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - - vgmstream->num_samples = ps_bytes_to_samples(data_size,channel_count); - break; - - case 0x78: - case 0x84: - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - if (vgmstream->interleave_block_size == 0) /* Gummy Bears Mini Golf */ - vgmstream->interleave_block_size = data_size / channel_count; - - vgmstream->num_samples = dsp_bytes_to_samples(data_size,channel_count); - - dsp_read_coefs_le(vgmstream, streamFile, coefs_offset+0x00,0x2e); - dsp_read_hist_le (vgmstream, streamFile, coefs_offset+0x24,0x2e); - break; - - default: - goto fail; - } - - /* most songs simply repeat; don't loop if too short (in seconds) */ - if (vgmstream->num_samples > 10*sample_rate) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +typedef enum { PSX, PCM, DSP } sdf_codec; + + +/* SDF - from Beyond Reality games */ +VGMSTREAM* init_vgmstream_sdf(STREAMFILE* sf) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + size_t data_size; + int loop_flag, channels, sample_rate, interleave, coefs_offset; + sdf_codec codec; + + + /* checks */ + if (!check_extensions(sf,"sdf")) + goto fail; + if (!is_id32be(0x00,sf, "SDF\0")) + goto fail; + if (read_u32le(0x04,sf) != 3) /* version? */ + goto fail; + + data_size = read_u32le(0x08,sf); + start_offset = get_streamfile_size(sf) - data_size; + + switch(start_offset) { + case 0x18: + if (read_u32le(0x10,sf) > 6) { + /* Hugo Magic in the Troll Woods (NDS) */ + /* 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; + + case 0x78: /* Gummy Bears Mini Golf (3DS) */ + sample_rate = read_s32le(0x10,sf); + channels = read_u32le(0x14,sf); + interleave = read_u32le(0x18,sf); + coefs_offset = 0x1c; + codec = DSP; + break; + + case 0x84: /* Mr. Bean's Wacky World (Wii) */ + sample_rate = read_s32le(0x10,sf); + channels = read_u32le(0x14,sf); + interleave = read_u32le(0x18,sf); + data_size = read_u32le(0x20,sf); /* usable size */ + coefs_offset = 0x28; + codec = DSP; + break; + + default: + goto fail; + } + + loop_flag = 1; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_SDF; + vgmstream->sample_rate = sample_rate; + + switch(codec) { + 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->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + vgmstream->num_samples = ps_bytes_to_samples(data_size, channels); + break; + + case DSP: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + if (vgmstream->interleave_block_size == 0) /* Gummy Bears Mini Golf */ + vgmstream->interleave_block_size = data_size / channels; + + vgmstream->num_samples = dsp_bytes_to_samples(data_size, channels); + + dsp_read_coefs_le(vgmstream, sf, coefs_offset+0x00,0x2e); + dsp_read_hist_le (vgmstream, sf, coefs_offset+0x24,0x2e); + break; + + default: + goto fail; + } + + /* most songs simply repeat; don't loop if too short (in seconds) */ + if (vgmstream->num_samples > 10*sample_rate) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c index cb53d60fa..acc012fd6 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c @@ -192,7 +192,7 @@ VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) { } /* 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) read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, sf); return ogg_vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c index 43de6e8f8..6a4a75c85 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_sead.c @@ -172,7 +172,7 @@ VGMSTREAM* init_vgmstream_sqex_sead(STREAMFILE* sf) { /* 0x18: reserved x2 */ /* 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) { ogg_vgmstream->num_streams = vgmstream->num_streams; ogg_vgmstream->stream_size = vgmstream->stream_size; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/str_wav.c b/Frameworks/vgmstream/vgmstream/src/meta/str_wav.c index ea2f026a2..f4181837f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/str_wav.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/str_wav.c @@ -150,8 +150,8 @@ VGMSTREAM* init_vgmstream_str_wav(STREAMFILE* sf) { vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = ffmpeg_data->totalSamples; - if (vgmstream->channels != ffmpeg_data->channels) + vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); + if (vgmstream->channels != ffmpeg_get_channels(ffmpeg_data)) goto fail; break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/strm_abylight.c b/Frameworks/vgmstream/vgmstream/src/meta/strm_abylight.c index cb97bcc56..cfdda7f39 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/strm_abylight.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/strm_abylight.c @@ -4,9 +4,9 @@ /* .STRM - from Abylight 3DS games [Cursed Castilla (3DS)] */ VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) { - VGMSTREAM * vgmstream = NULL; + VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count, sample_rate; + int loop_flag, channel_count, sample_rate, skip_samples; size_t data_size; @@ -22,6 +22,7 @@ VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) { loop_flag = 0; channel_count = 2; /* there are various possible fields but all files are stereo */ sample_rate = read_32bitLE(0x08,sf); + skip_samples = 1024; /* assumed, maybe a bit more */ start_offset = 0x1e; data_size = read_32bitLE(0x10,sf); @@ -42,14 +43,12 @@ VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) { #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; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - /* assumed, maybe a bit more */ - ffmpeg_set_skip_samples(vgmstream->codec_data, 1024); - vgmstream->num_samples -= 1024; + vgmstream->num_samples -= skip_samples; } #else goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index 74f514ae8..84c60aa21 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -483,10 +483,10 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { if (!ffmpeg_data) goto fail; 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) { - 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; } 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 /* ignore comments (that aren't subsongs) */ - if (line[0] == '#' && strchr(line,':') < 0) + if (line[0] == '#' && strchr(line,':') == NULL) return 0; /* try "(name): (val))" */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c index 02fb1fa70..830121c7d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c @@ -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; int channels, sample_rate; int32_t num_samples; @@ -660,7 +660,7 @@ static VGMSTREAM* init_vgmstream_ubi_bao_header(ubi_bao_header* bao, STREAMFILE* break; case UBI_SILENCE: - vgmstream = init_vgmstream_ubi_bao_silence(bao, sf); + vgmstream = init_vgmstream_ubi_bao_silence(bao); break; default: @@ -990,7 +990,7 @@ fail: } /* 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) return 1; @@ -1228,7 +1228,7 @@ static int parse_header(ubi_bao_header* bao, STREAMFILE* sf, off_t offset) { goto fail; } - if (!parse_values(bao, sf)) + if (!parse_values(bao)) goto fail; if (!parse_offsets(bao, sf)) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c index 0d9f17ff4..dec628671 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_jade.c @@ -1,380 +1,385 @@ -#include "meta.h" -#include "../coding/coding.h" - -static int get_loop_points(STREAMFILE *streamFile, int *out_loop_start, int *out_loop_end); - -/* 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 * vgmstream = NULL; - off_t start_offset, first_offset = 0xc; - off_t fmt_offset, data_offset; - size_t fmt_size, data_size; - int loop_flag, channel_count, sample_rate, codec, block_size; - int loop_start = 0, loop_end = 0; - int is_jade_v2 = 0; - - - /* checks */ - /* .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)] */ - if (!check_extensions(streamFile,"waa,wac,wad,wam,wav,lwav,psw")) - goto fail; - - /* a slightly twisted RIFF with custom codecs */ - if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */ - read_32bitBE(0x08,streamFile) != 0x57415645) /* "WAVE" */ - 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)) - goto fail; - } - else { - if (read_32bitLE(0x04,streamFile)+0x04+0x04 != get_streamfile_size(streamFile)) - goto fail; - } - - if (!find_chunk(streamFile, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size, 0, 0)) /* "fmt " */ - goto fail; - if (!find_chunk(streamFile, 0x64617461,first_offset,0, &data_offset,&data_size, 0, 0)) /* "data" */ - goto fail; - - /* ignore LyN RIFF (needed as codec 0xFFFE is reused) */ - { - off_t fact_offset; - size_t fact_size; - - if (find_chunk(streamFile, 0x66616374,first_offset,0, &fact_offset,&fact_size, 0, 0)) { /* "fact" */ - if (fact_size == 0x10 && read_32bitBE(fact_offset+0x04, streamFile) == 0x4C794E20) /* "LyN " */ - goto fail; /* parsed elsewhere */ - /* Jade doesn't use "fact", though */ - } - } - - - /* parse format */ - { - if (fmt_size < 0x10) - goto fail; - codec = (uint16_t)read_16bitLE(fmt_offset+0x00,streamFile); - channel_count = read_16bitLE(fmt_offset+0x02,streamFile); - sample_rate = read_32bitLE(fmt_offset+0x04,streamFile); - block_size = (uint16_t)read_16bitLE(fmt_offset+0x0c,streamFile); - /* 0x08: average bytes, 0x0e: bps, etc */ - - /* autodetect Jade "v2", uses a different interleave [Rayman Raving Rabbids (PS2/Wii)] */ - switch(codec) { - case 0xFFFF: { /* PS2 */ - int i; - - /* half interleave check as there is no flag (ends with the PS-ADPCM stop frame) */ - for (i = 0; i < channel_count; i++) { - off_t end_frame = data_offset + (data_size / channel_count) * (i+1) - 0x10; - if (read_32bitBE(end_frame+0x00,streamFile) != 0x07007777 || - read_32bitBE(end_frame+0x04,streamFile) != 0x77777777 || - read_32bitBE(end_frame+0x08,streamFile) != 0x77777777 || - read_32bitBE(end_frame+0x0c,streamFile) != 0x77777777) { - is_jade_v2 = 1; - break; - } - } - break; - } - - case 0xFFFE: /* GC/Wii */ - is_jade_v2 = (read_16bitLE(fmt_offset+0x10,streamFile) == 0); /* extra data size (0x2e*channels) */ - break; - } - - /* hopefully catches PC Rabbids */ - if (find_chunk(streamFile, 0x63756520,first_offset,0, NULL,NULL, 0, 0)) { /* "cue " */ - is_jade_v2 = 1; - } - } - - - /* get loop points */ - if (is_jade_v2) { - loop_flag = get_loop_points(streamFile, &loop_start, &loop_end); /* loops in "LIST" */ - } - else { - /* 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. - * Later, if the file is too short looping will be disabled. */ - loop_flag = check_extensions(streamFile,"waa,wam"); - } - - start_offset = data_offset; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->meta_type = meta_UBI_JADE; - if (is_jade_v2) { - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - } - - switch(codec) { - - case 0x0069: /* Xbox */ - /* Peter Jackson's King Kong uses 0x14 (other versions don't) */ - if (fmt_size != 0x12 && fmt_size != 0x14) goto fail; - if (block_size != 0x24*channel_count) goto fail; - - vgmstream->coding_type = coding_XBOX_IMA; - vgmstream->layout_type = layout_none; - - vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, channel_count); - if (!is_jade_v2) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - break; - - case 0xFFFF: /* PS2 */ - if (fmt_size != 0x12) goto fail; - if (block_size != 0x10) goto fail; - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - - if (is_jade_v2) { - vgmstream->interleave_block_size = 0x6400; - if (vgmstream->interleave_block_size) - vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels; - } - else { - vgmstream->interleave_block_size = data_size / channel_count; - } - - vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); - if (!is_jade_v2) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - break; - - case 0xFFFE: /* GC/Wii */ - if (fmt_size != 0x12) goto fail; - if (block_size != 0x08) goto fail; - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - - vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count); - if (!is_jade_v2) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - /* coefs / interleave */ - if (is_jade_v2) { - vgmstream->interleave_block_size = 0x6400; - if (vgmstream->interleave_block_size) - vgmstream->interleave_last_block_size = ((data_size % (vgmstream->interleave_block_size*vgmstream->channels))/2+7)/8*8; - - { - static const int16_t coef[16] = { /* default Ubisoft coefs, from ELF */ - 0x04ab,0xfced,0x0789,0xfedf,0x09a2,0xfae5,0x0c90,0xfac1, - 0x084d,0xfaa4,0x0982,0xfdf7,0x0af6,0xfafa,0x0be6,0xfbf5 - }; - int i, ch; - - for (ch = 0; ch < channel_count; ch++) { - for (i = 0; i < 16; i++) { - vgmstream->ch[ch].adpcm_coef[i] = coef[i]; - } - } - } - } - else { - /* has extra 0x2e coefs before each channel, not counted in data_size */ - 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_hist_be (vgmstream, streamFile, start_offset+0x20, vgmstream->interleave_block_size); - start_offset += 0x2e; - } - break; - - case 0x0002: /* PC */ - if (fmt_size != 0x12) goto fail; - if (block_size != 0x24*channel_count) goto fail; - - vgmstream->coding_type = coding_MSADPCM; - vgmstream->layout_type = layout_none; - vgmstream->frame_size = block_size; - - vgmstream->num_samples = msadpcm_bytes_to_samples(data_size, vgmstream->frame_size, channel_count); - if (!is_jade_v2) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - break; - - case 0x0001: { /* PS3 */ - VGMSTREAM *temp_vgmstream = NULL; - STREAMFILE *temp_sf = NULL; - - if (fmt_size != 0x10) goto fail; - if (block_size != 0x02*channel_count) goto fail; - - /* a MSF (usually ATRAC3) masquerading as PCM */ - if (read_32bitBE(start_offset, streamFile) != 0x4D534643) /* "MSF\43" */ - goto fail; - - temp_sf = setup_subfile_streamfile(streamFile, start_offset, data_size, "msf"); - if (!temp_sf) goto fail; - - temp_vgmstream = init_vgmstream_msf(temp_sf); - close_streamfile(temp_sf); - if (!temp_vgmstream) goto fail; - - temp_vgmstream->meta_type = vgmstream->meta_type; - close_vgmstream(vgmstream); - return temp_vgmstream; - } - - default: /* X360 uses .XMA */ - goto fail; - } - - /* V1 loops by extension, try to detect incorrectly looped jingles (too short) */ - if (!is_jade_v2) { - if(loop_flag - && vgmstream->num_samples < 15*sample_rate) { /* in seconds */ - vgmstream->loop_flag = 0; - } - } - - - if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - -/* 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) { - off_t cue_offset, list_offset; - size_t cue_size, list_size; - off_t offset, first_offset = 0x0c; - int i, cue_count, loop_id = 0, loop_start = 0, loop_end = 0; - - - /* unlooped files may contain LIST, but also may not */ - if (!find_chunk(streamFile, 0x63756520,first_offset,0, &cue_offset,&cue_size, 0, 0)) /* "cue " */ - goto fail; - if (!find_chunk(streamFile, 0x4C495354,first_offset,0, &list_offset,&list_size, 0, 0)) /* "LIST" */ - goto fail; - - offset = list_offset + 0x04; - while (offset < list_offset + list_size) { - uint32_t chunk_id = read_32bitBE(offset+0x00, streamFile); - uint32_t chunk_size = read_32bitLE(offset+0x04, streamFile); - offset += 0x08; - - switch(chunk_id) { - case 0x6C61626C: /* "labl" */ - if (read_32bitBE(offset+0x04, streamFile) == 0x6C6F6F70) /* "loop", actually an string tho */ - loop_id = read_32bitLE(offset+0x00, streamFile); - chunk_size += (chunk_size % 2) ? 1 : 0; /* string is even-padded after size */ - break; - case 0x6C747874: /* "ltxt" */ - if (loop_id == read_32bitLE(offset+0x00, streamFile)) - loop_end = read_32bitLE(offset+0x04, streamFile); - break; - - default: - VGM_LOG("Jade: unknown LIST chunk\n"); - goto fail; - } - - offset += chunk_size; - } - - if (!loop_end) - return 0; - - cue_count = read_32bitLE(cue_offset+0x00, streamFile); - for (i = 0; i < cue_count; i++) { - if (loop_id == read_32bitLE(cue_offset+0x04 + i*0x18 + 0x00, streamFile)) { - loop_start = read_32bitLE(cue_offset+0x04 + i*0x18 + 0x04, streamFile); - loop_end += loop_start; - break; - } - } - - *out_loop_start = loop_start; - *out_loop_end = loop_end; - return 1; - -fail: - return 0; -} - - -/* Jade RIFF in containers */ -VGMSTREAM * init_vgmstream_ubi_jade_container(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - off_t subfile_offset; - size_t subfile_size; - - /* Jade packs files in bigfiles, and once extracted the sound files have extra engine data before - * the RIFF + padding after. Most extractors don't remove the padding correctly, so here we add support. */ - - /* checks */ - /* 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")) - goto fail; - - if (read_32bitBE(0x04,streamFile) == 0x52494646 && - read_32bitLE(0x00,streamFile)+0x04 == get_streamfile_size(streamFile)) { - /* data size + RIFF + padding */ - subfile_offset = 0x04; - } - else if (read_32bitBE(0x00,streamFile) == 0x52494646 && - read_32bitLE(0x04,streamFile)+0x04+0x04 < get_streamfile_size(streamFile) && - (get_streamfile_size(streamFile) + 0x04) % 0x800 == 0) { - /* RIFF + padding with data size removed (bad extraction) */ - subfile_offset = 0x00; - } - else if (read_32bitBE(0x04,streamFile) == 0x52494646 && - read_32bitLE(0x00,streamFile) == get_streamfile_size(streamFile)) { - /* data_size + RIFF + padding - 0x04 (bad extraction) */ - subfile_offset = 0x04; - } - else { - goto fail; - } - - subfile_size = read_32bitLE(subfile_offset+0x04,streamFile) + 0x04+0x04; - - temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); - if (!temp_streamFile) goto fail; - - if (check_extensions(streamFile,"xma")) { - vgmstream = init_vgmstream_xma(temp_streamFile); - } else { - vgmstream = init_vgmstream_ubi_jade(temp_streamFile); - } - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +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)] */ +VGMSTREAM* init_vgmstream_ubi_jade(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset, first_offset = 0xc; + off_t fmt_offset, data_offset; + size_t fmt_size, data_size; + int loop_flag, channel_count, sample_rate, codec, block_size; + int loop_start = 0, loop_end = 0; + int is_jade_v2 = 0; + + + /* checks */ + /* .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)] */ + if (!check_extensions(sf,"waa,wac,wad,wam,wav,lwav,psw")) + goto fail; + + /* a slightly twisted RIFF with custom codecs */ + if (!is_id32be(0x00,sf, "RIFF") || + !is_id32be(0x08,sf, "WAVE")) + goto fail; + + + 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; + } + else { + if (read_32bitLE(0x04,sf)+0x04+0x04 != get_streamfile_size(sf)) + goto fail; + } + + if (!find_chunk(sf, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size, 0, 0)) /* "fmt " */ + goto fail; + if (!find_chunk(sf, 0x64617461,first_offset,0, &data_offset,&data_size, 0, 0)) /* "data" */ + goto fail; + + /* ignore LyN RIFF (needed as codec 0xFFFE is reused) */ + { + off_t fact_offset; + size_t fact_size; + + if (find_chunk(sf, 0x66616374,first_offset,0, &fact_offset,&fact_size, 0, 0)) { /* "fact" */ + if (fact_size == 0x10 && read_32bitBE(fact_offset+0x04, sf) == 0x4C794E20) /* "LyN " */ + goto fail; /* parsed elsewhere */ + /* Jade doesn't use "fact", though */ + } + } + + + /* parse format */ + { + if (fmt_size < 0x10) + goto fail; + codec = (uint16_t)read_16bitLE(fmt_offset+0x00,sf); + channel_count = read_16bitLE(fmt_offset+0x02,sf); + sample_rate = read_32bitLE(fmt_offset+0x04,sf); + block_size = (uint16_t)read_16bitLE(fmt_offset+0x0c,sf); + /* 0x08: average bytes, 0x0e: bps, etc */ + + /* autodetect Jade "v2", uses a different interleave [Rayman Raving Rabbids (PS2/Wii)] */ + switch(codec) { + case 0xFFFF: { /* PS2 */ + int i; + + /* half interleave check as there is no flag (ends with the PS-ADPCM stop frame) */ + for (i = 0; i < channel_count; i++) { + off_t end_frame = data_offset + (data_size / channel_count) * (i+1) - 0x10; + if (read_32bitBE(end_frame+0x00,sf) != 0x07007777 || + read_32bitBE(end_frame+0x04,sf) != 0x77777777 || + read_32bitBE(end_frame+0x08,sf) != 0x77777777 || + read_32bitBE(end_frame+0x0c,sf) != 0x77777777) { + is_jade_v2 = 1; + break; + } + } + break; + } + + case 0xFFFE: /* GC/Wii */ + is_jade_v2 = (read_16bitLE(fmt_offset+0x10,sf) == 0); /* extra data size (0x2e*channels) */ + break; + + default: + break; + } + + /* hopefully catches PC Rabbids */ + if (find_chunk(sf, 0x63756520,first_offset,0, NULL,NULL, 0, 0)) { /* "cue " */ + is_jade_v2 = 1; + } + } + + + /* get loop points */ + if (is_jade_v2) { + loop_flag = get_loop_points(sf, &loop_start, &loop_end); /* loops in "LIST" */ + } + else { + /* 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. + * Later, if the file is too short looping will be disabled. */ + loop_flag = check_extensions(sf,"waa,wam"); + } + + start_offset = data_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->meta_type = meta_UBI_JADE; + if (is_jade_v2) { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + } + + switch(codec) { + + case 0x0069: /* Xbox */ + /* Peter Jackson's King Kong uses 0x14 (other versions don't) */ + if (fmt_size != 0x12 && fmt_size != 0x14) goto fail; + if (block_size != 0x24*channel_count) goto fail; + + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, channel_count); + if (!is_jade_v2) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + break; + + case 0xFFFF: /* PS2 */ + if (fmt_size != 0x12) goto fail; + if (block_size != 0x10) goto fail; + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + + if (is_jade_v2) { + vgmstream->interleave_block_size = 0x6400; + if (vgmstream->interleave_block_size) + vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels; + } + else { + vgmstream->interleave_block_size = data_size / channel_count; + } + + vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); + if (!is_jade_v2) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + break; + + case 0xFFFE: /* GC/Wii */ + if (fmt_size != 0x12) goto fail; + if (block_size != 0x08) goto fail; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + + vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count); + if (!is_jade_v2) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + /* coefs / interleave */ + if (is_jade_v2) { + vgmstream->interleave_block_size = 0x6400; + if (vgmstream->interleave_block_size) + vgmstream->interleave_last_block_size = ((data_size % (vgmstream->interleave_block_size*vgmstream->channels))/2+7)/8*8; + + { + static const int16_t coef[16] = { /* default Ubisoft coefs, from ELF */ + 0x04ab,0xfced,0x0789,0xfedf,0x09a2,0xfae5,0x0c90,0xfac1, + 0x084d,0xfaa4,0x0982,0xfdf7,0x0af6,0xfafa,0x0be6,0xfbf5 + }; + int i, ch; + + for (ch = 0; ch < channel_count; ch++) { + for (i = 0; i < 16; i++) { + vgmstream->ch[ch].adpcm_coef[i] = coef[i]; + } + } + } + } + else { + /* has extra 0x2e coefs before each channel, not counted in data_size */ + vgmstream->interleave_block_size = (data_size + 0x2e*channel_count) / channel_count; + + dsp_read_coefs_be(vgmstream, sf, start_offset+0x00, vgmstream->interleave_block_size); + dsp_read_hist_be (vgmstream, sf, start_offset+0x20, vgmstream->interleave_block_size); + start_offset += 0x2e; + } + break; + + case 0x0002: /* PC */ + if (fmt_size != 0x12) goto fail; + if (block_size != 0x24*channel_count) goto fail; + + vgmstream->coding_type = coding_MSADPCM; + vgmstream->layout_type = layout_none; + vgmstream->frame_size = block_size; + + vgmstream->num_samples = msadpcm_bytes_to_samples(data_size, vgmstream->frame_size, channel_count); + if (!is_jade_v2) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + break; + + case 0x0001: { /* PS3 */ + VGMSTREAM *temp_vgmstream = NULL; + STREAMFILE *temp_sf = NULL; + + if (fmt_size != 0x10) goto fail; + if (block_size != 0x02*channel_count) goto fail; + + /* a MSF (usually ATRAC3) masquerading as PCM */ + if (read_32bitBE(start_offset, sf) != 0x4D534643) /* "MSF\43" */ + goto fail; + + temp_sf = setup_subfile_streamfile(sf, start_offset, data_size, "msf"); + if (!temp_sf) goto fail; + + temp_vgmstream = init_vgmstream_msf(temp_sf); + close_streamfile(temp_sf); + if (!temp_vgmstream) goto fail; + + temp_vgmstream->meta_type = vgmstream->meta_type; + close_vgmstream(vgmstream); + return temp_vgmstream; + } + + default: /* X360 uses .XMA */ + goto fail; + } + + /* V1 loops by extension, try to detect incorrectly looped jingles (too short) */ + if (!is_jade_v2) { + if(loop_flag + && vgmstream->num_samples < 15*sample_rate) { /* in seconds */ + vgmstream->loop_flag = 0; + } + } + + + if (!vgmstream_open_stream(vgmstream, sf,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* extract loops from "cue /LIST", returns if loops (info from Droolie) */ +static int get_loop_points(STREAMFILE *sf, int *out_loop_start, int *out_loop_end) { + off_t cue_offset, list_offset; + size_t cue_size, list_size; + off_t offset, first_offset = 0x0c; + int i, cue_count, loop_id = 0, loop_start = 0, loop_end = 0; + + + /* unlooped files may contain LIST, but also may not */ + if (!find_chunk(sf, 0x63756520,first_offset,0, &cue_offset,&cue_size, 0, 0)) /* "cue " */ + goto fail; + if (!find_chunk(sf, 0x4C495354,first_offset,0, &list_offset,&list_size, 0, 0)) /* "LIST" */ + goto fail; + + offset = list_offset + 0x04; + while (offset < list_offset + list_size) { + uint32_t chunk_id = read_32bitBE(offset+0x00, sf); + uint32_t chunk_size = read_32bitLE(offset+0x04, sf); + offset += 0x08; + + switch(chunk_id) { + case 0x6C61626C: /* "labl" */ + if (read_32bitBE(offset+0x04, sf) == 0x6C6F6F70) /* "loop", actually an string tho */ + loop_id = read_32bitLE(offset+0x00, sf); + chunk_size += (chunk_size % 2) ? 1 : 0; /* string is even-padded after size */ + break; + case 0x6C747874: /* "ltxt" */ + if (loop_id == read_32bitLE(offset+0x00, sf)) + loop_end = read_32bitLE(offset+0x04, sf); + break; + + default: + VGM_LOG("Jade: unknown LIST chunk\n"); + goto fail; + } + + offset += chunk_size; + } + + if (!loop_end) + return 0; + + cue_count = read_32bitLE(cue_offset+0x00, sf); + for (i = 0; i < cue_count; i++) { + if (loop_id == read_32bitLE(cue_offset+0x04 + i*0x18 + 0x00, sf)) { + loop_start = read_32bitLE(cue_offset+0x04 + i*0x18 + 0x04, sf); + loop_end += loop_start; + break; + } + } + + *out_loop_start = loop_start; + *out_loop_end = loop_end; + return 1; + +fail: + return 0; +} + + +/* Jade RIFF in containers */ +VGMSTREAM* init_vgmstream_ubi_jade_container(STREAMFILE* sf) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *temp_sf = NULL; + off_t subfile_offset; + size_t subfile_size; + + /* Jade packs files in bigfiles, and once extracted the sound files have extra engine data before + * the RIFF + padding after. Most extractors don't remove the padding correctly, so here we add support. */ + + /* checks */ + /* standard Jade exts + .xma for padded XMA used in Beyond Good & Evil HD (X360) */ + if (!check_extensions(sf,"waa,wac,wad,wam,wav,lwav,xma")) + goto fail; + + if (read_32bitBE(0x04,sf) == 0x52494646 && + read_32bitLE(0x00,sf)+0x04 == get_streamfile_size(sf)) { + /* data size + RIFF + padding */ + subfile_offset = 0x04; + } + else if (read_32bitBE(0x00,sf) == 0x52494646 && + read_32bitLE(0x04,sf)+0x04+0x04 < get_streamfile_size(sf) && + (get_streamfile_size(sf) + 0x04) % 0x800 == 0) { + /* RIFF + padding with data size removed (bad extraction) */ + subfile_offset = 0x00; + } + else if (read_32bitBE(0x04,sf) == 0x52494646 && + read_32bitLE(0x00,sf) == get_streamfile_size(sf)) { + /* data_size + RIFF + padding - 0x04 (bad extraction) */ + subfile_offset = 0x04; + } + else { + goto fail; + } + + subfile_size = read_32bitLE(subfile_offset+0x04,sf) + 0x04+0x04; + + temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL); + if (!temp_sf) goto fail; + + if (check_extensions(sf,"xma")) { + vgmstream = init_vgmstream_xma(temp_sf); + } else { + vgmstream = init_vgmstream_ubi_jade(temp_sf); + } + + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c index 819e512b4..d63a0845b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -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_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_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_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; } -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) { sprintf(bank_name, "Bnk_%d.bnm", bank_number); } 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]; 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; } @@ -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); 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; - 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) 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); /* 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; int channels, sample_rate; int32_t num_samples; @@ -1585,7 +1585,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf break; case UBI_SILENCE: - vgmstream = init_vgmstream_ubi_sb_silence(sb, sf_index, sf); + vgmstream = init_vgmstream_ubi_sb_silence(sb); break; case UBI_NONE: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vs.c b/Frameworks/vgmstream/vgmstream/src/meta/vs.c index 57589cff0..4e8b94c06 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vs.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vs.c @@ -1,52 +1,52 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../coding/coding.h" - -/* .VS - from Melbourne House games [Men in Black II (PS2), Grand Prix Challenge (PS2) */ -VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - - - /* checks */ - if (!check_extensions(streamFile, "vs")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0xC8000000) - goto fail; - - loop_flag = 0; - channel_count = 2; - start_offset = 0x08; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_VS; - vgmstream->sample_rate = read_32bitLE(0x04,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_blocked_vs; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - /* calc num_samples */ - { - vgmstream->next_block_offset = start_offset; - do { - block_update(vgmstream->next_block_offset,vgmstream); - vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); - } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - block_update(start_offset, vgmstream); - - } - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + +/* .VS - from Melbourne House games [Men in Black II (PS2), Grand Prix Challenge (PS2) */ +VGMSTREAM* init_vgmstream_vs(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels; + + + /* checks */ + if (!check_extensions(sf, "vs")) + goto fail; + if (read_u32be(0x00,sf) != 0xC8000000) + goto fail; + + loop_flag = 0; + channels = 2; + start_offset = 0x08; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_VS; + vgmstream->sample_rate = read_s32le(0x04,sf); + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_vs; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + + /* calc num_samples */ + { + vgmstream->next_block_offset = start_offset; + do { + block_update(vgmstream->next_block_offset,vgmstream); + vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); + } + while (vgmstream->next_block_offset < get_streamfile_size(sf)); + block_update(start_offset, vgmstream); + + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vs_str.c b/Frameworks/vgmstream/vgmstream/src/meta/vs_str.c index a6002b364..587cec33f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vs_str.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vs_str.c @@ -1,56 +1,56 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../coding/coding.h" - -/* .vs/STRx - from The Bouncer (PS2) */ -VGMSTREAM * init_vgmstream_vs_str(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - int channel_count, loop_flag; - off_t start_offset; - - - /* checks */ - /* .vs: real extension (from .nam container) - * .str: fake, partial header id */ - if (!check_extensions(streamFile, "vs,str")) - goto fail; - - if (!(read_32bitBE(0x000,streamFile) == 0x5354524C && /* "STRL" */ - read_32bitBE(0x800,streamFile) == 0x53545252) && /* "STRR" */ - read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */ - goto fail; - - - loop_flag = 0; - channel_count = (read_32bitBE(0x00,streamFile) == 0x5354524D) ? 1 : 2; /* "STRM"=mono (voices) */ - start_offset = 0x00; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_VS_STR; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_blocked_vs_str; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - /* calc num_samples */ - { - vgmstream->next_block_offset = start_offset; - do { - block_update(vgmstream->next_block_offset,vgmstream); - vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); - } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - block_update(start_offset, vgmstream); - } - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + +/* .vs/STRx - from The Bouncer (PS2) */ +VGMSTREAM* init_vgmstream_vs_str(STREAMFILE* sf) { + VGMSTREAM * vgmstream = NULL; + int channel_count, loop_flag; + off_t start_offset; + + + /* checks */ + /* .vs: real extension (from .nam container) + * .str: fake, partial header id */ + if (!check_extensions(sf, "vs,str")) + goto fail; + + if (!(read_32bitBE(0x000,sf) == 0x5354524C && /* "STRL" */ + read_32bitBE(0x800,sf) == 0x53545252) && /* "STRR" */ + read_32bitBE(0x00,sf) != 0x5354524D) /* "STRM" */ + goto fail; + + + loop_flag = 0; + channel_count = (read_32bitBE(0x00,sf) == 0x5354524D) ? 1 : 2; /* "STRM"=mono (voices) */ + start_offset = 0x00; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_VS_STR; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_vs_str; + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + + /* calc num_samples */ + { + vgmstream->next_block_offset = start_offset; + do { + block_update(vgmstream->next_block_offset,vgmstream); + vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); + } + while (vgmstream->next_block_offset < get_streamfile_size(sf)); + block_update(start_offset, vgmstream); + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/waf.c b/Frameworks/vgmstream/vgmstream/src/meta/waf.c index ba73d1430..f7fffa0e3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/waf.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/waf.c @@ -2,42 +2,43 @@ #include "../coding/coding.h" /* 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 * vgmstream = NULL; +VGMSTREAM* init_vgmstream_waf(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count; + int loop_flag, channels; /* checks */ - if (!check_extensions(streamFile, "waf")) + if (!check_extensions(sf, "waf")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x57414600) /* "WAF\0" */ + if (!is_id32be(0x00,sf, "WAF\0")) goto fail; - if (read_32bitLE(0x34,streamFile) + 0x38 != get_streamfile_size(streamFile)) + if (read_u32le(0x34,sf) + 0x38 != get_streamfile_size(sf)) goto fail; - channel_count = read_16bitLE(0x06,streamFile); - loop_flag = 0; + channels = read_u16le(0x06,sf); + loop_flag = 0; start_offset = 0x38; + /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; 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->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) */ - if (!msadpcm_check_coefs(streamFile, 0x16)) + if (!msadpcm_check_coefs(sf, 0x16)) 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; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wave_segmented.c b/Frameworks/vgmstream/vgmstream/src/meta/wave_segmented.c index 51fb0aeea..8891cdf26 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wave_segmented.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wave_segmented.c @@ -1,220 +1,220 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "../layout/layout.h" - -#define MAX_SEGMENTS 4 - -/* .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 * vgmstream = NULL; - off_t segments_offset; - int loop_flag = 0, channel_count, sample_rate; - int32_t num_samples, loop_start_sample = 0, loop_end_sample = 0; - - segmented_layout_data *data = NULL; - int segment_count, loop_start_segment = 0, loop_end_segment = 0; - - int big_endian; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - - - /* checks */ - if (!check_extensions(streamFile, "wave")) - goto fail; - - if (read_32bitLE(0x00,streamFile) != 0x4DF72D4A && /* header id */ - read_32bitBE(0x00,streamFile) != 0x4DF72D4A) - goto fail; - if (read_8bit(0x04,streamFile) != 0x01) /* version? */ - goto fail; - - /* PS3/X360 games */ - big_endian = read_32bitBE(0x00,streamFile) == 0x4DF72D4A; - if (big_endian) { - read_32bit = read_32bitBE; - read_16bit = read_16bitBE; - } else { - read_32bit = read_32bitLE; - read_16bit = read_16bitLE; - } - - channel_count = read_8bit(0x05,streamFile); - segment_count = read_16bit(0x06,streamFile); - if (segment_count > MAX_SEGMENTS || segment_count <= 0) goto fail; - - loop_start_segment = read_16bit(0x08, streamFile); - loop_end_segment = read_16bit(0x0a, streamFile); - segments_offset = read_32bit(0x0c, streamFile); - - sample_rate = read_32bit(0x10, streamFile); - num_samples = read_32bit(0x14, streamFile); - /* 0x18: unknown (usually 0, maybe some count) */ - - - /* init layout */ - data = init_layout_segmented(segment_count); - if (!data) goto fail; - - /* parse segments (usually: preload + intro + loop + ending, intro/ending may be skipped) - * Often first segment is ADPCM and rest Ogg; may only have one segment. */ - { - off_t extradata_offset, table_offset, segment_offset; - size_t segment_size; - int32_t segment_samples; - int codec; - int i, ch; - - /* open each segment subfile */ - for (i = 0; i < segment_count; i++) { - codec = read_8bit(segments_offset+0x10*i+0x00, streamFile); - /* 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+0x03, streamFile) != 0x00) goto fail; /* unknown */ - - segment_samples = read_32bit(segments_offset+0x10*i+0x04, streamFile); - extradata_offset = read_32bit(segments_offset+0x10*i+0x08, streamFile); - table_offset = read_32bit(segments_offset+0x10*i+0x0c, streamFile); - - /* create a sub-VGMSTREAM per segment - * (we'll reopen this streamFile as needed, so each sub-VGMSTREAM is fully independent) */ - switch(codec) { - case 0x02: { /* "adpcm" */ - data->segments[i] = allocate_vgmstream(channel_count, 0); - if (!data->segments[i]) goto fail; - - data->segments[i]->sample_rate = sample_rate; - data->segments[i]->meta_type = meta_WAVE; - data->segments[i]->coding_type = coding_IMA_int; - data->segments[i]->layout_type = layout_none; - data->segments[i]->num_samples = segment_samples; - - if (!vgmstream_open_stream(data->segments[i],streamFile,0x00)) - goto fail; - - /* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */ - for (ch = 0; ch < channel_count; ch++) { - segment_offset = read_32bit(table_offset + 0x04*ch, streamFile); - data->segments[i]->ch[ch].channel_start_offset = - data->segments[i]->ch[ch].offset = segment_offset; - - /* ADPCM setup */ - data->segments[i]->ch[ch].adpcm_history1_32 = read_16bit(extradata_offset+0x04*ch+0x00, streamFile); - data->segments[i]->ch[ch].adpcm_step_index = read_8bit(extradata_offset+0x04*ch+0x02, streamFile); - /* 0x03: reserved */ - } - - break; - } - - case 0x03: { /* "dsp-adpcm" */ - data->segments[i] = allocate_vgmstream(channel_count, 0); - if (!data->segments[i]) goto fail; - - data->segments[i]->sample_rate = sample_rate; - data->segments[i]->meta_type = meta_WAVE; - data->segments[i]->coding_type = coding_NGC_DSP; - data->segments[i]->layout_type = layout_none; - data->segments[i]->num_samples = segment_samples; - - if (!vgmstream_open_stream(data->segments[i],streamFile,0x00)) - goto fail; - - /* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */ - for (ch = 0; ch < channel_count; ch++) { - segment_offset = read_32bit(table_offset + 0x04*ch, streamFile); - data->segments[i]->ch[ch].channel_start_offset = - data->segments[i]->ch[ch].offset = segment_offset; - } - - /* 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_coefs(data->segments[i], streamFile, extradata_offset+0x06*channel_count+0x00, 0x20, big_endian); - - break; - } - -#ifdef VGM_USE_VORBIS - case 0x04: { /* "vorbis" */ - ogg_vorbis_meta_info_t ovmi = {0}; - - segment_offset = read_32bit(table_offset, streamFile); - segment_size = read_32bitBE(segment_offset, streamFile); /* always BE */ - - ovmi.meta_type = meta_WAVE; - ovmi.stream_size = segment_size; - - data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, segment_offset+0x04, &ovmi); - if (!data->segments[i]) goto fail; - - if (data->segments[i]->num_samples != segment_samples) { - VGM_LOG("WAVE: segment %i samples != num_samples\n", i); - goto fail; - } - - break; - } -#endif - - default: /* others: s16be/s16le/mp3 as referenced in the exe? */ - VGM_LOG("WAVE: unknown codec\n"); - goto fail; - } - } - } - - /* setup segmented VGMSTREAMs */ - if (!setup_layout_segmented(data)) - goto fail; - - - /* parse samples */ - { - int32_t sample_count = 0; - int i; - - loop_flag = (loop_start_segment > 0); - - for (i = 0; i < segment_count; i++) { - if (loop_flag && loop_start_segment == i) { - loop_start_sample = sample_count; - } - - sample_count += data->segments[i]->num_samples; - - if (loop_flag && loop_end_segment-1 == i) { - loop_end_sample = sample_count; - } - } - - if (sample_count != num_samples) { - VGM_LOG("WAVE: total segments samples %i != num_samples %i\n", sample_count, num_samples); - goto fail; - } - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start_sample; - vgmstream->loop_end_sample = loop_end_sample; - - vgmstream->meta_type = meta_WAVE_segmented; - vgmstream->stream_size = get_streamfile_size(streamFile); /* wrong kbps otherwise */ - - /* .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->layout_type = layout_segmented; - vgmstream->layout_data = data; - - return vgmstream; - -fail: - free_layout_segmented(data); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" + +#define MAX_SEGMENTS 4 + +/* .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 *sf) { + VGMSTREAM * vgmstream = NULL; + off_t segments_offset; + int loop_flag = 0, channel_count, sample_rate; + int32_t num_samples, loop_start_sample = 0, loop_end_sample = 0; + + segmented_layout_data *data = NULL; + int segment_count, loop_start_segment = 0, loop_end_segment = 0; + + int big_endian; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + + /* checks */ + if (!check_extensions(sf, "wave")) + goto fail; + + if (read_32bitLE(0x00,sf) != 0x4DF72D4A && /* header id */ + read_32bitBE(0x00,sf) != 0x4DF72D4A) + goto fail; + if (read_8bit(0x04,sf) != 0x01) /* version? */ + goto fail; + + /* PS3/X360 games */ + big_endian = read_32bitBE(0x00,sf) == 0x4DF72D4A; + if (big_endian) { + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + channel_count = read_8bit(0x05,sf); + segment_count = read_16bit(0x06,sf); + if (segment_count > MAX_SEGMENTS || segment_count <= 0) goto fail; + + loop_start_segment = read_16bit(0x08, sf); + loop_end_segment = read_16bit(0x0a, sf); + segments_offset = read_32bit(0x0c, sf); + + sample_rate = read_32bit(0x10, sf); + num_samples = read_32bit(0x14, sf); + /* 0x18: unknown (usually 0, maybe some count) */ + + + /* init layout */ + data = init_layout_segmented(segment_count); + if (!data) goto fail; + + /* parse segments (usually: preload + intro + loop + ending, intro/ending may be skipped) + * Often first segment is ADPCM and rest Ogg; may only have one segment. */ + { + off_t extradata_offset, table_offset, segment_offset; + size_t segment_size; + int32_t segment_samples; + int codec; + int i, ch; + + /* open each segment subfile */ + for (i = 0; i < segment_count; i++) { + codec = read_8bit(segments_offset+0x10*i+0x00, sf); + /* 0x01(1): unknown (flag? usually 0x00/0x01/0x02) */ + if (read_8bit(segments_offset+0x10*i+0x02, sf) != 0x01) 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, sf); + extradata_offset = read_32bit(segments_offset+0x10*i+0x08, sf); + table_offset = read_32bit(segments_offset+0x10*i+0x0c, sf); + + /* create a sub-VGMSTREAM per segment + * (we'll reopen this sf as needed, so each sub-VGMSTREAM is fully independent) */ + switch(codec) { + case 0x02: { /* "adpcm" */ + data->segments[i] = allocate_vgmstream(channel_count, 0); + if (!data->segments[i]) goto fail; + + data->segments[i]->sample_rate = sample_rate; + data->segments[i]->meta_type = meta_WAVE; + data->segments[i]->coding_type = coding_IMA_int; + data->segments[i]->layout_type = layout_none; + data->segments[i]->num_samples = segment_samples; + + if (!vgmstream_open_stream(data->segments[i],sf,0x00)) + goto fail; + + /* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */ + for (ch = 0; ch < channel_count; ch++) { + segment_offset = read_32bit(table_offset + 0x04*ch, sf); + data->segments[i]->ch[ch].channel_start_offset = + data->segments[i]->ch[ch].offset = segment_offset; + + /* ADPCM setup */ + 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, sf); + /* 0x03: reserved */ + } + + break; + } + + case 0x03: { /* "dsp-adpcm" */ + data->segments[i] = allocate_vgmstream(channel_count, 0); + if (!data->segments[i]) goto fail; + + data->segments[i]->sample_rate = sample_rate; + data->segments[i]->meta_type = meta_WAVE; + data->segments[i]->coding_type = coding_NGC_DSP; + data->segments[i]->layout_type = layout_none; + data->segments[i]->num_samples = segment_samples; + + if (!vgmstream_open_stream(data->segments[i],sf,0x00)) + goto fail; + + /* bizarrely enough channel data isn't sequential (segment0 ch1+ may go after all other segments) */ + for (ch = 0; ch < channel_count; ch++) { + segment_offset = read_32bit(table_offset + 0x04*ch, sf); + data->segments[i]->ch[ch].channel_start_offset = + data->segments[i]->ch[ch].offset = segment_offset; + } + + /* ADPCM setup: 0x06 initial ps/hist1/hist2 (per channel) + 0x20 coefs (per channel) */ + dsp_read_hist(data->segments[i], sf, extradata_offset+0x02, 0x06, big_endian); + dsp_read_coefs(data->segments[i], sf, extradata_offset+0x06*channel_count+0x00, 0x20, big_endian); + + break; + } + +#ifdef VGM_USE_VORBIS + case 0x04: { /* "vorbis" */ + ogg_vorbis_meta_info_t ovmi = {0}; + + segment_offset = read_32bit(table_offset, sf); + segment_size = read_32bitBE(segment_offset, sf); /* always BE */ + + ovmi.meta_type = meta_WAVE; + ovmi.stream_size = segment_size; + + data->segments[i] = init_vgmstream_ogg_vorbis_config(sf, segment_offset+0x04, &ovmi); + if (!data->segments[i]) goto fail; + + if (data->segments[i]->num_samples != segment_samples) { + VGM_LOG("WAVE: segment %i samples != num_samples\n", i); + goto fail; + } + + break; + } +#endif + + default: /* others: s16be/s16le/mp3 as referenced in the exe? */ + VGM_LOG("WAVE: unknown codec\n"); + goto fail; + } + } + } + + /* setup segmented VGMSTREAMs */ + if (!setup_layout_segmented(data)) + goto fail; + + + /* parse samples */ + { + int32_t sample_count = 0; + int i; + + loop_flag = (loop_start_segment > 0); + + for (i = 0; i < segment_count; i++) { + if (loop_flag && loop_start_segment == i) { + loop_start_sample = sample_count; + } + + sample_count += data->segments[i]->num_samples; + + if (loop_flag && loop_end_segment-1 == i) { + loop_end_sample = sample_count; + } + } + + if (sample_count != num_samples) { + VGM_LOG("WAVE: total segments samples %i != num_samples %i\n", sample_count, num_samples); + goto fail; + } + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + + vgmstream->meta_type = meta_WAVE_segmented; + vgmstream->stream_size = get_streamfile_size(sf); /* wrong kbps otherwise */ + + /* .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->layout_type = layout_segmented; + vgmstream->layout_data = data; + + return vgmstream; + +fail: + free_layout_segmented(data); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wavebatch.c b/Frameworks/vgmstream/vgmstream/src/meta/wavebatch.c index 03cb3a505..5539f1231 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wavebatch.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wavebatch.c @@ -1,138 +1,135 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* WBAT - Firebrand Games header [Need for Speed: The Run (3DS), Fast & Furious: Showdown (3DS)] */ -VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, name_offset, offset, stream_offset; - size_t names_size, stream_size; - int loop_flag, channel_count, sample_rate, num_samples; - int big_endian, version, codec; - int total_subsongs, target_subsong = streamFile->stream_index; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - - - /* checks */ - if (!check_extensions(streamFile, "wavebatch")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x54414257) /* "TABW" */ - goto fail; - - /* section0: base header */ - big_endian = ((uint16_t)read_16bitBE(0x04,streamFile) == 0xFEFF); /* BOM (always LE on 3DS/Android) */ - if (big_endian) { - read_32bit = read_32bitBE; - read_16bit = read_16bitBE; - } else { - read_32bit = read_32bitLE; - read_16bit = read_16bitLE; - } - - - version = read_16bit(0x06, streamFile); /* assumed */ - if (version != 0x06 && version != 0x07) /* v6 = NFS: The Run , v7 = F&F Showndown */ - goto fail; - - total_subsongs = read_32bit(0x08,streamFile); - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - names_size = read_32bit(0x0c,streamFile); - /* 0x10/14: see below */ - /* 0x18: data size (all subsongs) */ - offset = 0x1c + names_size; /* skip names table */ - - /* the following 2 sections (rarely) won't match total_subsongs */ - - /* section1: unknown */ - { - size_t unknown_size = read_32bit(0x10,streamFile); - /* 0x00: usually 0, rarely 0x20? */ - offset += unknown_size*0x04; - } - - /* section2: samples */ - { - size_t samples_size = read_32bit(0x14,streamFile); - /* 0x00: num_samples */ - offset += samples_size*0x04; - } - - /* section3: headers */ - { - off_t header_offset = offset+(target_subsong-1)*0x24; - - name_offset = read_32bit(header_offset+0x00, streamFile) + 0x1c; /* within name table */ - codec = read_32bit(header_offset+0x04, streamFile); - sample_rate = read_32bit(header_offset+0x08, streamFile); - channel_count = read_32bit(header_offset+0x0c, streamFile); - /* 0x10: index within section1/2? */ - /* 0x14: flags? 0x01 or (rarely) 0x02 */ - stream_offset = read_32bit(header_offset+0x18, streamFile); - stream_size = read_32bit(header_offset+0x1c, streamFile); /* including DSP config */ - num_samples = read_32bit(header_offset+0x20, streamFile) / channel_count; /* nibble/PCMs */ - - offset += total_subsongs*0x24; - } - - loop_flag = 0; - start_offset = offset + stream_offset; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; - - vgmstream->meta_type = meta_WAVEBATCH; - - switch(codec) { - case 0x00: /* PCM16 [NASCAR Unleashed (3DS), Solar Flux Pocket (Android)] */ - vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x02; - break; - - case 0x01: /* PCM8 [Cars 2 (3DS)] */ - vgmstream->coding_type = coding_PCM8; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x01; - break; - - case 0x02: { /* DSP [WRC FIA World Rally Championship (3DS)] */ - size_t config_size = (0x20+0x14)*channel_count + (0x0c)*channel_count; /* coefs+hist + padding */ - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_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_hist (vgmstream,streamFile,start_offset+0x20,0x14+0x20,big_endian); - start_offset += config_size; - - break; - } - - default: - VGM_LOG("WAVEBATCH: unknown codec %x\n", codec); - goto fail; - } - - - - read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamFile); /* always null-terminated */ - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* WBAT - Firebrand Games header [Need for Speed: The Run (3DS), Fast & Furious: Showdown (3DS)] */ +VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *sf) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, name_offset, offset, stream_offset; + size_t names_size, stream_size; + int loop_flag, channel_count, sample_rate, num_samples; + int big_endian, version, codec; + int total_subsongs, target_subsong = sf->stream_index; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + + /* checks */ + if (!check_extensions(sf, "wavebatch")) + goto fail; + if (!is_id32be(0x00,sf, "TABW")) + goto fail; + + /* section0: base header */ + big_endian = (read_u16be(0x04,sf) == 0xFEFF); /* BOM (always LE on 3DS/Android) */ + if (big_endian) { + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + + version = read_16bit(0x06, sf); /* assumed */ + if (version != 0x06 && version != 0x07) /* v6 = NFS: The Run , v7 = F&F Showndown */ + goto fail; + + total_subsongs = read_32bit(0x08,sf); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + names_size = read_32bit(0x0c,sf); + /* 0x10/14: see below */ + /* 0x18: data size (all subsongs) */ + offset = 0x1c + names_size; /* skip names table */ + + /* the following 2 sections (rarely) won't match total_subsongs */ + + /* section1: unknown */ + { + size_t unknown_size = read_32bit(0x10,sf); + /* 0x00: usually 0, rarely 0x20? */ + offset += unknown_size*0x04; + } + + /* section2: samples */ + { + size_t samples_size = read_32bit(0x14,sf); + /* 0x00: num_samples */ + offset += samples_size*0x04; + } + + /* section3: headers */ + { + off_t header_offset = offset+(target_subsong-1)*0x24; + + name_offset = read_32bit(header_offset+0x00, sf) + 0x1c; /* within name table */ + codec = read_32bit(header_offset+0x04, sf); + sample_rate = read_32bit(header_offset+0x08, sf); + channel_count = read_32bit(header_offset+0x0c, sf); + /* 0x10: index within section1/2? */ + /* 0x14: flags? 0x01 or (rarely) 0x02 */ + stream_offset = read_32bit(header_offset+0x18, sf); + stream_size = read_32bit(header_offset+0x1c, sf); /* including DSP config */ + num_samples = read_32bit(header_offset+0x20, sf) / channel_count; /* nibble/PCMs */ + + offset += total_subsongs*0x24; + } + + loop_flag = 0; + start_offset = offset + stream_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + vgmstream->meta_type = meta_WAVEBATCH; + + switch(codec) { + case 0x00: /* PCM16 [NASCAR Unleashed (3DS), Solar Flux Pocket (Android)] */ + vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + break; + + case 0x01: /* PCM8 [Cars 2 (3DS)] */ + vgmstream->coding_type = coding_PCM8; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x01; + break; + + case 0x02: { /* DSP [WRC FIA World Rally Championship (3DS)] */ + size_t config_size = (0x20+0x14)*channel_count + (0x0c)*channel_count; /* coefs+hist + padding */ + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = (stream_size - config_size) / channel_count; /* full interleave*/; + + dsp_read_coefs(vgmstream,sf,start_offset+0x00,0x20+0x14,big_endian); + dsp_read_hist (vgmstream,sf,start_offset+0x20,0x14+0x20,big_endian); + start_offset += config_size; + + break; + } + + default: + VGM_LOG("WAVEBATCH: unknown codec %x\n", codec); + goto fail; + } + + read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf); /* always null-terminated */ + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c index 88b69899b..e41aa33d7 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wwise.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wwise.c @@ -412,7 +412,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) { vgmstream->num_samples = msd.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 } @@ -433,7 +433,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) { vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; + vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); //todo correct? break; } @@ -518,7 +518,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) { vgmstream->layout_type = layout_none; /* 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; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xnb.c b/Frameworks/vgmstream/vgmstream/src/meta/xnb.c index e07059dc2..25d42c2a0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xnb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xnb.c @@ -62,10 +62,10 @@ VGMSTREAM* init_vgmstream_xnb(STREAMFILE* sf) { char reader_name[255+1]; size_t string_len; uint8_t type_count; - const static 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 */ - const static 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_sound = "Microsoft.Xna.Framework.Content.SoundEffectReader"; /* partial "fmt" chunk or XMA */ + static const char* type_ogg = "SoundEffectFromOggReader"; /* has extra text info after base part */ + static const char* type_song = "Microsoft.Xna.Framework.Content.SongReader"; /* references a companion .wma */ + static const char* type_int32 = "Microsoft.Xna.Framework.Content.Int32Reader"; /* extra crap */ type_count = read_u8(offset++, sf_h); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xssb.c b/Frameworks/vgmstream/vgmstream/src/meta/xssb.c index 8f63c793a..668f99ca8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xssb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xssb.c @@ -128,6 +128,9 @@ VGMSTREAM* init_vgmstream_xssb(STREAMFILE *sf) { vgmstream->num_samples = xbox_ima_bytes_to_samples(h.stream_size, h.channels); break; + + default: + goto fail; } if (!vgmstream_open_stream(vgmstream, sf, h.stream_start)) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c index 3447371c6..517363f8d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -530,7 +530,7 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) { /* no wma_bytes_to_samples, this should be ok */ if (!vgmstream->num_samples) - vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; + vgmstream->num_samples = ffmpeg_get_samples(ffmpeg_data); break; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwma.c b/Frameworks/vgmstream/vgmstream/src/meta/xwma.c index 689fefa0e..c57ba915d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwma.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwma.c @@ -1,87 +1,87 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* XWMA - Microsoft WMA container [The Elder Scrolls: Skyrim (PC/X360), Hydrophobia (PC)] */ -VGMSTREAM * init_vgmstream_xwma(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t fmt_offset, data_offset, first_offset = 0xc; - size_t fmt_size, data_size; - int loop_flag, channel_count; - - - /* checks */ - /* .xwma: standard - * .xwm: The Elder Scrolls: Skyrim (PC), Blade Arcus from Shining (PC) */ - if (!check_extensions(streamFile, "xwma,xwm")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x52494646) /* "RIFF" */ - goto fail; - if (read_32bitBE(0x08,streamFile) != 0x58574D41) /* "XWMA" */ - goto fail; - - if ( !find_chunk_le(streamFile, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size) ) /* "fmt "*/ - goto fail; - if ( !find_chunk_le(streamFile, 0x64617461,first_offset,0, &data_offset,&data_size) ) /* "data"*/ - goto fail; - - channel_count = read_16bitLE(fmt_offset+0x02,streamFile); - loop_flag = 0; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(fmt_offset+0x04, streamFile); - vgmstream->meta_type = meta_XWMA; - - /* the main purpose of this meta is redoing the XWMA header to: - * - redo header to fix XWMA with buggy bit rates so FFmpeg can play them ok - * - skip seek table to fix FFmpeg buggy XWMA seeking (see init_seek) - * - read num_samples correctly - */ - -#ifdef VGM_USE_FFMPEG - { - uint8_t buf[0x100]; - int bytes, avg_bps, block_align, wma_codec; - - avg_bps = read_32bitLE(fmt_offset+0x08, streamFile); - block_align = (uint16_t)read_16bitLE(fmt_offset+0x0c, streamFile); - wma_codec = (uint16_t)read_16bitLE(fmt_offset+0x00, streamFile); - - bytes = ffmpeg_make_riff_xwma(buf,0x100, wma_codec, data_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align); - vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, data_offset,data_size); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - /* manually find total samples, why don't they put this in the header is beyond me */ - { - ms_sample_data msd = {0}; - - msd.channels = vgmstream->channels; - msd.data_offset = data_offset; - msd.data_size = data_size; - - if (wma_codec == 0x0162) - wmapro_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x00E0); - else - wma_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x001F); - - vgmstream->num_samples = msd.num_samples; - if (vgmstream->num_samples == 0) - vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; /* from avg-br */ - //num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2 - } - } -#else - goto fail; -#endif - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* XWMA - Microsoft WMA container [The Elder Scrolls: Skyrim (PC/X360), Hydrophobia (PC)] */ +VGMSTREAM * init_vgmstream_xwma(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t fmt_offset, data_offset, first_offset = 0xc; + size_t fmt_size, data_size; + int loop_flag, channel_count; + + + /* checks */ + /* .xwma: standard + * .xwm: The Elder Scrolls: Skyrim (PC), Blade Arcus from Shining (PC) */ + if (!check_extensions(streamFile, "xwma,xwm")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x52494646) /* "RIFF" */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x58574D41) /* "XWMA" */ + goto fail; + + if ( !find_chunk_le(streamFile, 0x666d7420,first_offset,0, &fmt_offset,&fmt_size) ) /* "fmt "*/ + goto fail; + if ( !find_chunk_le(streamFile, 0x64617461,first_offset,0, &data_offset,&data_size) ) /* "data"*/ + goto fail; + + channel_count = read_16bitLE(fmt_offset+0x02,streamFile); + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(fmt_offset+0x04, streamFile); + vgmstream->meta_type = meta_XWMA; + + /* the main purpose of this meta is redoing the XWMA header to: + * - redo header to fix XWMA with buggy bit rates so FFmpeg can play them ok + * - skip seek table to fix FFmpeg buggy XWMA seeking (see init_seek) + * - read num_samples correctly + */ + +#ifdef VGM_USE_FFMPEG + { + uint8_t buf[0x100]; + int bytes, avg_bps, block_align, wma_codec; + + avg_bps = read_32bitLE(fmt_offset+0x08, streamFile); + block_align = (uint16_t)read_16bitLE(fmt_offset+0x0c, streamFile); + wma_codec = (uint16_t)read_16bitLE(fmt_offset+0x00, streamFile); + + bytes = ffmpeg_make_riff_xwma(buf,0x100, wma_codec, data_size, vgmstream->channels, vgmstream->sample_rate, avg_bps, block_align); + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, data_offset,data_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + /* manually find total samples, why don't they put this in the header is beyond me */ + { + ms_sample_data msd = {0}; + + msd.channels = vgmstream->channels; + msd.data_offset = data_offset; + msd.data_size = data_size; + + if (wma_codec == 0x0162) + wmapro_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x00E0); + else + wma_get_samples(&msd, streamFile, block_align, vgmstream->sample_rate,0x001F); + + vgmstream->num_samples = msd.num_samples; + if (vgmstream->num_samples == 0) + 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 + } + } +#else + goto fail; +#endif + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwma_konami.c b/Frameworks/vgmstream/vgmstream/src/meta/xwma_konami.c index 350602a33..3ed2ca6ba 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwma_konami.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwma_konami.c @@ -1,86 +1,86 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "xwma_konami_streamfile.h" - - -/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (X360), Metal Gear Solid 3 HD (X360)] */ -VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count, codec, sample_rate; - size_t data_size; - STREAMFILE *temp_streamFile = NULL; - - - /* checks */ - if (!check_extensions(streamFile,"xwma")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x58574D41) /* "XWMA" */ - goto fail; - - codec = read_32bitBE(0x04,streamFile); - channel_count = read_32bitBE(0x08,streamFile); - sample_rate = read_32bitBE(0x0c,streamFile); - data_size = read_32bitBE(0x10,streamFile); /* data size without padding */ - loop_flag = 0; - start_offset = 0x20; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->meta_type = meta_XWMA_KONAMI; - -#ifdef VGM_USE_FFMPEG - { - uint8_t buf[0x100]; - int bytes, avg_bps, block_align; - - /* 0x10: related to size? */ - avg_bps = read_32bitBE(0x14, streamFile); - block_align = read_32bitBE(0x18, streamFile); - - /* data has padding (unrelated to KCEJ blocks) */ - temp_streamFile = setup_xwma_konami_streamfile(streamFile, start_offset, block_align); - if (!temp_streamFile) goto fail; - - bytes = ffmpeg_make_riff_xwma(buf,0x100, codec, data_size, channel_count, sample_rate, avg_bps, block_align); - vgmstream->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0x00,data_size); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - /* manually find total samples */ - { - ms_sample_data msd = {0}; - - msd.channels = vgmstream->channels; - msd.data_offset = 0x00; - msd.data_size = data_size; - - - if (codec == 0x0161) - wma_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x001F); - //else //todo not correct - // wmapro_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x00E0); - - vgmstream->num_samples = msd.num_samples; - if (vgmstream->num_samples == 0) - vgmstream->num_samples = (int32_t)((ffmpeg_codec_data*)vgmstream->codec_data)->totalSamples; /* from avg-br */ - //num_samples seem to be found in the last "seek" table entry too, as: entry / channels / 2 - } - } -#else - goto fail; -#endif - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "xwma_konami_streamfile.h" + + +/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (X360), Metal Gear Solid 3 HD (X360)] */ +VGMSTREAM * init_vgmstream_xwma_konami(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, codec, sample_rate; + size_t data_size; + STREAMFILE *temp_streamFile = NULL; + + + /* checks */ + if (!check_extensions(streamFile,"xwma")) + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x58574D41) /* "XWMA" */ + goto fail; + + codec = read_32bitBE(0x04,streamFile); + channel_count = read_32bitBE(0x08,streamFile); + sample_rate = read_32bitBE(0x0c,streamFile); + data_size = read_32bitBE(0x10,streamFile); /* data size without padding */ + loop_flag = 0; + start_offset = 0x20; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->meta_type = meta_XWMA_KONAMI; + +#ifdef VGM_USE_FFMPEG + { + uint8_t buf[0x100]; + int bytes, avg_bps, block_align; + + /* 0x10: related to size? */ + avg_bps = read_32bitBE(0x14, streamFile); + block_align = read_32bitBE(0x18, streamFile); + + /* data has padding (unrelated to KCEJ blocks) */ + temp_streamFile = setup_xwma_konami_streamfile(streamFile, start_offset, block_align); + if (!temp_streamFile) goto fail; + + bytes = ffmpeg_make_riff_xwma(buf,0x100, codec, data_size, channel_count, sample_rate, avg_bps, block_align); + vgmstream->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0x00,data_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + /* manually find total samples */ + { + ms_sample_data msd = {0}; + + msd.channels = vgmstream->channels; + msd.data_offset = 0x00; + msd.data_size = data_size; + + + if (codec == 0x0161) + wma_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x001F); + //else //todo not correct + // wmapro_get_samples(&msd, temp_streamFile, block_align, vgmstream->sample_rate,0x00E0); + + vgmstream->num_samples = msd.num_samples; + if (vgmstream->num_samples == 0) + 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 + } + } +#else + goto fail; +#endif + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/mixing.c b/Frameworks/vgmstream/vgmstream/src/mixing.c index ce0257bc1..e357a703c 100644 --- a/Frameworks/vgmstream/vgmstream/src/mixing.c +++ b/Frameworks/vgmstream/vgmstream/src/mixing.c @@ -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) { int is_prev = 1; + /* test if prev is really cancelled by this */ if ((mix_prev->time_end > 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)) @@ -687,12 +688,12 @@ void mixing_push_fade(VGMSTREAM* vgmstream, int ch_dst, double vol_start, double if (is_prev) { /* 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.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; } else if (mix_prev->time_post < 0 && mix.time_pre >= 0) { diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 64f13f6c2..3153c49c4 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -525,6 +525,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_dsp_kwa, init_vgmstream_ogv_3rdeye, init_vgmstream_sspr, + init_vgmstream_piff_tpcm, /* 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 */ @@ -606,9 +607,9 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) { #ifdef VGM_USE_FFMPEG /* check FFmpeg streams here, for lack of a better place */ if (vgmstream->coding_type == coding_FFmpeg) { - ffmpeg_codec_data *data = vgmstream->codec_data; - if (data && data->streamCount && !vgmstream->num_streams) { - vgmstream->num_streams = data->streamCount; + int ffmpeg_subsongs = ffmpeg_get_subsong_count(vgmstream->codec_data); + if (ffmpeg_subsongs && !vgmstream->num_streams) { + vgmstream->num_streams = ffmpeg_subsongs; } } #endif @@ -1464,7 +1465,21 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* } if (is_unique) { + size_t stream_size; + 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->subsong[br->count] = subsong_cur; @@ -1473,13 +1488,7 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* if (p_uniques) (*p_uniques)++; - if (vgmstream->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); - } + bitrate += stream_size; break; } diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 67ab5ed7e..62e86f6d5 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -31,14 +31,6 @@ enum { VGMSTREAM_MAX_NUM_SAMPLES = 1000000000 }; /* no ~5h vgm hopefully */ //#define VGM_USE_SPEEX -#ifdef VGM_USE_VORBIS -#include -#endif - -#ifdef VGM_USE_MPEG -#include -#endif - #ifdef VGM_USE_MP4V2 #define MP4V2_NO_STDINT_DEFS #include @@ -48,24 +40,12 @@ enum { VGMSTREAM_MAX_NUM_SAMPLES = 1000000000 }; /* no ~5h vgm hopefully */ #include #endif -#ifdef VGM_USE_MAIATRAC3PLUS -#include -#endif - -#ifdef VGM_USE_FFMPEG -#include -#include -#include -#endif - #include "clHCA.h" #ifdef BUILD_VGMSTREAM #include "coding/g72x_state.h" -#include "coding/nwa_decoder.h" #else #include "g72x_state.h" -#include "nwa_decoder.h" #endif @@ -175,6 +155,7 @@ typedef enum { coding_ASF, /* Argonaut ASF 4-bit ADPCM */ coding_DSA, /* Ocean DSA 4-bit ADPCM */ coding_XMD, /* Konami XMD 4-bit ADPCM */ + coding_TANTALUS, /* Tantalus 4-bit ADPCM */ coding_PCFX, /* PC-FX 4-bit ADPCM */ 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 */ @@ -763,6 +744,7 @@ typedef enum { meta_IDSP_TOSE, meta_DSP_KWA, meta_OGV_3RDEYE, + meta_PIFF_TPCM, } meta_t; /* standard WAVEFORMATEXTENSIBLE speaker positions */ @@ -1047,63 +1029,6 @@ typedef struct { } 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 typedef struct { STREAMFILE* streamfile;