Updated VGMStream to r1745-4-g9ef1030d

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
CQTexperiment
Christopher Snowhill 2022-05-02 14:58:25 -07:00
parent 2aa3ddd545
commit ace62005db
33 changed files with 667 additions and 201 deletions

View File

@ -251,6 +251,12 @@
836C052C23F62F3100FA07C7 /* libatrac9.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 835FC6C623F62AEF006960FA /* libatrac9.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
836EF0DB27BB975900BF35B2 /* libvorbis.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 836EF0D027BB960A00BF35B2 /* libvorbis.0.dylib */; };
836EF0DD27BB97C500BF35B2 /* libvorbisfile.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 836EF0DC27BB97BA00BF35B2 /* libvorbisfile.3.dylib */; };
836F46AE28208735005B9B87 /* blocked_tt_ad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46AD28208735005B9B87 /* blocked_tt_ad.c */; };
836F46B22820874D005B9B87 /* tt_ad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46AF2820874D005B9B87 /* tt_ad.c */; };
836F46B32820874D005B9B87 /* esf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46B02820874D005B9B87 /* esf.c */; };
836F46B42820874D005B9B87 /* adm3.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46B12820874D005B9B87 /* adm3.c */; };
836F46B7282087A6005B9B87 /* cri_utf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F46B5282087A6005B9B87 /* cri_utf.c */; };
836F46B8282087A6005B9B87 /* cri_utf.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F46B6282087A6005B9B87 /* cri_utf.h */; };
836F6B4718BDB8880095E648 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836F6B4518BDB8880095E648 /* InfoPlist.strings */; };
836F6F1E18BDC2190095E648 /* acm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE018BDC2180095E648 /* acm_decoder.c */; };
836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE218BDC2180095E648 /* adx_decoder.c */; };
@ -677,8 +683,6 @@
83FBD506235D31F800D35BCD /* riff_ogg_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FBD502235D31F700D35BCD /* riff_ogg_streamfile.h */; };
83FC176D23AC58D100E1025F /* xma_ue3.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FC176A23AC58D100E1025F /* xma_ue3.c */; };
83FC176E23AC58D100E1025F /* csb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FC176B23AC58D100E1025F /* csb.c */; };
83FC176F23AC58D100E1025F /* cri_utf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FC176C23AC58D100E1025F /* cri_utf.h */; };
83FC177123AC59A800E1025F /* cri_utf.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FC177023AC59A800E1025F /* cri_utf.c */; };
83FC417026D32FF5009A2022 /* hca_decoder_clhca.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FC416E26D32FF5009A2022 /* hca_decoder_clhca.h */; };
83FC417126D32FF5009A2022 /* hca_decoder_clhca.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FC416F26D32FF5009A2022 /* hca_decoder_clhca.c */; };
83FC417326D3304D009A2022 /* xsh_xsd_xss.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FC417226D3304D009A2022 /* xsh_xsd_xss.c */; };
@ -1042,6 +1046,12 @@
835FC6C123F62AEE006960FA /* libatrac9.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libatrac9.xcodeproj; path = ../libatrac9/libatrac9.xcodeproj; sourceTree = "<group>"; };
836EF0D027BB960A00BF35B2 /* libvorbis.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libvorbis.0.dylib; path = ../../ThirdParty/vorbis/lib/libvorbis.0.dylib; sourceTree = "<group>"; };
836EF0DC27BB97BA00BF35B2 /* libvorbisfile.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libvorbisfile.3.dylib; path = ../../ThirdParty/vorbis/lib/libvorbisfile.3.dylib; sourceTree = "<group>"; };
836F46AD28208735005B9B87 /* blocked_tt_ad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_tt_ad.c; sourceTree = "<group>"; };
836F46AF2820874D005B9B87 /* tt_ad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tt_ad.c; sourceTree = "<group>"; };
836F46B02820874D005B9B87 /* esf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = esf.c; sourceTree = "<group>"; };
836F46B12820874D005B9B87 /* adm3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adm3.c; sourceTree = "<group>"; };
836F46B5282087A6005B9B87 /* cri_utf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cri_utf.c; sourceTree = "<group>"; };
836F46B6282087A6005B9B87 /* cri_utf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cri_utf.h; sourceTree = "<group>"; };
836F6B3918BDB8880095E648 /* libvgmstream.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libvgmstream.framework; sourceTree = BUILT_PRODUCTS_DIR; };
836F6B4418BDB8880095E648 /* libvgmstream-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "libvgmstream-Info.plist"; sourceTree = "<group>"; };
836F6B4618BDB8880095E648 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -1466,8 +1476,6 @@
83FBD502235D31F700D35BCD /* riff_ogg_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = riff_ogg_streamfile.h; sourceTree = "<group>"; };
83FC176A23AC58D100E1025F /* xma_ue3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xma_ue3.c; sourceTree = "<group>"; };
83FC176B23AC58D100E1025F /* csb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = csb.c; sourceTree = "<group>"; };
83FC176C23AC58D100E1025F /* cri_utf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cri_utf.h; sourceTree = "<group>"; };
83FC177023AC59A800E1025F /* cri_utf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cri_utf.c; sourceTree = "<group>"; };
83FC416E26D32FF5009A2022 /* hca_decoder_clhca.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hca_decoder_clhca.h; sourceTree = "<group>"; };
83FC416F26D32FF5009A2022 /* hca_decoder_clhca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hca_decoder_clhca.c; sourceTree = "<group>"; };
83FC417226D3304D009A2022 /* xsh_xsd_xss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xsh_xsd_xss.c; sourceTree = "<group>"; };
@ -1775,6 +1783,7 @@
8306B09C20984550000302D4 /* blocked_str_snds.c */,
8306B09820984550000302D4 /* blocked_thp.c */,
8306B09920984550000302D4 /* blocked_tra.c */,
836F46AD28208735005B9B87 /* blocked_tt_ad.c */,
83031ECA243C50CB00C3F3E0 /* blocked_ubi_sce.c */,
83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */,
83031ECB243C50CB00C3F3E0 /* blocked_vid1.c */,
@ -1810,6 +1819,7 @@
837CEAD623487E8300E62A4A /* acb.c */,
836F6E2B18BDC2180095E648 /* acm.c */,
83F2CCE125A5B41600F46FA8 /* acx.c */,
836F46B12820874D005B9B87 /* adm3.c */,
83D26A7626E66D98001A9475 /* adp_bos.c */,
83AA7F7A2519C042004C5298 /* adp_konami.c */,
834FE0CF215C79E8000A5D3D /* adpcm_capcom.c */,
@ -1863,8 +1873,6 @@
834FE0E8215C79EC000A5D3D /* ck.c */,
8346D97825BF838C00D1A8B0 /* compresswave.c */,
83A8BAE425667AA7000F5F3F /* cpk.c */,
83FC177023AC59A800E1025F /* cri_utf.c */,
83FC176C23AC58D100E1025F /* cri_utf.h */,
83FC176B23AC58D100E1025F /* csb.c */,
834FE0D8215C79EA000A5D3D /* csmp.c */,
836F6E3C18BDC2180095E648 /* Cstr.c */,
@ -1896,6 +1904,7 @@
83AF2CC826226BA500538240 /* encrypted_bgm_streamfile.h */,
832FC36E278FAE3E0056A860 /* encrypted_mc161_streamfile.h */,
83031ECE243C50DE00C3F3E0 /* encrypted.c */,
836F46B02820874D005B9B87 /* esf.c */,
836F6E4918BDC2180095E648 /* exakt_sc.c */,
836F6E4A18BDC2180095E648 /* excitebots.c */,
83AF2CC626226BA400538240 /* exst.c */,
@ -2169,6 +2178,7 @@
83E7FD6425EF2B2400683FD2 /* tac.c */,
8373342E23F60D4100DE14DC /* tgc.c */,
836F6EFA18BDC2190095E648 /* thp.c */,
836F46AF2820874D005B9B87 /* tt_ad.c */,
836F6EFB18BDC2190095E648 /* tun.c */,
83C7280122BC893A00678B4A /* txth_streamfile.h */,
830165971F256BD000CA0941 /* txth.c */,
@ -2274,6 +2284,8 @@
children = (
83D26A8026E66DC2001A9475 /* chunks.c */,
83D26A7E26E66DC2001A9475 /* chunks.h */,
836F46B5282087A6005B9B87 /* cri_utf.c */,
836F46B6282087A6005B9B87 /* cri_utf.h */,
83B46FD42707FB9A00847FC9 /* endianness.h */,
83D26A7D26E66DC2001A9475 /* log.c */,
83D26A7F26E66DC2001A9475 /* log.h */,
@ -2325,6 +2337,7 @@
83D26A8326E66DC2001A9475 /* log.h in Headers */,
83C7282222BC893D00678B4A /* mta2_streamfile.h in Headers */,
83AA7F802519C042004C5298 /* sab_streamfile.h in Headers */,
836F46B8282087A6005B9B87 /* cri_utf.h in Headers */,
83A21F87201D8981000F04B9 /* fsb_keys.h in Headers */,
83E7FD6325EF2B0C00683FD2 /* tac_decoder_lib_data.h in Headers */,
832FC36C278FA4CB0056A860 /* ubi_ckd_cwav_streamfile.h in Headers */,
@ -2341,7 +2354,6 @@
8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */,
83D2007A248DDB770048BD24 /* fsb_encrypted_streamfile.h in Headers */,
836F6F2718BDC2190095E648 /* g72x_state.h in Headers */,
83FC176F23AC58D100E1025F /* cri_utf.h in Headers */,
83C7282822BC8C1500678B4A /* mixing.h in Headers */,
832BF82C21E0514B006F50F1 /* hca_keys_awb.h in Headers */,
839933602591E8C1001855AF /* ubi_sb_garbage_streamfile.h in Headers */,
@ -2611,6 +2623,7 @@
836F6F9B18BDC2190095E648 /* mn_str.c in Sources */,
832BF82821E0514B006F50F1 /* xwma.c in Sources */,
83FC176E23AC58D100E1025F /* csb.c in Sources */,
836F46B32820874D005B9B87 /* esf.c in Sources */,
8306B0EB20984590000302D4 /* wave_segmented.c in Sources */,
83E7FD5F25EF2B0C00683FD2 /* tac_decoder.c in Sources */,
836F6F9F18BDC2190095E648 /* musc.c in Sources */,
@ -2622,6 +2635,7 @@
836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */,
8346D97925BF838C00D1A8B0 /* idtech.c in Sources */,
83FF0EBC1E93282100C58054 /* wwise.c in Sources */,
836F46B42820874D005B9B87 /* adm3.c in Sources */,
836F6F7018BDC2190095E648 /* apple_caff.c in Sources */,
836F6FB618BDC2190095E648 /* ngc_sck_dsp.c in Sources */,
836F6F2818BDC2190095E648 /* ima_decoder.c in Sources */,
@ -2785,6 +2799,7 @@
83C7282022BC893D00678B4A /* dcs_wav.c in Sources */,
8306B0F220984590000302D4 /* ubi_jade.c in Sources */,
83852B0C2680247900378854 /* ads_midway.c in Sources */,
836F46AE28208735005B9B87 /* blocked_tt_ad.c in Sources */,
836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */,
836F6F2918BDC2190095E648 /* l5_555_decoder.c in Sources */,
836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */,
@ -2865,6 +2880,7 @@
836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */,
836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */,
836F702118BDC2190095E648 /* rs03.c in Sources */,
836F46B7282087A6005B9B87 /* cri_utf.c in Sources */,
836F6F8818BDC2190095E648 /* fsb.c in Sources */,
83F2CCE525A5B41600F46FA8 /* acx.c in Sources */,
83FC176D23AC58D100E1025F /* xma_ue3.c in Sources */,
@ -2988,6 +3004,7 @@
834FE100215C79ED000A5D3D /* svg.c in Sources */,
836F6F2518BDC2190095E648 /* g721_decoder.c in Sources */,
836F6FE818BDC2190095E648 /* ps2_mic.c in Sources */,
836F46B22820874D005B9B87 /* tt_ad.c in Sources */,
836F6F3C18BDC2190095E648 /* xa_decoder.c in Sources */,
8317C24C26982CC1007DD0B8 /* sspr.c in Sources */,
832BF82521E0514B006F50F1 /* ogg_opus.c in Sources */,
@ -2995,7 +3012,6 @@
836F6F9118BDC2190095E648 /* ios_psnd.c in Sources */,
836F700618BDC2190095E648 /* vgs_ps.c in Sources */,
834FE10F215C79ED000A5D3D /* sdf.c in Sources */,
83FC177123AC59A800E1025F /* cri_utf.c in Sources */,
834FE0FF215C79ED000A5D3D /* sqex_scd_sscf.c in Sources */,
8373341A23F60C7B00DE14DC /* relic_decoder_mixfft.c in Sources */,
836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */,

View File

@ -265,13 +265,12 @@ size_t ptadpcm_bytes_to_samples(size_t bytes, int channels, size_t frame_size);
/* ubi_adpcm_decoder */
typedef struct ubi_adpcm_codec_data ubi_adpcm_codec_data;
ubi_adpcm_codec_data* init_ubi_adpcm(STREAMFILE* sf, off_t offset, int channels);
ubi_adpcm_codec_data* init_ubi_adpcm(STREAMFILE* sf, uint32_t offset, uint32_t size, int channels);
void decode_ubi_adpcm(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do);
void reset_ubi_adpcm(ubi_adpcm_codec_data* data);
void seek_ubi_adpcm(ubi_adpcm_codec_data* data, int32_t num_sample);
void free_ubi_adpcm(ubi_adpcm_codec_data* data);
int32_t ubi_adpcm_get_samples(ubi_adpcm_codec_data* data);
int32_t ubi_adpcm_bytes_to_samples(ubi_adpcm_codec_data* data, uint32_t size);
/* imuse_decoder */
@ -492,6 +491,7 @@ void free_mpeg(mpeg_codec_data* data);
int mpeg_get_sample_rate(mpeg_codec_data* data);
long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data* data);
uint32_t mpeg_get_tag_size(STREAMFILE* sf, uint32_t offset, uint32_t header);
int mpeg_get_frame_info(STREAMFILE* sf, off_t offset, mpeg_frame_info* info);
#endif

View File

@ -203,8 +203,11 @@ STREAMFILE* hca_get_streamfile(hca_codec_data* data) {
* (ex. newer Tales of the Rays files clip a lot) */
#define HCA_KEY_MIN_TEST_FRAMES 3 //7
#define HCA_KEY_MAX_TEST_FRAMES 7 //12
/* score of 10~30 isn't uncommon in a single frame, too many frames over that is unlikely */
#define HCA_KEY_MAX_FRAME_SCORE 150
/* score of 10~30 isn't uncommon in a single frame, too many frames over that is unlikely
* In rare cases of badly mastered frames there are +580. [Iris Mysteria! (Android)]
* Lesser is preferable (faster skips) but high scores are less common in the current detection. */
//TODO: may need to improve detection by counting silent (0) vs valid samples, as bad keys give lots of 0s
#define HCA_KEY_MAX_FRAME_SCORE 600
#define HCA_KEY_MAX_TOTAL_SCORE (HCA_KEY_MAX_TEST_FRAMES * 50*HCA_KEY_SCORE_SCALE)
/* Test a number of frames if key decrypts correctly.
@ -267,7 +270,7 @@ static int test_hca_score(hca_codec_data* data, hca_keytest_t* hk) {
switch(score) {
case 1: score = 1; break;
case 0: score = 3*HCA_KEY_SCORE_SCALE; break; /* blanks after non-blacks aren't very trustable */
default: score = score*HCA_KEY_SCORE_SCALE;
default: score = score * HCA_KEY_SCORE_SCALE;
}
total_score += score;

View File

@ -563,21 +563,23 @@ void decode_blitz_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channels
/* IMA with custom frame sizes, header and nibble layout. Outputs an odd number of samples per frame,
* so to simplify calcs this decodes full frames, thus hist doesn't need to be mantained.
* Officially defined in "Microsoft Multimedia Standards Update" doc (RIFFNEW.pdf). */
void decode_ms_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
void decode_ms_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, samples_read = 0, samples_done = 0, max_samples;
int32_t hist1;// = stream->adpcm_history1_32;
int step_index;// = stream->adpcm_step_index;
int frame_channels = vgmstream->codec_config ? 1 : vgmstream->channels; /* mono or mch modes */
int frame_channel = vgmstream->codec_config ? 0 : channel;
/* internal interleave (configurable size), mixed channels */
int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
int block_samples = ((vgmstream->frame_size - 0x04*frame_channels) * 2 / frame_channels) + 1;
first_sample = first_sample % block_samples;
/* normal header (hist+step+reserved), per channel */
{ //if (first_sample == 0) {
off_t header_offset = stream->offset + 0x04*channel;
off_t header_offset = stream->offset + 0x04*frame_channel;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */
hist1 = read_s16le(header_offset+0x00,stream->streamfile);
step_index = read_u8(header_offset+0x02,stream->streamfile); /* 0x03: reserved */
if (step_index < 0) step_index = 0;
if (step_index > 88) step_index = 88;
@ -595,7 +597,7 @@ void decode_ms_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t *
/* decode nibbles (layout: alternates 4 bytes/4*2 nibbles per channel) */
for (i = 0; i < max_samples; i++) {
off_t byte_offset = stream->offset + 0x04*vgmstream->channels + 0x04*channel + 0x04*vgmstream->channels*(i/8) + (i%8)/2;
off_t byte_offset = stream->offset + 0x04*frame_channels + 0x04*frame_channel + 0x04*frame_channels*(i/8) + (i%8)/2;
int nibble_shift = (i&1?4:0); /* low nibble first */
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index); /* original expand */
@ -609,7 +611,7 @@ void decode_ms_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t *
/* internal interleave: increment offset on complete frame */
if (first_sample + samples_done == block_samples) {
stream->offset += vgmstream->interleave_block_size;
stream->offset += vgmstream->frame_size;
}
//stream->adpcm_history1_32 = hist1;

View File

@ -340,6 +340,37 @@ int mpeg_get_frame_info(STREAMFILE* sf, off_t offset, mpeg_frame_info* info) {
return mpeg_get_frame_info_h(header, info);
}
uint32_t mpeg_get_tag_size(STREAMFILE* sf, uint32_t offset, uint32_t header) {
if (!header)
header = read_u32be(offset+0x00, sf);
/* skip ID3v2 */
if ((header & 0xFFFFFF00) == get_id32be("ID3\0")) {
size_t frame_size = 0;
uint8_t flags = read_u8(offset+0x05, sf);
/* this is how it's officially read :/ */
frame_size += read_u8(offset+0x06, sf) << 21;
frame_size += read_u8(offset+0x07, sf) << 14;
frame_size += read_u8(offset+0x08, sf) << 7;
frame_size += read_u8(offset+0x09, sf) << 0;
frame_size += 0x0a;
if (flags & 0x10) /* footer? */
frame_size += 0x0a;
return frame_size;
}
/* skip ID3v1 */
if ((header & 0xFFFFFF00) == get_id32be("TAG\0")) {
;VGM_LOG("MPEG: ID3v1 at %x\n", offset);
return 0x80;
}
return 0;
}
size_t mpeg_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes) {
off_t offset = start_offset;
off_t max_offset = start_offset + bytes;
@ -355,32 +386,13 @@ size_t mpeg_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes) {
/* MPEG may use VBR so must read all frames */
while (offset < max_offset) {
uint32_t header = read_u32be(offset+0x00, sf);
/* skip ID3v2 */
if ((header & 0xFFFFFF00) == 0x49443300) { /* "ID3\0" */
size_t frame_size = 0;
uint8_t flags = read_u8(offset+0x05, sf);
/* this is how it's officially read :/ */
frame_size += read_u8(offset+0x06, sf) << 21;
frame_size += read_u8(offset+0x07, sf) << 14;
frame_size += read_u8(offset+0x08, sf) << 7;
frame_size += read_u8(offset+0x09, sf) << 0;
frame_size += 0x0a;
if (flags & 0x10) /* footer? */
frame_size += 0x0a;
offset += frame_size;
size_t tag_size = mpeg_get_tag_size(sf, offset, header);
if (tag_size) {
offset += tag_size;
continue;
}
/* skip ID3v1 */
if ((header & 0xFFFFFF00) == 0x54414700) { /* "TAG\0" */
;VGM_LOG("MPEG: ID3v1 at %lx\n", offset);
offset += 0x80;
continue;
}
/* regular frame */
/* regular frame (assumed) */
if (!mpeg_get_frame_info_h(header, &info)) {
VGM_LOG("MPEG: unknown frame at %lx\n", offset);
break;
@ -407,28 +419,31 @@ size_t mpeg_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes) {
}
/* other flags indicate seek table and stuff */
/* vendor specific */
if (info.frame_size > xing_offset + 0x78 + 0x24 &&
read_u32be(offset + xing_offset + 0x78, sf) == 0x4C414D45) { /* "LAME" */
if (info.layer == 3) {
uint32_t delays = read_u32be(offset + xing_offset + 0x8C, sf);
encoder_delay = ((delays >> 12) & 0xFFF);
encoder_padding = ((delays >> 0) & 0xFFF);
;VGM_LOG("MPEG: found Xing header\n");
encoder_delay += (528 + 1); /* implicit MDCT decoder delay (seen in LAME source) */
if (encoder_padding > 528 + 1)
encoder_padding -= (528 + 1);
}
else {
encoder_delay = 240 + 1;
/* vendor specific */
if (info.frame_size > xing_offset + 0x78 + 0x24) {
uint32_t sub_id = read_u32be(offset + xing_offset + 0x78, sf);
if (sub_id == get_id32be("LAME") || /* LAME */
sub_id == get_id32be("Lavc")) { /* FFmpeg */
if (info.layer == 3) {
uint32_t delays = read_u32be(offset + xing_offset + 0x8C, sf);
encoder_delay = ((delays >> 12) & 0xFFF);
encoder_padding = ((delays >> 0) & 0xFFF);
encoder_delay += (528 + 1); /* implicit MDCT decoder delay (seen in LAME source) */
if (encoder_padding > 528 + 1)
encoder_padding -= (528 + 1);
}
else {
encoder_delay = 240 + 1;
}
}
/* replay gain and stuff */
}
/* there is also "iTunes" vendor with no apparent extra info, iTunes delays are in "iTunSMPB" ID3 tag */
;VGM_LOG("MPEG: found Xing header\n");
break; /* we got samples */
}
}

View File

@ -71,8 +71,8 @@ struct ubi_adpcm_codec_data {
ubi_adpcm_header_data header;
ubi_adpcm_channel_data ch[UBI_CHANNELS_MAX];
off_t start_offset;
off_t offset;
uint32_t start_offset;
uint32_t offset;
int subframe_number;
uint8_t frame[UBI_FRAME_SIZE_MAX];
@ -86,16 +86,17 @@ struct ubi_adpcm_codec_data {
/* *********************************************************************** */
static int parse_header(STREAMFILE* sf, ubi_adpcm_codec_data* data, off_t offset);
static int parse_header(STREAMFILE* sf, ubi_adpcm_codec_data* data, uint32_t offset, uint32_t size);
static void decode_frame(STREAMFILE* sf, ubi_adpcm_codec_data* data);
static void fix_samples(ubi_adpcm_codec_data* data, uint32_t size);
ubi_adpcm_codec_data* init_ubi_adpcm(STREAMFILE* sf, off_t offset, int channels) {
ubi_adpcm_codec_data* init_ubi_adpcm(STREAMFILE* sf, uint32_t offset, uint32_t size, int channels) {
ubi_adpcm_codec_data* data = NULL;
data = calloc(1, sizeof(ubi_adpcm_codec_data));
if (!data) goto fail;
if (!parse_header(sf, data, offset)) {
if (!parse_header(sf, data, offset, size)) {
VGM_LOG("UBI ADPCM: wrong header\n");
goto fail;
}
@ -193,7 +194,7 @@ static void read_header_state(uint8_t* data, ubi_adpcm_header_data* header) {
header->channels = get_u32le(data + 0x2c);
}
static int parse_header(STREAMFILE* sf, ubi_adpcm_codec_data* data, off_t offset) {
static int parse_header(STREAMFILE* sf, ubi_adpcm_codec_data* data, uint32_t offset, uint32_t size) {
uint8_t buf[0x30];
size_t bytes;
@ -214,6 +215,11 @@ static int parse_header(STREAMFILE* sf, ubi_adpcm_codec_data* data, off_t offset
if (data->header.channels > UBI_CHANNELS_MAX || data->header.channels < UBI_CHANNELS_MIN)
goto fail;
/* some kind of internal bug I guess, seen in a few subsongs in Rayman 3 PC demo */
if (data->header.sample_count == 0x77E7A374 * data->header.channels) {
fix_samples(data, size);
}
return 1;
fail:
return 0;
@ -548,8 +554,8 @@ static void decode_frame(STREAMFILE* sf, ubi_adpcm_codec_data* data) {
bytes = read_streamfile(data->frame, data->offset, frame_size, sf);
if (bytes != frame_size) {
VGM_LOG("UBI ADPCM: wrong bytes read %x vs %x at %lx\n", bytes, frame_size, data->offset);
//goto fail; //?
VGM_LOG("UBI ADPCM: wrong bytes read %x vs %x at %x\n", bytes, frame_size, data->offset);
//goto fail; //may reach EOF earlier
}
if (channels == 1) {
@ -587,21 +593,37 @@ int32_t ubi_adpcm_get_samples(ubi_adpcm_codec_data* data) {
return data->header.sample_count / data->header.channels;
}
int32_t ubi_adpcm_bytes_to_samples(ubi_adpcm_codec_data* data, uint32_t size) {
uint32_t frame_size;
static void fix_samples(ubi_adpcm_codec_data* data, uint32_t size) {
uint32_t frame_size, setup_size, subframe_size, base_frames, last_size;
int subframes;
int32_t samples;
if (!data || !data->header.channels || !data->header.subframes_per_frame)
return 0;
if (!data || !data->header.channels || !data->header.subframes_per_frame || !size)
return;
size -= 0x30; /* ignore header */
setup_size = 0x34 * data->header.channels; /* setup per channel */
subframe_size = (data->header.codes_per_subframe * data->header.bits_per_sample /*+ 8*/) / 8 + 0x01; /* padding byte */
frame_size = setup_size + subframe_size * data->header.subframes_per_frame;
/* don't trust subframe count */
base_frames = ((size - 0x01) / frame_size); /* force smaller size just in case so last frame isn't used */
last_size = size - (base_frames * frame_size);
subframes = base_frames * data->header.subframes_per_frame;
size -= 0x30; /* header */
samples = base_frames * (data->header.codes_per_subframe * data->header.subframes_per_frame);
frame_size = 0x34 * data->header.channels; /* setup per channel */
frame_size += (data->header.codes_per_subframe * data->header.bits_per_sample /*+ 8*/) * data->header.subframes_per_frame / 8;
frame_size += data->header.subframes_per_frame * 0x01; /* padding byte */
/* last subframe is shorter (and may contain padding after codes_per_subframe_last), and last frame may not contain all subframes */
if (last_size > setup_size + subframe_size) {
samples += data->header.codes_per_subframe * (data->header.subframes_per_frame - 1);
subframes += (data->header.subframes_per_frame - 1);
}
return ((size - 0x01) / frame_size) * /* force smaller size so last frame isn't used */
data->header.codes_per_subframe * data->header.subframes_per_frame +
data->header.codes_per_subframe_last * data->header.subframes_per_frame;
/* for some reason several files that need fixing seem to have garbage in the 2nd half of last codes */
samples += data->header.codes_per_subframe_last / 2;
subframes += 1;
data->header.sample_count = samples; /* for all channels */
data->header.subframe_count = subframes;
}

View File

@ -428,7 +428,9 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
return 64;
case coding_MS_IMA:
case coding_REF_IMA:
return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;/* +1 from header sample */
case coding_MS_IMA_mono:
return ((vgmstream->frame_size - 0x04) * 2) + 1; /* +1 from header sample */
case coding_RAD_IMA:
return (vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels;
case coding_NDS_IMA:
@ -628,12 +630,14 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
case coding_OKI4S:
case coding_MTF_IMA:
return 0x01;
case coding_MS_IMA:
case coding_RAD_IMA:
case coding_NDS_IMA:
case coding_DAT4_IMA:
case coding_REF_IMA:
return vgmstream->interleave_block_size;
case coding_MS_IMA:
case coding_MS_IMA_mono:
return vgmstream->frame_size;
case coding_AWC_IMA:
return 0x800;
case coding_RAD_IMA_mono:
@ -931,6 +935,9 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
}
break;
case coding_MS_IMA:
case coding_MS_IMA_mono:
//TODO: improve
vgmstream->codec_config = (vgmstream->coding_type == coding_MS_IMA_mono) || vgmstream->channels == 1; /* mono mode */
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_ms_ima(vgmstream,&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do, ch);

View File

@ -82,6 +82,7 @@ static const char* extension_list[] = {
"atx",
"aud",
"audio", //txth/reserved [Grimm Echoes (Android)]
"audio_data",
"aus",
"awa", //txth/reserved [Missing Parts Side A (PS2)]
"awb",
@ -172,6 +173,7 @@ static const char* extension_list[] = {
"enm",
"eno",
"ens",
"esf",
"exa",
"ezw",
@ -431,6 +433,7 @@ static const char* extension_list[] = {
"rxx", //txth/reserved [Full Auto (X360)]
"s14",
"s3s", //txth/reserved [DT Racer (PS2)]
"s3v", //Sound Voltex (AC)
"sab",
"sad",
@ -520,6 +523,7 @@ static const char* extension_list[] = {
"swag",
"swav",
"swd",
"switch", //txth/reserved (.m4a-x.switch) [Ikinari Maou (Switch)]
"switch_audio",
"sx",
"sxd",
@ -778,6 +782,7 @@ static const coding_info coding_info_list[] = {
{coding_MTF_IMA, "MT Framework 4-bit IMA ADPCM"},
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
{coding_MS_IMA_mono, "Microsoft 4-bit IMA ADPCM (mono/interleave)"},
{coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"},
{coding_XBOX_IMA_mch, "XBOX 4-bit IMA ADPCM (multichannel)"},
{coding_XBOX_IMA_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"},
@ -925,6 +930,7 @@ static const layout_info layout_info_list[] = {
{layout_blocked_vs_square, "blocked (Square VS)"},
{layout_blocked_vid1, "blocked (VID1)"},
{layout_blocked_ubi_sce, "blocked (Ubi SCE)"},
{layout_blocked_tt_ad, "blocked (TT AD)"},
};
static const meta_info meta_info_list[] = {
@ -1389,6 +1395,9 @@ static const meta_info meta_info_list[] = {
{meta_MPEG, "MPEG header"},
{meta_SSPF, "Konami SSPF header"},
{meta_S3V, "Konami S3V header"},
{meta_ESF, "Eurocom ESF header"},
{meta_ADM3, "Crankcase ADM3 header"},
{meta_TT_AD, "Traveller's Tales AUDIO_DATA header"},
};
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {

View File

@ -358,7 +358,13 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t*
* segments use only a few samples from a full file (like Wwise transitions), bitrates
* become a bit high since its hard to detect only part of the file is needed. */
if (vgmstream->layout_type == layout_segmented) {
if (vgmstream->stream_size != 0) {
/* format may report full size for custom layouts that otherwise get odd values */
bitrate += get_vgmstream_file_bitrate_from_size(vgmstream->stream_size, vgmstream->sample_rate, vgmstream->num_samples);
if (p_uniques)
(*p_uniques)++;
}
else if (vgmstream->layout_type == layout_segmented) {
int uniques = 0;
segmented_layout_data *data = (segmented_layout_data *) vgmstream->layout_data;
for (i = 0; i < data->segment_count; i++) {
@ -400,20 +406,20 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t*
}
if (is_unique) {
size_t stream_size;
size_t file_bitrate;
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);
file_bitrate = 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);
file_bitrate = get_vgmstream_file_bitrate_from_streamfile(sf_cur, vgmstream->sample_rate, vgmstream->num_samples);
}
/* possible in cases like using silence codec */
if (!stream_size)
if (!file_bitrate)
break;
br->hash[br->count] = hash_cur;
@ -423,7 +429,7 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t*
if (p_uniques)
(*p_uniques)++;
bitrate += stream_size;
bitrate += file_bitrate;
break;
}

View File

@ -213,6 +213,9 @@ void block_update(off_t block_offset, VGMSTREAM* vgmstream) {
case layout_blocked_ubi_sce:
block_update_ubi_sce(block_offset,vgmstream);
break;
case layout_blocked_tt_ad:
block_update_tt_ad(block_offset,vgmstream);
break;
default: /* not a blocked layout */
break;
}

View File

@ -0,0 +1,31 @@
#include "layout.h"
/* Traveller's Tales blocks (.AUDIO_DATA) */
void block_update_tt_ad(off_t block_offset, VGMSTREAM* vgmstream) {
STREAMFILE* sf = vgmstream->ch[0].streamfile;
uint32_t header_id, block_size, header_size;
int i;
header_size = 0x00;
block_size = vgmstream->frame_size;
//TODO could be optimized?
/* first chunk and last frame has an extra header:
* 0x00: id
* 0x04: 0 in FRST, left samples in LAST, others not seen (found in exe) */
header_id = read_u32be(block_offset, sf);
if (header_id == get_id32be("FRST") || header_id == get_id32be("LAST") ||
header_id == get_id32be("LSRT") || header_id == get_id32be("LEND")) {
header_size = 0x08;
}
VGM_ASSERT(header_id == get_id32be("LSRT") || header_id == get_id32be("LEND"), "TT-AD: loop found\n");
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = block_size /* * vgmstream->channels*/;
vgmstream->next_block_offset = block_offset + block_size * vgmstream->channels + header_size;
/* MS-IMA = same offset per channel */
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + header_size + block_size * i;
}
}

View File

@ -49,6 +49,7 @@ void block_update_xa_aiff(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vs_square(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_vid1(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_ubi_sce(off_t block_offset, VGMSTREAM* vgmstream);
void block_update_tt_ad(off_t block_offset, VGMSTREAM* vgmstream);
/* other layouts */
void render_vgmstream_interleave(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);

View File

@ -1,31 +1,32 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "cri_utf.h"
#include "../util/cri_utf.h"
#define MAX_SEGMENTS 2 /* usually segment0=intro, segment1=loop/main */
/* AAX - segmented ADX [Bayonetta (PS3), Pandora's Tower (Wii), Catherine (X360), Binary Domain (PS3)] */
VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
int loop_flag = 0, channel_count = 0;
VGMSTREAM* init_vgmstream_aax(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
int loop_flag = 0, channels = 0;
int32_t sample_count, loop_start_sample = 0, loop_end_sample = 0;
segmented_layout_data *data = NULL;
segmented_layout_data* data = NULL;
int segment_count, loop_segment = 0, is_hca;
off_t segment_offset[MAX_SEGMENTS];
size_t segment_size[MAX_SEGMENTS];
int i;
utf_context *utf = NULL;
utf_context* utf = NULL;
/* checks */
if (!is_id32be(0x00,sf, "@UTF"))
goto fail;
/* .aax: often with extension (with either HCA or AAX tables)
* (extensionless): sometimes without [PES 2013 (PC)] */
if (!check_extensions(streamFile, "aax,"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x40555446) /* "@UTF" */
if (!check_extensions(sf, "aax,"))
goto fail;
/* .aax contains a simple UTF table, each row being a segment pointing to a CRI audio format */
@ -35,7 +36,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
uint32_t table_offset = 0x00;
utf = utf_open(streamFile, table_offset, &rows, &name);
utf = utf_open(sf, table_offset, &rows, &name);
if (!utf) goto fail;
if (strcmp(name, "AAX") == 0)
@ -74,7 +75,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
/* open each segment subfile */
for (i = 0; i < segment_count; i++) {
STREAMFILE* temp_sf = setup_subfile_streamfile(streamFile, segment_offset[i],segment_size[i], (is_hca ? "hca" : "adx"));
STREAMFILE* temp_sf = setup_subfile_streamfile(sf, segment_offset[i],segment_size[i], (is_hca ? "hca" : "adx"));
if (!temp_sf) goto fail;
data->segments[i] = is_hca ?
@ -105,11 +106,11 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
}
}
channel_count = data->output_channels;
channels = data->output_channels;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = data->segments[0]->sample_rate;
@ -135,21 +136,22 @@ fail:
/* CRI's UTF wrapper around DSP [Sonic Colors sfx (Wii), NiGHTS: Journey of Dreams sfx (Wii)] */
VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_utf_dsp(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
uint8_t loop_flag = 0, channel_count;
uint8_t loop_flag = 0, channels;
uint32_t sample_rate, num_samples, loop_start, loop_end, interleave;
uint32_t data_offset, data_size, header_offset, header_size;
utf_context *utf = NULL;
utf_context* utf = NULL;
/* checks */
if (!is_id32be(0x00,sf, "@UTF"))
goto fail;
/* .aax: assumed
* (extensionless): extracted names inside csb/cpk often don't have extensions */
if (!check_extensions(streamFile, "aax,"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x40555446) /* "@UTF" */
if (!check_extensions(sf, "aax,"))
goto fail;
/* .aax contains a simple UTF table with one row and various columns being header info */
@ -159,7 +161,7 @@ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
uint32_t table_offset = 0x00;
utf = utf_open(streamFile, table_offset, &rows, &name);
utf = utf_open(sf, table_offset, &rows, &name);
if (!utf) goto fail;
if (strcmp(name, "ADPCM_WII") != 0)
@ -172,7 +174,7 @@ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
goto fail;
if (!utf_query_u32(utf, 0, "nsmpl", &num_samples))
goto fail;
if (!utf_query_u8(utf, 0, "nch", &channel_count))
if (!utf_query_u8(utf, 0, "nch", &channels))
goto fail;
if (!utf_query_u8(utf, 0, "lpflg", &loop_flag)) /* full loops */
goto fail;
@ -182,21 +184,21 @@ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
if (!utf_query_data(utf, 0, "header", &header_offset, &header_size))
goto fail;
if (channel_count < 1 || channel_count > 2)
if (channels < 1 || channels > 2)
goto fail;
if (header_size != channel_count * 0x60)
if (header_size != channels * 0x60)
goto fail;
start_offset = data_offset;
interleave = (data_size+7) / 8 * 8 / channel_count;
interleave = (data_size+7) / 8 * 8 / channels;
loop_start = read_32bitBE(header_offset + 0x10, streamFile);
loop_end = read_32bitBE(header_offset + 0x14, streamFile);
loop_start = read_32bitBE(header_offset + 0x10, sf);
loop_end = read_32bitBE(header_offset + 0x14, sf);
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
@ -209,9 +211,9 @@ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = interleave;
vgmstream->meta_type = meta_UTF_DSP;
dsp_read_coefs_be(vgmstream, streamFile, header_offset+0x1c, 0x60);
dsp_read_coefs_be(vgmstream, sf, header_offset+0x1c, 0x60);
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -1,6 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "cri_utf.h"
#include "../util/cri_utf.h"
/* ACB (Atom Cue sheet Binary) - CRI container of memory audio, often together with a .awb wave bank */

View File

@ -0,0 +1,152 @@
#include "meta.h"
#include "../coding/coding.h"
typedef struct {
int total_subsongs;
int target_subsong;
uint32_t stream_offset;
uint32_t stream_size;
int loop_flag;
int sample_rate;
int channels;
int32_t num_samples;
} adm3_header_t;
static int parse_adm3(adm3_header_t* adm3, STREAMFILE* sf);
/* ADM3 - Crankcase Audio REV plugin file [Cyberpunk 2077 (PC), MotoGP 21 (PC)] */
VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
adm3_header_t adm3 = {0};
/* checks */
if (!is_id32be(0x00,sf, "ADM3"))
goto fail;
if (!check_extensions(sf, "wem"))
goto fail;
adm3.target_subsong = sf->stream_index;
if (adm3.target_subsong == 0) adm3.target_subsong = 1;
/* ADM3 are files used with the Wwise Crankaudio plugin, that simulate engine noises with
* base internal samples and some internal RPM config (probably). Actual file seems to
* define some combo of samples, this only plays those separate samples.
* Decoder is basically Apple's IMA (internally just "ADPCMDecoder") but transforms to float
* each sample during decode by multiplying by 0.000030518509 */
if (!parse_adm3(&adm3, sf))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(adm3.channels, adm3.loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_ADM3;
vgmstream->sample_rate = adm3.sample_rate;
vgmstream->num_samples = adm3.num_samples; /* slightly lower than bytes-to-samples */
vgmstream->num_streams = adm3.total_subsongs;
vgmstream->stream_size = adm3.stream_size;
vgmstream->coding_type = coding_APPLE_IMA4;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x22;
if (!vgmstream_open_stream(vgmstream, sf, adm3.stream_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
static int parse_type(adm3_header_t* adm3, STREAMFILE* sf, uint32_t offset) {
if (is_id32be(offset, sf, "RMP1")) {
offset = read_u32le(offset + 0x1c, sf);
if (!parse_type(adm3, sf, offset))
goto fail;
/* 0x24: offset to GRN1 */
}
else if (is_id32be(offset, sf, "SMB1")) {
uint32_t table_count = read_u32le(offset + 0x10, sf);
uint32_t table_offset = read_u32le(offset + 0x18, sf);
int i;
for (i = 0; i < table_count; i++) {
uint32_t smp2_unk = read_u32le(table_offset + i * 0x08 + 0x00, sf);
uint32_t smp2_offset = read_u32le(table_offset + i * 0x08 + 0x04, sf);
if (smp2_unk != 1)
goto fail;
if (!parse_type(adm3, sf, smp2_offset)) /* SMP2 */
goto fail;
}
}
else if (is_id32be(offset, sf, "SMP2")) {
adm3->total_subsongs++;
if (adm3->target_subsong == adm3->total_subsongs) {
/* 0x04 always 0 */
/* 0x08 always 0x00040000 */
adm3->channels = read_u32le(offset + 0x0c, sf);
/* 0x10 float pitch? */
/* 0x14 int pitch? */
/* 0x18 0x0001? */
/* 0x1a 0x0030? (header size?) */
adm3->sample_rate = read_s32le(offset + 0x1c, sf);
adm3->num_samples = read_s32le(offset + 0x20, sf);
adm3->stream_size = read_u32le(offset + 0x24, sf);
/* 0x28 1? */
adm3->stream_offset = read_u32le(offset + 0x2c, sf);
}
}
else {
VGM_LOG("ADM3: unknown at %x\n", offset);
goto fail;
}
return 1;
fail:
return 0;
}
static int parse_adm3(adm3_header_t* adm3, STREAMFILE* sf) {
uint32_t offset;
/* 0x04: null */
/* 0x08: version? */
/* 0x0c: header size */
/* 0x10: data start */
/* rest unknown, looks mostly the same between files */
/* higher ramp, N samples from low to high */
offset = read_u32le(0x0FC, sf);
if (!parse_type(adm3, sf, offset)) goto fail; /* RMP1 */
if (read_u32le(0x100, sf) != 1) goto fail;
/* lower ramp, also N samples */
offset = read_u32le(0x104, sf);
if (!parse_type(adm3, sf, offset)) goto fail; /* RMP1 */
if (read_u32le(0x108, sf) != 1) goto fail;
/* idle engine */
offset = read_u32le(0x10c, sf);
if (!parse_type(adm3, sf, offset)) goto fail; /* SMP2 */
if (read_u32le(0x110, sf) != 1) goto fail;
if (adm3->target_subsong < 0 || adm3->target_subsong > adm3->total_subsongs || adm3->total_subsongs < 1)
goto fail;
return 1;
fail:
return 0;
}

View File

@ -1,6 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "cri_utf.h"
#include "../util/cri_utf.h"
typedef enum { HCA, CWAV, ADX } cpk_type_t;
@ -26,10 +26,11 @@ VGMSTREAM* init_vgmstream_cpk_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
/* checks */
if (!check_extensions(sf, "awb"))
goto fail;
if (!is_id32be(0x00,sf, "CPK "))
goto fail;
if (!check_extensions(sf, "awb"))
goto fail;
if (!is_id32be(0x10,sf, "@UTF"))
goto fail;
/* 04: 0xFF? */

View File

@ -1,6 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "cri_utf.h"
#include "../util/cri_utf.h"
/* CSB (Cue Sheet Binary?) - CRI container of memory audio, often together with a .cpk wave bank */
@ -9,8 +9,8 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) {
STREAMFILE* temp_sf = NULL;
off_t subfile_offset;
size_t subfile_size;
utf_context *utf = NULL;
utf_context *utf_sdl = NULL;
utf_context* utf = NULL;
utf_context* utf_sdl = NULL;
int total_subsongs, target_subsong = sf->stream_index;
uint8_t fmt = 0;
const char* stream_name = NULL;

View File

@ -0,0 +1,46 @@
#include "meta.h"
#include "../coding/coding.h"
/* .ESF - from Mortal Kombat 4 (PC) */
VGMSTREAM* init_vgmstream_esf(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t pcm_size;
off_t start_offset;
int loop_flag, bps_flag, hq_flag, channels, bps;
/* checks */
if (!is_id32be(0x00, sf, "ESF\x06"))
goto fail;
if (!check_extensions(sf, "esf"))
goto fail;
pcm_size = read_u32le(0x04, sf);
bps_flag = pcm_size & 0x20000000;
hq_flag = pcm_size & 0x40000000;
loop_flag = pcm_size & 0x80000000;
pcm_size &= 0x1FFFFFFF;
channels = 1; /* mono only */
start_offset = 0x08;
bps = bps_flag ? 16 : 8; /* 16 is supposed to mean PCM16 but is actually IMA */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_ESF;
vgmstream->sample_rate = hq_flag ? 22050 : 11025;
vgmstream->coding_type = (bps == 8) ? coding_PCM8_U : coding_DVI_IMA;
vgmstream->num_samples = pcm_bytes_to_samples(pcm_size, 1, bps);
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;
}

View File

@ -982,4 +982,10 @@ VGMSTREAM* init_vgmstream_sspf(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_s3v(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_esf(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_tt_ad(STREAMFILE* sf);
#endif /*_META_H*/

View File

@ -2,16 +2,33 @@
#include "../coding/coding.h"
/* MPEG - standard MP1/2/3 audio MP3 */
/* MPEG - standard MP1/2/3 audio */
VGMSTREAM* init_vgmstream_mpeg(STREAMFILE* sf) {
#ifdef VGM_USE_MPEG
VGMSTREAM* vgmstream = NULL;
uint32_t start_offset;
int loop_flag = 0;
mpeg_frame_info info = {0};
uint32_t header_id;
/* checks */
if (!mpeg_get_frame_info(sf, 0x00, &info))
header_id = read_u32be(0x00, sf);
if ((header_id & 0xFFF00000) != 0xFFF00000 &&
(header_id & 0xFFFFFF00) != get_id32be("ID3\0") &&
(header_id & 0xFFFFFF00) != get_id32be("TAG\0"))
goto fail;
//TODO: may try init_mpeg as-is, already skips tags
start_offset = 0x00;
while (start_offset < get_streamfile_size(sf)) {
uint32_t tag_size = mpeg_get_tag_size(sf, start_offset, 0);
if (tag_size == 0)
break;
start_offset += tag_size;
}
if (!mpeg_get_frame_info(sf, start_offset, &info))
goto fail;
/* .mp3/mp2: standard (is .mp1 ever used in games?)

View File

@ -1,15 +1,17 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* P3D - from Radical's Prototype 1/2 (PC/PS3/X360), Spider-Man 4 Beta (X360) */
VGMSTREAM* init_vgmstream_p3d(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, offset, name_offset = 0;
uint32_t start_offset, offset, name_offset = 0;
size_t header_size, file_size, data_size;
uint32_t xma2_offset = 0, xma2_size = 0;
int loop_flag, channels, sample_rate, codec;
int i, name_count, text_len, block_size = 0, num_samples;
uint32_t (*read_u32)(off_t,STREAMFILE*) = NULL;
int i, name_count, unk_count, text_len, block_size = 0, num_samples;
read_u32_t read_u32;
/* checks */
@ -19,30 +21,36 @@ VGMSTREAM* init_vgmstream_p3d(STREAMFILE* sf) {
if (!check_extensions(sf,"p3d"))
goto fail;
read_u32 = guess_endianness32bit(0x04,sf) ? read_u32be : read_u32le;
read_u32 = guess_endian32(0x04,sf) ? read_u32be : read_u32le;
file_size = get_streamfile_size(sf);
/* base header */
header_size = read_u32(0x04,sf);
if (header_size != 0x0C) goto fail;
if (header_size != 0x0c) goto fail;
if (read_u32(0x08,sf) != file_size) goto fail;
if (read_u32(0x0C,sf) != 0xFE000000) goto fail; /* fixed */
if (read_u32(0x10,sf) + header_size != file_size) goto fail;
if (read_u32(0x14,sf) + header_size != file_size) goto fail; /* body size again */
if (read_u32(0x18,sf) != 0x0000000A) goto fail; /* fixed */
offset = 0x0c;
/* header text */
offset = 0x1C;
text_len = read_u32(offset,sf);
/* P3D is just a generic container used in Radical's games, so we only want "AudioFile".
* Rarely some voice files start with a "AudioDialogueSubtitle" section, so skip that first */
if (is_id64be(offset+0x14,sf, "AudioDia")) {
offset += read_u32(offset + 0x04,sf); /* section size */
}
/* AudioFile section */
if (read_u32(offset + 0x00,sf) != 0xFE000000) goto fail; /* section marker */
if (read_u32(offset + 0x04,sf) + offset != file_size) goto fail; /* AudioFile size */
if (read_u32(offset + 0x08,sf) + offset != file_size) goto fail; /* again */
if (read_u32(offset + 0x0c,sf) != 0x0000000A) goto fail; /* fixed */
text_len = read_u32(offset + 0x10,sf);
if (text_len != 9) goto fail;
offset += 0x04;
offset += 0x14;
/* check the type as P3D is just a generic container used in Radical's games */
if (!is_id64be(offset+0x00,sf, "AudioFil") || read_u16be(offset+0x08,sf) != 0x6500) /* "AudioFile\0" */
goto fail;
offset += text_len + 0x01;
/* file names: always 2 (repeated); but if it's 3 there is an extra string later */
/* file names: 1 internal stream name + 1 external filename (usually repeated) + 1 an extra string later (P2) */
name_count = read_u32(offset,sf);
if (name_count != 2 && name_count != 3) goto fail; /* 2: Prototype1, 3: Prototype2 */
offset += 0x04;
@ -55,8 +63,9 @@ VGMSTREAM* init_vgmstream_p3d(STREAMFILE* sf) {
offset += 0x04 + text_len;
}
/* info count? */
if (0x01 != read_u32(offset,sf)) goto fail;
/* 1=music, 0=dialogues */
unk_count = read_u32(offset,sf);
if (unk_count != 0x00 && unk_count != 0x01) goto fail;
offset += 0x04;
/* next string can be used as a codec id */
@ -64,8 +73,8 @@ VGMSTREAM* init_vgmstream_p3d(STREAMFILE* sf) {
codec = read_u32be(offset+0x04,sf);
offset += 0x04 + text_len + 0x01;
/* extra "Music" string in Prototype 2 */
if (name_count == 3) {
/* extra "Music" or "Dialogue" string in Prototype 2 */
if (name_count >= 3) {
text_len = read_u32(offset,sf) + 1; /* null-terminated */
offset += 0x04 + text_len;
}

View File

@ -654,8 +654,8 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
read_u32be(start_offset+0x3c, sf) == 0xFFFFFFFF)
goto fail;
///* MSADPCM .ckd are parsed elsewhere, though they are valid so no big deal if parsed here (just that loops should be ignored) */
if (!fmt.is_at9 && check_extensions(sf, "ckd"))
/* MSADPCM .ckd are parsed elsewhere, though they are valid so no big deal if parsed here (just that loops should be ignored) */
if (fmt.codec == 0x0002 && check_extensions(sf, "ckd"))
goto fail;
/* ignore Gitaroo Man Live! (PSP) multi-RIFF (to allow chunked TXTH) */

View File

@ -21,7 +21,7 @@ VGMSTREAM* init_vgmstream_sspf(STREAMFILE* sf) {
goto fail;
/* extra check to ignore .spc, that are a RAM pack of .ssp with a ~0x800 table at the end */
file_size = read_u32be(0x08, sf) + 0x08; /* without padding */
file_size = read_u32be(0x08, sf); /* without padding */
pad_size = 0;
if (file_size % 0x800) /* add padding */
pad_size = 0x800 - (file_size % 0x800);

View File

@ -2,24 +2,36 @@
#include "../coding/coding.h"
/* Tiger Game.com ADPCM file */
VGMSTREAM * init_vgmstream_tgc(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_tgc(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint16_t size;
off_t start_offset;
/* checks */
if (!check_extensions(streamFile, "4"))
if (read_u8(0x00, sf) != 0)
goto fail;
if (!check_extensions(sf, "4"))
goto fail;
size = read_u16be(0x01, sf);
if (size != get_streamfile_size(sf))
goto fail;
start_offset = 0x03;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(1, 0);
if (!vgmstream) goto fail;
vgmstream->sample_rate = 8000;
vgmstream->num_samples = ((uint16_t)read_16bitBE(1, streamFile) - 3) * 2;
vgmstream->num_samples = (size - 0x03) * 2;
vgmstream->meta_type = meta_TGC;
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_TGC;
if (!vgmstream_open_stream(vgmstream, streamFile, 3))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -0,0 +1,94 @@
#include "meta.h"
#include "../coding/coding.h"
/* .AUDIO_DATA - Traveller's Tales "NTT" engine audio format [Lego Star Wars: The Skywalker Saga (PC/Switch)] */
VGMSTREAM* init_vgmstream_tt_ad(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
uint32_t offset, stream_offset, stream_size;
int loop_flag, channels, sample_rate, codec, frame_size = 0;
int32_t num_samples;
/* checks */
if (!is_id32be(0x00,sf, "FMT "))
goto fail;
/* actual extension */
if (!check_extensions(sf, "audio_data"))
goto fail;
offset = 0x08;
/* 0x00: null */
codec = read_u16le(offset + 0x02,sf);
sample_rate = read_s32le(offset + 0x04,sf);
num_samples = read_s32le(offset + 0x08,sf);
channels = read_u8(offset + 0x0c,sf);
/* 0x0d: bps (16=IMA, 32=Ogg) */
/* 0x10:
Ogg = some size?
IMA = frame size + flag? */
if (codec == 0x0a)
frame_size = read_u16le(offset + 0x10,sf);
loop_flag = 0; /* music just repeats? */
offset += read_u32le(0x04, sf);
/* Ogg seek table*/
if (is_id32be(offset, sf, "SEEK")) {
offset += 0x08 + read_u32le(offset + 0x04, sf);
}
/* found with some IMA */
if (is_id32be(offset, sf, "RMS ")) {
offset += 0x08 + read_u32le(offset + 0x04, sf);
}
if (!is_id32be(offset, sf, "DATA"))
goto fail;
stream_offset = offset + 0x08;
stream_size = read_u32le(offset + 0x04, sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_TT_AD;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
switch(codec) {
#ifdef VGM_USE_VORBIS
case 0x01: {
vgmstream->codec_data = init_ogg_vorbis(sf, stream_offset, stream_size, NULL);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_OGG_VORBIS;
vgmstream->layout_type = layout_none;
break;
}
#endif
case 0x0a:
vgmstream->coding_type = coding_MS_IMA_mono;
vgmstream->layout_type = layout_blocked_tt_ad;
vgmstream->frame_size = frame_size;
vgmstream->interleave_block_size = frame_size;
break;
default:
vgm_logi("FMT: unsupported codec 0x%x\n", codec);
goto fail;
}
if (!vgmstream_open_stream(vgmstream, sf, stream_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -46,6 +46,7 @@ typedef enum {
XA,
XA_EA,
CP_YM,
PCM_FLOAT_LE,
UNKNOWN = 99,
} txth_codec_t;
@ -213,13 +214,14 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
if (txth.interleave == 0) {
uint32_t interleave = 0;
switch(txth.codec) {
case PSX: interleave = 0x10; break;
case PSX_bf: interleave = 0x10; break;
case NGC_DSP: interleave = 0x08; break;
case PCM16LE: interleave = 0x02; break;
case PCM16BE: interleave = 0x02; break;
case PCM8: interleave = 0x01; break;
case PCM8_U: interleave = 0x01; break;
case PSX: interleave = 0x10; break;
case PSX_bf: interleave = 0x10; break;
case NGC_DSP: interleave = 0x08; break;
case PCM16LE: interleave = 0x02; break;
case PCM16BE: interleave = 0x02; break;
case PCM8: interleave = 0x01; break;
case PCM8_U: interleave = 0x01; break;
case PCM_FLOAT_LE: interleave = 0x04; break;
default:
break;
}
@ -229,26 +231,27 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
/* type to coding conversion */
switch (txth.codec) {
case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX_IMA; break;
case NGC_DTK: coding = coding_NGC_DTK; break;
case PCM16BE: coding = coding_PCM16BE; break;
case PCM16LE: coding = coding_PCM16LE; break;
case PCM8: coding = coding_PCM8; break;
case SDX2: coding = coding_SDX2; break;
case DVI_IMA: coding = coding_DVI_IMA; break;
case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX_IMA; break;
case NGC_DTK: coding = coding_NGC_DTK; break;
case PCM16BE: coding = coding_PCM16BE; break;
case PCM16LE: coding = coding_PCM16LE; break;
case PCM8: coding = coding_PCM8; break;
case PCM_FLOAT_LE: coding = coding_PCMFLOAT; break;
case SDX2: coding = coding_SDX2; break;
case DVI_IMA: coding = coding_DVI_IMA; break;
#ifdef VGM_USE_MPEG
case MPEG: coding = coding_MPEG_layer3; break; /* we later find out exactly which */
case MPEG: coding = coding_MPEG_layer3; break; /* we later find out exactly which */
#endif
case IMA: coding = coding_IMA; break;
case AICA: coding = coding_AICA; break;
case MSADPCM: coding = coding_MSADPCM; break;
case NGC_DSP: coding = coding_NGC_DSP; break;
case PCM8_U_int: coding = coding_PCM8_U_int; break;
case PSX_bf: coding = coding_PSX_badflags; break;
case MS_IMA: coding = coding_MS_IMA; break;
case PCM8_U: coding = coding_PCM8_U; break;
case APPLE_IMA4: coding = coding_APPLE_IMA4; break;
case IMA: coding = coding_IMA; break;
case AICA: coding = coding_AICA; break;
case MSADPCM: coding = coding_MSADPCM; break;
case NGC_DSP: coding = coding_NGC_DSP; break;
case PCM8_U_int: coding = coding_PCM8_U_int; break;
case PSX_bf: coding = coding_PSX_badflags; break;
case MS_IMA: coding = coding_MS_IMA; break;
case PCM8_U: coding = coding_PCM8_U; break;
case APPLE_IMA4: coding = coding_APPLE_IMA4; break;
#ifdef VGM_USE_FFMPEG
case ATRAC3:
case ATRAC3PLUS:
@ -256,19 +259,19 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
case XMA2:
case AC3:
case AAC:
case FFMPEG: coding = coding_FFmpeg; break;
case FFMPEG: coding = coding_FFmpeg; break;
#endif
case PCFX: coding = coding_PCFX; break;
case PCM4: coding = coding_PCM4; break;
case PCM4_U: coding = coding_PCM4_U; break;
case OKI16: coding = coding_OKI16; break;
case OKI4S: coding = coding_OKI4S; break;
case TGC: coding = coding_TGC; break;
case ASF: coding = coding_ASF; break;
case EAXA: coding = coding_EA_XA; break;
case XA: coding = coding_XA; break;
case XA_EA: coding = coding_XA_EA; break;
case CP_YM: coding = coding_CP_YM; break;
case PCFX: coding = coding_PCFX; break;
case PCM4: coding = coding_PCM4; break;
case PCM4_U: coding = coding_PCM4_U; break;
case OKI16: coding = coding_OKI16; break;
case OKI4S: coding = coding_OKI4S; break;
case TGC: coding = coding_TGC; break;
case ASF: coding = coding_ASF; break;
case EAXA: coding = coding_EA_XA; break;
case XA: coding = coding_XA; break;
case XA_EA: coding = coding_XA_EA; break;
case CP_YM: coding = coding_CP_YM; break;
default:
goto fail;
}
@ -305,6 +308,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
case coding_PCM16BE:
case coding_PCM8:
case coding_PCM8_U:
case coding_PCMFLOAT:
case coding_PCM4:
case coding_PCM4_U:
case coding_SDX2:
@ -963,6 +967,7 @@ static txth_codec_t parse_codec(txth_header* txth, const char* val) {
else if (is_string(val,"XA")) return XA;
else if (is_string(val,"XA_EA")) return XA_EA;
else if (is_string(val,"CP_YM")) return CP_YM;
else if (is_string(val,"PCM_FLOAT_LE")) return PCM_FLOAT_LE;
/* special handling */
else if (is_string(val,"name_value")) return txth->name_values[0];
else if (is_string(val,"name_value1")) return txth->name_values[0];
@ -2039,6 +2044,8 @@ static int get_bytes_to_samples(txth_header* txth, uint32_t bytes) {
case PCM8_U_int:
case PCM8_U:
return pcm_bytes_to_samples(bytes, txth->channels, 8);
case PCM_FLOAT_LE:
return pcm_bytes_to_samples(bytes, txth->channels, 32);
case PCM4:
case PCM4_U:
case TGC:

View File

@ -705,18 +705,13 @@ static VGMSTREAM* init_vgmstream_ubi_hx_header(ubi_hx_header* hx, STREAMFILE* sf
break;
case UBI:
vgmstream->codec_data = init_ubi_adpcm(sb, hx->stream_offset, vgmstream->channels);
vgmstream->codec_data = init_ubi_adpcm(sb, hx->stream_offset, hx->stream_size, vgmstream->channels);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_UBI_ADPCM;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ubi_adpcm_get_samples(vgmstream->codec_data);
/* some kind of internal bug I guess, seen in a few subsongs in Rayman 3 PC demo, other values are also buggy */
if (vgmstream->num_samples == 0x77E7A374) {
vgmstream->num_samples = ubi_adpcm_bytes_to_samples(vgmstream->codec_data, hx->stream_size);
}
/* XIII has 6-bit stereo music, Rayman 3 4-bit music, both use 6-bit mono) */
break;

View File

@ -1018,7 +1018,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
sb->stream_size -= 0x08;
}
vgmstream->codec_data = init_ubi_adpcm(sf_data, start_offset, vgmstream->channels);
vgmstream->codec_data = init_ubi_adpcm(sf_data, start_offset, 0, vgmstream->channels);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_UBI_ADPCM;
vgmstream->layout_type = layout_none;

View File

@ -304,6 +304,7 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) {
case layout_blocked_vs_square:
case layout_blocked_vid1:
case layout_blocked_ubi_sce:
case layout_blocked_tt_ad:
render_vgmstream_blocked(buf, sample_count, vgmstream);
break;
case layout_segmented:

View File

@ -1,5 +1,5 @@
#include "cri_utf.h"
#include "../util/log.h"
#include "log.h"
#define UTF_MAX_SCHEMA_SIZE 0x8000 /* arbitrary max */
#define COLUMN_BITMASK_FLAG 0xf0

View File

@ -470,7 +470,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_csb,
init_vgmstream_fwse,
init_vgmstream_fda,
init_vgmstream_tgc,
init_vgmstream_kwb,
init_vgmstream_lrmd,
init_vgmstream_bkhd,
@ -522,6 +521,9 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_sspf,
init_vgmstream_opus_rsnd,
init_vgmstream_s3v,
init_vgmstream_esf,
init_vgmstream_adm3,
init_vgmstream_tt_ad,
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
init_vgmstream_mpeg,
@ -535,6 +537,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_seb,
init_vgmstream_ps2_pnb,
init_vgmstream_sli_ogg,
init_vgmstream_tgc,
/* 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 */
@ -1159,9 +1162,10 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o
goto fail;
}
if ((vgmstream->coding_type == coding_MSADPCM ||
vgmstream->coding_type == coding_MSADPCM_ck ||
vgmstream->coding_type == coding_MSADPCM_int) &&
if ((vgmstream->coding_type == coding_MSADPCM || vgmstream->coding_type == coding_MSADPCM_ck ||
vgmstream->coding_type == coding_MSADPCM_int ||
vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono
) &&
vgmstream->frame_size == 0) {
vgmstream->frame_size = vgmstream->interleave_block_size;
}

View File

@ -123,6 +123,7 @@ typedef enum {
coding_BLITZ_IMA, /* Blitz Games 4-bit IMA ADPCM */
coding_MS_IMA, /* Microsoft IMA ADPCM */
coding_MS_IMA_mono, /* Microsoft IMA ADPCM (mono/interleave) */
coding_XBOX_IMA, /* XBOX IMA ADPCM */
coding_XBOX_IMA_mch, /* XBOX IMA ADPCM (multichannel) */
coding_XBOX_IMA_int, /* XBOX IMA ADPCM (mono/interleave) */
@ -286,6 +287,7 @@ typedef enum {
layout_blocked_vs_square,
layout_blocked_vid1,
layout_blocked_ubi_sce,
layout_blocked_tt_ad,
/* otherwise odd */
layout_segmented, /* song divided in segments (song sections) */
@ -765,6 +767,9 @@ typedef enum {
meta_MPEG,
meta_SSPF,
meta_S3V,
meta_ESF,
meta_ADM3,
meta_TT_AD,
} meta_t;