Updated VGMStream to r1050-1043-g16b4cf22.

CQTexperiment
Christopher Snowhill 2018-02-18 20:38:16 -08:00
parent 6cd51431bd
commit e1c33b5477
55 changed files with 1245 additions and 958 deletions

View File

@ -129,7 +129,6 @@
836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */; };
836F6F5318BDC2190095E648 /* ps2_iab_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */; };
836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */; };
836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */; };
836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1918BDC2180095E648 /* scd_int_layout.c */; };
836F6F5718BDC2190095E648 /* str_snds_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1A18BDC2180095E648 /* str_snds_blocked.c */; };
836F6F5818BDC2190095E648 /* thp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1B18BDC2180095E648 /* thp_blocked.c */; };
@ -234,7 +233,6 @@
836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9018BDC2180095E648 /* ps2_adsc.c */; };
836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9118BDC2180095E648 /* ps2_ass.c */; };
836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9218BDC2180095E648 /* ps2_ast.c */; };
836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9318BDC2180095E648 /* ps2_aus.c */; };
836F6FD018BDC2190095E648 /* ps2_b1s.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9418BDC2180095E648 /* ps2_b1s.c */; };
836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9518BDC2180095E648 /* ps2_bg00.c */; };
836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9618BDC2180095E648 /* ps2_bmdx.c */; };
@ -304,7 +302,6 @@
836F701918BDC2190095E648 /* psx_cdxa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDD18BDC2190095E648 /* psx_cdxa.c */; };
836F701A18BDC2190095E648 /* psx_fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDE18BDC2190095E648 /* psx_fag.c */; };
836F701B18BDC2190095E648 /* psx_gms.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDF18BDC2190095E648 /* psx_gms.c */; };
836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE018BDC2190095E648 /* psx_str_mgav.c */; };
836F701D18BDC2190095E648 /* raw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE118BDC2190095E648 /* raw.c */; };
836F701E18BDC2190095E648 /* redspark.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE218BDC2190095E648 /* redspark.c */; };
836F701F18BDC2190095E648 /* riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE318BDC2190095E648 /* riff.c */; };
@ -439,6 +436,9 @@
83E56BA51F2EE3520026BC60 /* vorbis_custom_utils_ogl.c in Sources */ = {isa = PBXBuildFile; fileRef = 83E56BA01F2EE3500026BC60 /* vorbis_custom_utils_ogl.c */; };
83EDE5D81A70951A005F5D84 /* mca.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EDE5D61A70951A005F5D84 /* mca.c */; };
83EDE5D91A70951A005F5D84 /* btsnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EDE5D71A70951A005F5D84 /* btsnd.c */; };
83EED5D3203A8BC7008BEB45 /* ea_swvr.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D1203A8BC7008BEB45 /* ea_swvr.c */; };
83EED5D4203A8BC7008BEB45 /* aus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D2203A8BC7008BEB45 /* aus.c */; };
83EED5D6203A8BD7008BEB45 /* blocked_ea_swvr.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */; };
83F4129C1E93313C002E37D0 /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83F4128F1E932F9A002E37D0 /* Vorbis.framework */; };
83F5F8831908D0A400C8E65F /* fsb5.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F5F8821908D0A400C8E65F /* fsb5.c */; };
83FF0EBC1E93282100C58054 /* wwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FF0EBB1E93282100C58054 /* wwise.c */; };
@ -691,7 +691,6 @@
836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adm_blocked.c; sourceTree = "<group>"; };
836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_iab_blocked.c; sourceTree = "<group>"; };
836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_strlr_blocked.c; sourceTree = "<group>"; };
836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_mgav_blocked.c; sourceTree = "<group>"; };
836F6E1918BDC2180095E648 /* scd_int_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_int_layout.c; sourceTree = "<group>"; };
836F6E1A18BDC2180095E648 /* str_snds_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds_blocked.c; sourceTree = "<group>"; };
836F6E1B18BDC2180095E648 /* thp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp_blocked.c; sourceTree = "<group>"; };
@ -796,7 +795,6 @@
836F6E9018BDC2180095E648 /* ps2_adsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adsc.c; sourceTree = "<group>"; };
836F6E9118BDC2180095E648 /* ps2_ass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ass.c; sourceTree = "<group>"; };
836F6E9218BDC2180095E648 /* ps2_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ast.c; sourceTree = "<group>"; };
836F6E9318BDC2180095E648 /* ps2_aus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_aus.c; sourceTree = "<group>"; };
836F6E9418BDC2180095E648 /* ps2_b1s.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_b1s.c; sourceTree = "<group>"; };
836F6E9518BDC2180095E648 /* ps2_bg00.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bg00.c; sourceTree = "<group>"; };
836F6E9618BDC2180095E648 /* ps2_bmdx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bmdx.c; sourceTree = "<group>"; };
@ -866,7 +864,6 @@
836F6EDD18BDC2190095E648 /* psx_cdxa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_cdxa.c; sourceTree = "<group>"; };
836F6EDE18BDC2190095E648 /* psx_fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_fag.c; sourceTree = "<group>"; };
836F6EDF18BDC2190095E648 /* psx_gms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_gms.c; sourceTree = "<group>"; };
836F6EE018BDC2190095E648 /* psx_str_mgav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_str_mgav.c; sourceTree = "<group>"; };
836F6EE118BDC2190095E648 /* raw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw.c; sourceTree = "<group>"; };
836F6EE218BDC2190095E648 /* redspark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = redspark.c; sourceTree = "<group>"; };
836F6EE318BDC2190095E648 /* riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = riff.c; sourceTree = "<group>"; };
@ -997,6 +994,9 @@
83E56BA01F2EE3500026BC60 /* vorbis_custom_utils_ogl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_ogl.c; sourceTree = "<group>"; };
83EDE5D61A70951A005F5D84 /* mca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mca.c; sourceTree = "<group>"; };
83EDE5D71A70951A005F5D84 /* btsnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = btsnd.c; sourceTree = "<group>"; };
83EED5D1203A8BC7008BEB45 /* ea_swvr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_swvr.c; sourceTree = "<group>"; };
83EED5D2203A8BC7008BEB45 /* aus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aus.c; sourceTree = "<group>"; };
83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_swvr.c; sourceTree = "<group>"; };
83F412871E932F9A002E37D0 /* Vorbis.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Vorbis.xcodeproj; path = ../Vorbis/macosx/Vorbis.xcodeproj; sourceTree = "<group>"; };
83F5F8821908D0A400C8E65F /* fsb5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fsb5.c; sourceTree = "<group>"; };
83FF0EBB1E93282100C58054 /* wwise.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wwise.c; sourceTree = "<group>"; };
@ -1224,6 +1224,7 @@
8349A8E31FE6253800E26435 /* blocked_ea_1snh.c */,
8349A8E41FE6253800E26435 /* blocked_ea_schl.c */,
8349A8E71FE6253900E26435 /* blocked_ea_sns.c */,
83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */,
8349A8E51FE6253800E26435 /* blocked_ivaud.c */,
8349A8E61FE6253900E26435 /* blocked_vawx.c */,
83AA5D1A1F6E2F7F0020821C /* blocked_vgs.c */,
@ -1244,7 +1245,6 @@
836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */,
836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */,
836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */,
836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */,
831BD1201EEE1D2A00198540 /* rws_blocked.c */,
836F6E1918BDC2180095E648 /* scd_int_layout.c */,
836F6E1A18BDC2180095E648 /* str_snds_blocked.c */,
@ -1280,6 +1280,7 @@
836F6E3518BDC2180095E648 /* ast.c */,
83A21F80201D8980000F04B9 /* atsl3.c */,
83A21F7C201D897F000F04B9 /* atx.c */,
83EED5D2203A8BC7008BEB45 /* aus.c */,
83AA5D201F6E2F9B0020821C /* awc.c */,
836F6E3618BDC2180095E648 /* baf.c */,
8349A8F81FE6257E00E26435 /* bar_streamfile.h */,
@ -1308,6 +1309,7 @@
8349A8F71FE6257E00E26435 /* ea_eaac.c */,
830165981F256BD000CA0941 /* ea_schl_fixed.c */,
836F6E4618BDC2180095E648 /* ea_schl.c */,
83EED5D1203A8BC7008BEB45 /* ea_swvr.c */,
836F6E4818BDC2180095E648 /* emff.c */,
836F6E4918BDC2180095E648 /* exakt_sc.c */,
836F6E4A18BDC2180095E648 /* excitebots.c */,
@ -1406,7 +1408,6 @@
836F6E9018BDC2180095E648 /* ps2_adsc.c */,
836F6E9118BDC2180095E648 /* ps2_ass.c */,
836F6E9218BDC2180095E648 /* ps2_ast.c */,
836F6E9318BDC2180095E648 /* ps2_aus.c */,
836F6E9418BDC2180095E648 /* ps2_b1s.c */,
836F6E9518BDC2180095E648 /* ps2_bg00.c */,
836F6E9618BDC2180095E648 /* ps2_bmdx.c */,
@ -1481,7 +1482,6 @@
836F6EDD18BDC2190095E648 /* psx_cdxa.c */,
836F6EDE18BDC2190095E648 /* psx_fag.c */,
836F6EDF18BDC2190095E648 /* psx_gms.c */,
836F6EE018BDC2190095E648 /* psx_str_mgav.c */,
836F6EE118BDC2190095E648 /* raw.c */,
836F6EE218BDC2190095E648 /* redspark.c */,
836F6EE318BDC2190095E648 /* riff.c */,
@ -1802,6 +1802,7 @@
8349A8DF1FE6251F00E26435 /* vorbis_custom_utils_vid1.c in Sources */,
83A21F8D201D8982000F04B9 /* sqex_sead.c in Sources */,
839B54571EEE1DA000048A2D /* rws_blocked.c in Sources */,
83EED5D3203A8BC7008BEB45 /* ea_swvr.c in Sources */,
839B54521EEE1D9600048A2D /* ngc_ulw.c in Sources */,
836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */,
836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */,
@ -1915,7 +1916,9 @@
836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */,
8349A8ED1FE6253900E26435 /* blocked_ea_sns.c in Sources */,
836F6F6F18BDC2190095E648 /* akb.c in Sources */,
83EED5D6203A8BD7008BEB45 /* blocked_ea_swvr.c in Sources */,
8349A9181FE6258200E26435 /* ea_1snh.c in Sources */,
83EED5D4203A8BC7008BEB45 /* aus.c in Sources */,
836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */,
83709E071ECBC1A4005C03D3 /* mss.c in Sources */,
836F6F8F18BDC2190095E648 /* his.c in Sources */,
@ -1969,9 +1972,7 @@
836F705218BDC2190095E648 /* zwdsp.c in Sources */,
836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */,
836F6FFF18BDC2190095E648 /* ps2_strlr.c in Sources */,
836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */,
836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */,
836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */,
8349A8EC1FE6253900E26435 /* blocked_vawx.c in Sources */,
836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */,
836F700418BDC2190095E648 /* ps2_vas.c in Sources */,
@ -2123,7 +2124,6 @@
836F6FEA18BDC2190095E648 /* ps2_msa.c in Sources */,
836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */,
836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */,
836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */,
83345A4F1F8AEB2800B2EAA4 /* nub_xma.c in Sources */,
836F6F7618BDC2190095E648 /* brstm.c in Sources */,
836F700718BDC2190095E648 /* ps2_vgv.c in Sources */,

View File

@ -32,8 +32,9 @@ void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
size_t ima_bytes_to_samples(size_t bytes, int channels);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
size_t xbox_ima_bytes_to_samples(size_t bytes, int channels);
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset);
/* ngc_dsp_decoder */

View File

@ -403,7 +403,7 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header,
for (i = 0; i < data->formatCtx->nb_streams; ++i) {
stream = data->formatCtx->streams[i];
if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
if (stream->codecpar && stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
streamCount++;
/* select Nth audio stream if specified, or first one */

View File

@ -169,7 +169,7 @@ size_t switch_opus_get_samples(off_t offset, size_t data_size, int sample_rate,
uint8_t buf[4];
size_t block_size = read_32bitBE(offset, streamFile);
read_streamfile(buf, offset+4, 4, streamFile);
read_streamfile(buf, offset+8, 4, streamFile);
num_samples += get_opus_samples_per_frame(buf, sample_rate);
offset += 0x08 + block_size;

View File

@ -272,46 +272,126 @@ void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
}
/* ************************************ */
/* MS IMA */
/* MS-IMA */
/* ************************************ */
/* IMA with frames with header and custom sizes */
/* IMA with variable-sized frames, header and custom nibble layout (outputs non-aligned number of samples).
* Officially defined in "Microsoft Multimedia Standards Update" doc (RIFFNEW.pdf). */
void decode_ms_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count;
int i, samples_read = 0, samples_done = 0, max_samples;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
int32_t hist1;// = stream->adpcm_history1_32;
int step_index;// = stream->adpcm_step_index;
//internal interleave (configurable size), mixed channels (4 byte per ch)
int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels;
/* internal interleave (configurable size), mixed channels (4 byte per ch) */
int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
first_sample = first_sample % block_samples;
//normal header (per channel)
if (first_sample == 0) {
off_t header_offset = stream->offset + 4*channel;
/* normal header (hist+step+reserved per channel) */
{
off_t header_offset = stream->offset + 0x04*channel;
hist1 = read_16bitLE(header_offset,stream->streamfile);
step_index = read_8bit(header_offset+2,stream->streamfile);
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */
if (step_index < 0) step_index = 0;
if (step_index > 88) step_index = 88;
/* write header sample */
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)hist1;
samples_done++;
}
samples_read++;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 4*channel + 4*vgmstream->channels + i/8*4*vgmstream->channels + (i%8)/2;
int nibble_shift = (i&1?4:0); //low nibble first
max_samples = (block_samples - samples_read);
if (max_samples > samples_to_do + first_sample - samples_done)
max_samples = samples_to_do + first_sample - samples_done; /* for smaller last block */
/* decode nibbles (layout: alternates 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;
int nibble_shift = (i&1?4:0); /* low nibble first */
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)(hist1);
samples_done++;
}
samples_read++;
}
//internal interleave: increment offset on complete frame
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
/* internal interleave: increment offset on complete frame */
if (first_sample + samples_done == block_samples) {
stream->offset += vgmstream->interleave_block_size;
}
/* MS IMA with fixed frame size and custom multichannel nibble layout.
//stream->adpcm_history1_32 = hist1;
//stream->adpcm_step_index = step_index;
}
/* Reflection's MS-IMA (some layout info from XA2WAV by Deniz Oezmen) */
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * 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;
/* internal interleave (configurable size), mixed channels (4 byte per ch) */
int block_channel_size = (vgmstream->interleave_block_size - 0x04*vgmstream->channels) / vgmstream->channels;
int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
first_sample = first_sample % block_samples;
/* normal header (hist+step+reserved per channel) */
{
off_t header_offset = stream->offset + 0x04*channel;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */
if (step_index < 0) step_index = 0;
if (step_index > 88) step_index = 88;
/* write header sample */
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)hist1;
samples_done++;
}
samples_read++;
}
max_samples = (block_samples - samples_read);
if (max_samples > samples_to_do + first_sample - samples_done)
max_samples = samples_to_do + first_sample - samples_done; /* for smaller last block */
/* decode nibbles (layout: all nibbles from one channel, then other channels) */
for (i = 0; i < max_samples; i++) {
off_t byte_offset = stream->offset + 0x04*vgmstream->channels + block_channel_size*channel + i/2;
int nibble_shift = (i&1?4:0); /* low nibble first */
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)(hist1);
samples_done++;
}
samples_read++;
}
/* internal interleave: increment offset on complete frame */
if (first_sample + samples_done == block_samples) {
stream->offset += vgmstream->interleave_block_size;
}
//stream->adpcm_history1_32 = hist1;
//stream->adpcm_step_index = step_index;
}
/* ************************************ */
/* XBOX-IMA */
/* ************************************ */
/* MS-IMA with fixed frame size, skips last sample per channel (for aligment) and custom multichannel nibble layout.
* For multichannel the layout is (I think) mixed stereo channels (ex. 6ch: 2ch + 2ch + 2ch) */
void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
@ -351,19 +431,19 @@ void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * o
}
//internal interleave: increment offset on complete frame
if (channelspacing==1) {
if (channelspacing==1) { /* mono */
if (offset-stream->offset == 32+3) // ??
stream->offset+=36;
stream->offset += 0x24;
} else {
if (offset-stream->offset == 64+(4*(channel%2))+3) // ??
stream->offset+=36*channelspacing;
stream->offset += 0x24*channelspacing;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
/* mono XBOX ADPCM for interleave */
/* mono XBOX-IMA ADPCM for interleave */
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0, num_frame;
int32_t hist1 = stream->adpcm_history1_32;
@ -565,6 +645,7 @@ void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelsp
stream->adpcm_step_index = step_index;
}
/* XBOX-IMA with modified data layout */
void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
@ -572,7 +653,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
int step_index = stream->adpcm_step_index;
//internal interleave
int block_samples = (36 - 4) * 2; /* block size - header, 2 samples per byte */
int block_samples = (0x24 - 4) * 2; /* block size - header, 2 samples per byte */
first_sample = first_sample % block_samples;
//interleaved header (all hist per channel + all step_index per channel)
@ -601,7 +682,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
stream->adpcm_step_index = step_index;
}
/* XBOX-IMA with modified data layout */
void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0;
@ -638,7 +719,6 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample *
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
sample_count+=channelspacing;
//todo atenuation: apparently from hcs's analysis Wwise IMA decodes nibbles slightly different, reducing dbs
}
}
@ -648,45 +728,23 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample *
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
//todo atenuation: apparently from hcs's analysis Wwise IMA expands nibbles slightly different, reducing clipping/dbs
/*
From Wwise_v2015.1.6_Build5553_SDK.Linux
<_ZN13CAkADPCMCodec12DecodeSampleEiii>:
10: 83 e0 07 and $0x7,%eax ; sample
13: 01 c0 add %eax,%eax ; sample*2
15: 83 c0 01 add $0x1,%eax ; sample*2+1
18: 0f af 45 e4 imul -0x1c(%rbp),%eax ; (sample*2+1)*scale
1c: 8d 50 07 lea 0x7(%rax),%edx ; result+7
1f: 85 c0 test %eax,%eax ; result negative?
21: 0f 48 c2 cmovs %edx,%eax ; adjust if negative to fix rounding for below division
24: c1 f8 03 sar $0x3,%eax ; (sample*2+1)*scale/8
/* Reflection's MS-IMA (some layout info from XA2WAV) */
void decode_ref_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
//internal interleave (configurable size), mixed channels (4 byte per ch)
int block_channel_size = (vgmstream->interleave_block_size - 4*vgmstream->channels) / vgmstream->channels;
int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels;
first_sample = first_sample % block_samples;
//normal header (per channel)
if (first_sample == 0) {
off_t header_offset = stream->offset + 4*channel;
hist1 = read_16bitLE(header_offset,stream->streamfile);
step_index = read_8bit(header_offset+2,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
//layout: all nibbles from one channel, then all nibbles from other
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 4*vgmstream->channels + block_channel_size*channel + i/2;
int nibble_shift = (i&1?4:0); //low nibble first
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
}
//internal interleave: increment offset on complete frame
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
Different rounding model vs IMA's shift-and-add (also "adjust" step may be unnecessary).
*/
/* MS-IMA with possibly the XBOX-IMA model of even number of samples per block (more tests are needed) */
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count;
@ -785,17 +843,24 @@ void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
}
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) {
/* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels
+ ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0);
}
size_t ima_bytes_to_samples(size_t bytes, int channels) {
/* 2 samples per byte (2 nibbles) in stereo or mono config */
return bytes * 2 / channels;
}
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) {
/* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
return (bytes / block_align) * ((block_align - 0x04*channels) * 2 / channels + 1)
+ ((bytes % block_align) ? (((bytes % block_align) - 0x04*channels) * 2 / channels + 1) : 0);
}
size_t xbox_ima_bytes_to_samples(size_t bytes, int channels) {
int block_align = 0x24 * channels;
/* XBOX IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels
+ ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0); //todo probably not possible (aligned)
}
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset) {
int version, big_endian, header_samples;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;

View File

@ -530,8 +530,8 @@ static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info*
VGM_LOG("MPEG EAL3: written 0x%lx but expected less than 0x%x at 0x%lx\n", os->b_off/8, expected_frame_size, os->info_offset);
}
else {
/* fill ancillary data (ignored) */
memset(os->buf + os->b_off/8, 0x77, expected_frame_size - os->b_off/8);
/* fill ancillary data (should be ignored, but 0x00 seems to improve mpg123's free bitrate detection) */
memset(os->buf + os->b_off/8, 0x00, expected_frame_size - os->b_off/8);
}
os->b_off = expected_frame_size*8;

View File

@ -21,10 +21,6 @@ static const int ADPCMCoeffs[7][2] =
{ 392, -232 }
};
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) {
return bytes/block_size*((block_size-(7-1)*channels)*2/channels);
}
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) {
VGMSTREAMCHANNEL *ch1,*ch2;
int i;
@ -161,3 +157,8 @@ void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_s
}
}
}
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) {
return (bytes / block_size) * (block_size - (7-1)*channels) * 2 / channels
+ ((bytes % block_size) ? ((bytes % block_size) - (7-1)*channels) * 2 / channels : 0);
}

View File

@ -470,8 +470,8 @@ static const coding_info coding_info_list[] = {
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (mono/interleave)"},
{coding_3DS_IMA, "3DS IMA 4-bit ADPCM"},
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
{coding_XBOX, "XBOX 4-bit IMA ADPCM"},
{coding_XBOX_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"},
{coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"},
{coding_XBOX_IMA_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"},
{coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"},
{coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"},
{coding_RAD_IMA, "Radical 4-bit IMA ADPCM"},
@ -564,7 +564,7 @@ static const layout_info layout_info_list[] = {
{layout_gsb_blocked, "GSB blocked"},
{layout_thp_blocked, "THP Movie Audio blocked"},
{layout_filp_blocked, "FILp blocked"},
{layout_psx_mgav_blocked, "MGAV blocked"},
{layout_blocked_ea_swvr, "blocked (EA SWVR)"},
{layout_ps2_adm_blocked, "ADM blocked"},
{layout_dsp_bdsp_blocked, "DSP blocked"},
{layout_blocked_ivaud, "blocked (IVAUD)"},
@ -641,7 +641,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_STR, "assumed STR + STH File by .str & .sth extension"},
{meta_PS2_ILD, "ILD header"},
{meta_PS2_PNB, "assumed PNB (PsychoNauts Bgm File) by .pnb extension"},
{meta_XBOX_WAVM, "assumed Xbox WAVM file by .wavm extension"},
{meta_XBOX_WAVM, "Xbox WAVM raw header"},
{meta_XBOX_RIFF, "Microsoft XWAV RIFF header"},
{meta_DSP_STR, "assumed Conan Gamecube STR File by .str extension"},
{meta_EA_SCHL, "Electronic Arts SCHl header (variable)"},
@ -717,7 +717,7 @@ static const meta_info meta_info_list[] = {
{meta_DC_STR, "Sega Stream Asset Builder header"},
{meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"},
{meta_XBOX_XMU, "XMU header"},
{meta_XBOX_XVAS, "assumed TMNT file by .xvas extension"},
{meta_XBOX_XVAS, "Konami .XVAS header"},
{meta_PS2_XA2, "Acclaim XA2 Header"},
{meta_DC_IDVI, "Capcom IDVI header"},
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"},
@ -838,7 +838,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_ADSC, "ADSC Header"},
{meta_NGC_DSP_MPDS, "MPDS DSP header"},
{meta_DSP_STR_IG, "Infogrames dual dsp header"},
{meta_PSX_MGAV, "Electronic Arts RVWS header"},
{meta_EA_SWVR, "Electronic Arts SWVR header"},
{meta_PS2_B1S, "B1S header"},
{meta_PS2_WAD, "WAD header"},
{meta_DSP_XIII, "XIII dsp header"},
@ -955,6 +955,7 @@ static const meta_info meta_info_list[] = {
{meta_XWC, "Starbreeze XWC header"},
{meta_SQEX_SAB, "Square-Enix SAB header"},
{meta_SQEX_MAB, "Square-Enix MAB header"},
{meta_OGG_L2SD, "Ogg Vorbis (L2SD)"},
#ifdef VGM_USE_MP4V2
{meta_MP4, "AAC header"},

View File

@ -128,8 +128,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_blocked_ivaud:
block_update_ivaud(vgmstream->next_block_offset,vgmstream);
break;
case layout_psx_mgav_blocked:
psx_mgav_block_update(vgmstream->next_block_offset,vgmstream);
case layout_blocked_ea_swvr:
block_update_ea_swvr(vgmstream->next_block_offset,vgmstream);
break;
case layout_ps2_adm_blocked:
ps2_adm_block_update(vgmstream->next_block_offset,vgmstream);

View File

@ -149,7 +149,6 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
for (i = 0; i < vgmstream->channels; i++) {
off_t channel_start = read_32bit(block_offset + 0x0C + (0x04*i),streamFile);
vgmstream->ch[i].offset = block_offset + 0x0C + (0x04*vgmstream->channels) + channel_start;
VGM_LOG("ch=%x, off=%lx\n", i, vgmstream->ch[i].offset);
}
/* read ADPCM history before each channel if needed (not actually read in sx.exe) */

View File

@ -7,6 +7,8 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
uint32_t block_size, block_samples;
size_t file_size = get_streamfile_size(streamFile);
off_t channel_start;
size_t channel_interleave;
int i;
/* always BE */
@ -26,9 +28,26 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
* - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */
block_size &= 0x00FFFFFF;
switch(vgmstream->coding_type) {
case coding_NGC_DSP:
/* 0x04: unknown (0x00/02), 0x08: some size?, 0x34: null? */
channel_start = read_32bitBE(block_offset+0x08+0x00,streamFile);
channel_interleave = read_32bitBE(block_offset+0x08+0x0c,streamFile);
/* guessed as all known EA DSP only have one block with subheader (maybe changes coefs every block?) */
if (channel_start >= 0x40) {
dsp_read_coefs_be(vgmstream,streamFile, block_offset+0x08+0x10,0x28);
dsp_read_hist_be (vgmstream,streamFile, block_offset+0x08+0x30,0x28);//todo guessed and doesn't fix clicks in full loops
}
break;
default:
channel_start = 0x00;
channel_interleave = 0x00;
break;
}
for (i = 0; i < vgmstream->channels; i++) {
off_t channel_start = 0x00;
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start;
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i*channel_interleave;
/* also fix first offset (for EALayer3) */
if (block_offset == vgmstream->ch[i].channel_start_offset) {

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
int i;
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bit(vgmstream->current_block_offset+0x04,streamFile)-0x1C;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i);
}
}

View File

@ -46,7 +46,7 @@ void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream);
void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream);
void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream);

View File

@ -1,17 +0,0 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset+0x04,vgmstream->ch[0].streamfile)-0x1C;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i);
}
}

View File

@ -6,38 +6,33 @@
VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag;
int channel_count;
int identifer_byte;
int loop_flag, channel_count, codec;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"ads")) goto fail;
/* check dhSS Header */
if (read_32bitBE(0x00,streamFile) != 0x64685353)
if (read_32bitBE(0x00,streamFile) != 0x64685353) /* "dhSS" */
goto fail;
/* check dbSS Header */
if (read_32bitBE(0x20,streamFile) != 0x64625353)
if (read_32bitBE(0x20,streamFile) != 0x64625353) /* "dbSS" */
goto fail;
loop_flag = 1;
channel_count = read_32bitBE(0x10,streamFile);
if (channel_count > 0x2)
if (channel_count > 2)
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
identifer_byte = read_32bitBE(0x08,streamFile);
switch (identifer_byte) {
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
codec = read_32bitBE(0x08,streamFile);
switch (codec) {
case 0x00000020: /* GC */
start_offset = 0x28 + 0x60 * channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x28,streamFile);
if (loop_flag) {
@ -57,10 +52,8 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
case 0x00000021: /* Xbox */
start_offset = 0x28;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
vgmstream->coding_type = coding_XBOX_int;
vgmstream->num_samples = (read_32bitBE(0x24,streamFile) / 36 *64 / vgmstream->channels)-64; // to avoid the "pop" at the loop point
vgmstream->coding_type = coding_XBOX_IMA_int;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitBE(0x24,streamFile), vgmstream->channels);
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
vgmstream->interleave_block_size = 0x24;
if (loop_flag) {

View File

@ -42,7 +42,7 @@ static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) {
size_t filename_len;
int i, num_segments = 0;
size_t riff_size;
VGM_LOG("1\n");
if (read_16bitLE(0x1c,streamFile) != 0) goto fail; /* this must be first segment */
if (read_16bitLE(0x1e,streamFile) < 1 || read_16bitLE(0x1e,streamFile) > ATX_MAX_SEGMENTS) goto fail;
@ -57,7 +57,7 @@ VGM_LOG("1\n");
for (i = 0; i < num_segments; i++) {
off_t subfile_offset;
size_t subfile_size;
VGM_LOG("loop\n");
filename[filename_len - 5] = ('0'+i+1); /* ghetto digit conversion */
new_streamFile = open_stream_name(streamFile, filename);
if (!new_streamFile) goto fail;
@ -69,7 +69,7 @@ VGM_LOG("loop\n");
/* parse block/segment header (other Media.Vision's files use it too) */
subfile_offset = read_32bitLE(0x08,segment_streamFiles[i]); /* header size */
subfile_size = read_32bitLE(0x14,segment_streamFiles[i]); /* can be 0 in other containers */
VGM_LOG("subfile: %lx, %x\n", subfile_offset, subfile_size);
if (read_16bitLE(0x1c,segment_streamFiles[i]) != i)
goto fail; /* segment sequence */
/* 0x04: block size (should match subfile_size in .ATX) */

View File

@ -31,7 +31,7 @@ VGMSTREAM * init_vgmstream_aus(STREAMFILE *streamFile) {
vgmstream->num_samples = read_32bitLE(0x08,streamFile);
if(read_16bitLE(0x06,streamFile)==0x02) {
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type=layout_none;
} else {
vgmstream->coding_type = coding_PSX;

View File

@ -37,9 +37,6 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) {
if (!parse_awc_header(streamFile, &awc))
goto fail;
if (awc.is_encrypted)
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(awc.channel_count, 0);
@ -156,6 +153,10 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) {
if (flags & 0x00080000) /* encrypted data chunk (most of GTA5 PC) */
awc->is_encrypted = 1;
if (awc->is_encrypted) {
VGM_LOG("AWC: encrypted data found\n");
goto fail;
}
/* Music when the first id is 0 (base/fake entry with info for all channels), sfx pack otherwise.
* sfx = N single streams, music = N-1 interleaved mono channels (even for MP3/XMA).
@ -267,7 +268,7 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) {
/* If music, data is divided into blocks of block_chunk size with padding.
* Each block has a header/seek table and interleaved data for all channels */
if (awc->is_music && read_32bit(awc->stream_offset, streamFile) != 0) {
VGM_LOG("AWC: music found, but block doesn't start with seek table\n");
VGM_LOG("AWC: music found, but block doesn't start with seek table at %lx\n", awc->stream_offset);
goto fail;
}

View File

@ -15,10 +15,15 @@ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile) {
if (!check_extensions(streamFile,"snr"))
goto fail;
/* SNR headers normally need an external SNS file, but some have data */
/* SNR headers normally need an external SNS file, but some have data [Burnout Paradise, NFL2013 (iOS)] */
if (get_streamfile_size(streamFile) > 0x10) {
/* SNR with data (flag 0x40 not set), seen in Burnout Paradise, NFL2013 iOS */
off_t start_offset = (read_32bitBE(0x08, streamFile) == 0) ? 0x0c : 0x08;
off_t start_offset;
switch(read_8bit(0x04,streamFile)) { /* flags */
case 0x60: start_offset = 0x10; break;
case 0x20: start_offset = 0x0c; break;
default: start_offset = 0x08; break;
}
vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x00, start_offset, meta_EA_SNR_SNS);
if (!vgmstream) goto fail;
@ -31,11 +36,11 @@ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile) {
if (!vgmstream) goto fail;
}
if (streamData) close_streamfile(streamData);
close_streamfile(streamData);
return vgmstream;
fail:
if (streamData) close_streamfile(streamData);
close_streamfile(streamData);
return NULL;
}
@ -119,7 +124,8 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
sample_rate = (uint16_t)read_16bitBE(header_offset + 0x02,streamHead);
flags = (uint8_t)read_8bit(header_offset + 0x04,streamHead); /* upper nibble only? */
num_samples = (uint32_t)read_32bitBE(header_offset + 0x04,streamHead) & 0x00FFFFFF;
/* optional, in some headers: 0x08: null? 0x0c: varies (ex. null, full size) */
/* rest is optional, depends on flags header used (ex. SNU and SPS may have bigger headers):
* &0x20: 1 int (usually 0x00), &0x00/40: nothing, &0x60: 2 ints (usually 0x00 and 0x14) */
/* V0: SNR+SNS, V1: SPR+SPS (not apparent differences) */
if (version != 0 && version != 1) {
@ -166,14 +172,14 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
/* EA decoder list and known internal FourCCs */
switch(codec) {
case 0x02: /* "P6B0": PCM16BE (NBA Jam Wii) */
case 0x02: /* "P6B0": PCM16BE [NBA Jam (Wii)] */
vgmstream->coding_type = coding_PCM16_int;
vgmstream->codec_endian = 1;
vgmstream->layout_type = layout_blocked_ea_sns;
break;
#ifdef VGM_USE_FFMPEG
case 0x03: { /* "EXm0": EA-XMA (Dante's Inferno X360) */
case 0x03: { /* "EXm0": EA-XMA [Dante's Inferno (X360)] */
uint8_t buf[0x100];
int bytes, block_size, block_count;
size_t stream_size, virtual_size;
@ -200,15 +206,15 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
}
#endif
case 0x04: /* "Xas1": EA-XAS (Dead Space PC/PS3) */
case 0x04: /* "Xas1": EA-XAS [Dead Space (PC/PS3)] */
vgmstream->coding_type = coding_EA_XAS;
vgmstream->layout_type = layout_blocked_ea_sns;
break;
#ifdef VGM_USE_MPEG
case 0x05: /* "EL31": EALayer3 v1 (Need for Speed: Hot Pursuit PS3) */
case 0x06: /* "L32P": EALayer3 v2 "PCM" (Battlefield 1943 PS3) */
case 0x07: { /* "L32S": EALayer3 v2 "Spike" (Dante's Inferno PS3) */
case 0x05: /* "EL31": EALayer3 v1 [Need for Speed: Hot Pursuit (PS3)] */
case 0x06: /* "L32P": EALayer3 v2 "PCM" [Battlefield 1943 (PS3)] */
case 0x07: { /* "L32S": EALayer3 v2 "Spike" [Dante's Inferno (PS3)] */
mpeg_custom_config cfg = {0};
off_t mpeg_start_offset = start_offset + 0x08;
mpeg_custom_t type = (codec == 0x05 ? MPEG_EAL31b : (codec == 0x06) ? MPEG_EAL32P : MPEG_EAL32S);
@ -222,7 +228,13 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
}
#endif
#if 0 //todo unknown variation
case 0x08: /* "Gca0"?: DSP [Need for Speed: Nitro sfx (Wii)] */
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_ea_sns;
/* DSP coefs are read in the blocks */
break;
#if 0 //todo buffered ATRAC9
#ifdef VGM_USE_ATRAC9
case 0x0a: { /* EATrax */
atrac9_config cfg = {0};
@ -241,8 +253,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
#endif
case 0x00: /* "NONE" (internal 'codec not set' flag) */
case 0x01: /* not used/reserved? Gca0/MP30/P6L0/P2B0/P2L0/P8S0/P8U0/PFN0? */
case 0x08: /* ? */
case 0x01: /* not used/reserved? /MP30/P6L0/P2B0/P2L0/P8S0/P8U0/PFN0? */
case 0x09: /* EASpeex (libspeex variant, base versions vary: 1.0.5, 1.2beta3) */
case 0x0b: /* ? */
case 0x0c: /* EAOpus (inside each SNS/SPS block is 16b frame size + standard? Opus packet) */

View File

@ -292,7 +292,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
break;
case EA_CODEC2_XBOXADPCM: /* XBOX IMA (interleaved mono) */
vgmstream->coding_type = coding_XBOX_int;
vgmstream->coding_type = coding_XBOX_IMA_int;
break;
case EA_CODEC2_GCADPCM: /* DSP */
@ -342,7 +342,6 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
case EA_CODEC2_MT10: /* MicroTalk (10:1 compression) */
case EA_CODEC2_MT5: /* MicroTalk (5:1 compression) */
vgmstream->coding_type = coding_EA_MT;
VGM_LOG("mt: codec=%x, cv=%x, v=%x\n", ea->codec2, ea->codec_version, ea->version);
vgmstream->codec_data = init_ea_mt(vgmstream->channels, ea->version == EA_VERSION_V3);
if (!vgmstream->codec_data) goto fail;
break;

View File

@ -0,0 +1,80 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* SWVR - from EA games [Future Cop L.A.P.D. (PS/PC), Freekstyle (PS2/GC), EA Sports Supercross (PS)] */
VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count;
int big_endian;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
/* check extension */
if (!check_extensions(streamFile,"str"))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) == 0x53575652) { /* "SWVR" (GC) */
big_endian = 1;
read_32bit = read_32bitBE;
}
else if (read_32bitBE(0x00,streamFile) == 0x52565753) { /* "RVWS" (PS/PS2) */
big_endian = 0;
read_32bit = read_32bitLE;
}
else {
goto fail;
}
start_offset = read_32bit(0x04,streamFile);
loop_flag = 1;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = 16000;
vgmstream->codec_endian = big_endian;
vgmstream->meta_type = meta_EA_SWVR;
vgmstream->layout_type = layout_blocked_ea_swvr;
vgmstream->coding_type = coding_PSX;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
/* calculate samples */
{
off_t current_chunk = start_offset;
vgmstream->num_samples = 0;
while ((current_chunk + start_offset) < (get_streamfile_size(streamFile))) {
uint32_t block_id = (read_32bit(current_chunk,streamFile));
if (block_id == 0x5641474D) { /* "VAGM" */
block_update_ea_swvr(start_offset,vgmstream);
vgmstream->num_samples += vgmstream->current_block_size/16*28;
current_chunk += vgmstream->current_block_size + 0x1C;
}
current_chunk += 0x10;
}
}
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -288,7 +288,7 @@ VGMSTREAM * init_vgmstream_fsb(STREAMFILE *streamFile) {
/* FSOUND_IMAADPCMSTEREO is "noninterleaved, true stereo IMA", but doesn't seem to be any different
* (found in FSB4: Shatter, Blade Kitten (PC), Hard Corps: Uprising (PS3)) */
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
/* "interleaved header" IMA, only used with >2ch (ex. Blade Kitten 6ch)
* or (seemingly) when flag is used (ex. Dead to Rights 2 (Xbox) 2ch in FSB3.1 */

View File

@ -237,7 +237,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
break;
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */
vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX;
vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
break;

View File

@ -84,7 +84,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* type to coding conversion */
switch (genh.codec) {
case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX; 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;
@ -194,7 +194,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = genh.interleave;
vgmstream->layout_type = layout_none;
break;
case coding_XBOX:
case coding_XBOX_IMA:
vgmstream->layout_type = layout_none;
break;
case coding_NGC_DTK:

View File

@ -490,7 +490,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile);

View File

@ -18,6 +18,8 @@ VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) {
loop_flag = 0;
channel_count = read_16bitLE(0x16,streamFile);
if (read_32bitLE(0x18,streamFile) == 0x4800 && vgmstream->channels > 2)
channel_count = 2; //todo add support for interleave stereo streams
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
@ -36,14 +38,12 @@ VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) {
/* no other way to know */
if (vgmstream->interleave_block_size == 0x4800) {
/* interleaved stereo streams (2ch 0x4800 + 2ch 0x4800 = 4ch) */
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_interleave;
/* header values are somehow off? */
data_size = get_streamfile_size(streamFile);
vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->channels = 2; //todo add support for interleave stereo streams
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
}
else {
/* 0x800 interleave */

View File

@ -232,6 +232,7 @@ VGMSTREAM * init_vgmstream_ngc_mdsp_std(STREAMFILE *streamFile) {
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave_shortblock;
vgmstream->meta_type = meta_DSP_STD;
vgmstream->interleave_block_size = header.block_size * 8;
if (vgmstream->interleave_block_size)
vgmstream->interleave_smallblock_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
for (i = 0; i < channel_count; i++) {
@ -620,7 +621,11 @@ VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) {
ch0_header.loop_flag != ch1_header.loop_flag ||
ch0_header.loop_start_offset != ch1_header.loop_start_offset ||
ch0_header.loop_end_offset != ch1_header.loop_end_offset
) goto fail;
) {
/* Timesplitters 2 GC's ts2_atom_smasher_44_fx.mss differs slightly in samples but plays ok */
if (meta_type != meta_DSP_MSS)
goto fail;
}
if (ch0_header.loop_flag) {
off_t loop_off;

View File

@ -9,7 +9,7 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
int loop_flag = 0, channel_count;
int num_samples = 0, loop_start = 0, loop_end = 0;
off_t offset = 0, data_offset;
size_t data_size;
size_t data_size, skip = 0;
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"opus,lopus,nop")) /* no relation to Ogg Opus */
@ -53,6 +53,7 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
channel_count = read_8bit(offset + 0x09, streamFile);
/* 0x0a: packet size if CBR, 0 if VBR */
data_offset = offset + read_32bitLE(offset + 0x10, streamFile);
skip = read_32bitLE(offset + 0x1c, streamFile);
if ((uint32_t)read_32bitLE(data_offset, streamFile) != 0x80000004)
goto fail;
@ -77,10 +78,9 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
size_t bytes, skip;
size_t bytes;
ffmpeg_custom_config cfg;
skip = 0; //todo
ffmpeg_codec_data *ffmpeg_data;
bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate);
if (bytes <= 0) goto fail;
@ -88,14 +88,21 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
memset(&cfg, 0, sizeof(ffmpeg_custom_config));
cfg.type = FFMPEG_SWITCH_OPUS;
vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg);
if (!vgmstream->codec_data) goto fail;
ffmpeg_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (vgmstream->num_samples == 0)
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size, vgmstream->sample_rate, streamFile);
if (ffmpeg_data->skipSamples <= 0) {
ffmpeg_set_skip_samples(ffmpeg_data, skip);
}
if (vgmstream->num_samples == 0) {
vgmstream->num_samples = switch_opus_get_samples(start_offset, data_size,
vgmstream->sample_rate, streamFile) - skip;
}
}
#else
goto fail;

View File

@ -156,6 +156,26 @@ static void isd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
}
}
static void l2sd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
size_t bytes_read = size*nmemb;
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
char *header_id = "OggS";
/* First "OggS" is changed */
{
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x04) {
/* replace key in the first 4 bytes with "OggS" */
((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4];
}
else {
break;
}
}
}
}
/* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */
VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
@ -169,6 +189,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
int is_psychic = 0;
int is_sngw = 0;
int is_isd = 0;
int is_l2sd = 0;
/* check extension */
@ -195,6 +216,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
is_psychic = 1;
inf.decryption_callback = psychic_ogg_decryption_callback;
}
else if (read_32bitBE(0x00,streamFile) == 0x4C325344) { /* "L2SD" [Lineage II Chronicle 4 (PC)] */
is_l2sd = 1;
inf.decryption_callback = l2sd_ogg_decryption_callback;
}
else if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
goto fail; /* not known (ex. Wwise) */
}
@ -251,6 +276,8 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
inf.meta_type = meta_OGG_SNGW;
} else if (is_isd) {
inf.meta_type = meta_OGG_ISD;
} else if (is_l2sd) {
inf.meta_type = meta_OGG_L2SD;
} else {
inf.meta_type = meta_OGG_VORBIS;
}

View File

@ -1,77 +0,0 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* STR (Future Cop L.A.P.D.) */
VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
off_t current_chunk;
char filename[PATH_LIMIT];
int loop_flag = 0;
int channel_count;
int dataBuffer = 0;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x52565753) /* "RVWS" */
goto fail;
loop_flag = 1;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitLE(0x4,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = 16000;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_psx_mgav_blocked;
vgmstream->meta_type = meta_PSX_MGAV;
/* open the file for reading */
{
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
}
}
// calculate samples
current_chunk = start_offset;
vgmstream->num_samples = 0;
while ((current_chunk + start_offset) < (get_streamfile_size(streamFile)))
{
dataBuffer = (read_32bitBE(current_chunk,streamFile));
if (dataBuffer == 0x4D474156) /* "MGAV" */
{
psx_mgav_block_update(start_offset,vgmstream);
vgmstream->num_samples += vgmstream->current_block_size/16*28;
current_chunk += vgmstream->current_block_size + 0x1C;
}
current_chunk += 0x10;
}
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -126,18 +126,18 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
fmt->coding_type = coding_MSADPCM;
break;
case 0x11: /* MS IMA ADPCM */
case 0x11: /* MS IMA ADPCM [Layton Brothers: Mystery Room (iOS/Android)] */
if (fmt->bps != 4) goto fail;
fmt->coding_type = coding_MS_IMA;
break;
case 0x69: /* MS IMA ADPCM (XBOX) - Rayman Raving Rabbids 2 (PC) */
case 0x69: /* XBOX IMA ADPCM [Rayman Raving Rabbids 2 (PC) --maybe waa/wac/wam/wad?] */
if (fmt->bps != 4) goto fail;
fmt->coding_type = coding_MS_IMA;
fmt->coding_type = coding_XBOX_IMA;
break;
case 0x007A: /* MS IMA ADPCM (LA Rush, Psi Ops PC) */
/* 0x007A is apparently "Voxware SC3" but in .MED it's just MS-IMA */
case 0x007A: /* MS IMA ADPCM [LA Rush (PC), Psi Ops (PC)] */
/* 0x007A is apparently "Voxware SC3" but in .MED it's just MS-IMA (0x11) */
if (!check_extensions(streamFile,"med"))
goto fail;
@ -228,8 +228,8 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
size_t file_size, riff_size, data_size = 0;
off_t start_offset = 0;
int fact_sample_count = -1;
int fact_sample_skip = -1;
int fact_sample_count = 0;
int fact_sample_skip = 0;
int loop_flag = 0;
long loop_start_ms = -1;
@ -246,9 +246,10 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
int at3 = 0; /* Sony ATRAC3 / ATRAC3plus */
int at9 = 0; /* Sony ATRAC9 */
/* check extension, case insensitive
* .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC) */
if ( check_extensions(streamFile, "wav,lwav,da,cd,med") ) {
/* check extension */
/* .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC), .snd: Layton Brothers (iOS/Android) */
if ( check_extensions(streamFile, "wav,lwav,da,cd,med,snd") ) {
;
}
else if ( check_extensions(streamFile, "mwv") ) {
@ -355,7 +356,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
mwv_ctrl_offset = current_chunk;
break;
case 0x66616374: /* fact */
if (sns && chunk_size == 0x10) {
if (chunk_size == 0x04) { /* standard, usually found with ADPCM */
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
} else if (sns && chunk_size == 0x10) {
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
} else if ((at3 || at9) && chunk_size == 0x08) {
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
@ -380,13 +383,14 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
if (!FormatChunkFound || !DataChunkFound) goto fail;
//todo improve detection using fmt sizes/values as Wwise's don't match the RIFF standard
/* JUNK is an optional Wwise chunk, and Wwise hijacks the MSADPCM/MS_IMA/XBOX IMA ids (how nice).
* To ensure their stuff is parsed in wwise.c we reject their JUNK, which they put almost always.
* As JUNK is legal (if unusual) we only reject those codecs.
* (ex. Cave PC games have PCM16LE + JUNK + smpl created by "Samplitude software") */
if (JunkFound
&& check_extensions(streamFile,"wav,lwav") /* for some .MED IMA */
&& (fmt.coding_type==coding_MSADPCM || fmt.coding_type==coding_MS_IMA))
&& (fmt.coding_type==coding_MSADPCM /*|| fmt.coding_type==coding_MS_IMA*/ || fmt.coding_type==coding_XBOX_IMA))
goto fail;
@ -409,9 +413,11 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
case coding_PCM16LE:
vgmstream->num_samples = pcm_bytes_to_samples(data_size, fmt.channel_count, 16);
break;
case coding_PCM8_U_int:
vgmstream->num_samples = pcm_bytes_to_samples(data_size, vgmstream->channels, 8);
break;
case coding_L5_555:
if (!mwv) goto fail;
vgmstream->num_samples = data_size / 0x12 / fmt.channel_count * 32;
@ -437,12 +443,22 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
}
break;
case coding_MSADPCM:
vgmstream->num_samples = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
vgmstream->num_samples = fact_sample_count ? fact_sample_count :
msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
break;
case coding_MS_IMA:
vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
vgmstream->num_samples = fact_sample_count ? fact_sample_count :
ms_ima_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
break;
case coding_XBOX_IMA:
vgmstream->num_samples = fact_sample_count ? fact_sample_count :
xbox_ima_bytes_to_samples(data_size, fmt.channel_count);
break;
case coding_NGC_DSP:
if (!sns) goto fail;
if (fact_sample_count <= 0) goto fail;
@ -531,6 +547,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
switch (fmt.coding_type) {
case coding_MSADPCM:
case coding_MS_IMA:
case coding_XBOX_IMA:
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
#endif

View File

@ -142,74 +142,44 @@ fail:
}
/* RSD2XADP */
VGMSTREAM * init_vgmstream_rsd2xadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rsd",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x52534432) /* RSD2 */
goto fail;
if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */
/* check extension */
if (!check_extensions(streamFile,"rsd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x52534432) /* RSD2 */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x58414450) /* XADP */
goto fail;
start_offset = read_32bitLE(0x18,streamFile); /* not sure about this */
data_size = get_streamfile_size(streamFile);
loop_flag = 0;
channel_count = read_32bitLE(0x8,streamFile);
channel_count = read_32bitLE(0x08,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitLE(0x18,streamFile); /* not sure about this */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = loop_flag;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count;
}
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_RSD2XADP;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
if (vgmstream->coding_type == coding_XBOX) {
vgmstream->layout_type=layout_none;
vgmstream->ch[i].channel_start_offset=start_offset;
} else {
vgmstream->ch[i].channel_start_offset=
start_offset+vgmstream->interleave_block_size*i;
}
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset;
}
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}
@ -968,25 +938,24 @@ fail:
return NULL;
}
/* RSD6XADP */
/* RSD6XADP - from Crash Tag Team Racing (Xbox) */
VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag;
int channel_count;
/* check extension */
if (!check_extensions(streamFile,"rsd"))
goto fail;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rsd",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */
goto fail;
if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */
goto fail;
start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset;
loop_flag = 0;
channel_count = read_32bitLE(0x8,streamFile);
@ -994,46 +963,19 @@ VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = loop_flag;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count;
}
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_RSD6XADP;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
if (vgmstream->coding_type == coding_XBOX) {
vgmstream->layout_type=layout_none;
vgmstream->ch[i].channel_start_offset=start_offset;
} else {
vgmstream->ch[i].channel_start_offset=
start_offset+vgmstream->interleave_block_size*i;
}
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset;
}
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -189,13 +189,13 @@ VGMSTREAM * init_vgmstream_rws(STREAMFILE *streamFile) {
vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channel_count);
break;
case 0x936538EF: /* MS-IMA PC (936538EF 11B62D43 957FA71A DE44227A) */
case 0x2BA22F63: /* MS-IMA Xbox (2BA22F63 DD118F45 AA27A5C3 46E9790E) */
case 0x936538EF: /* XBOX-IMA PC (936538EF 11B62D43 957FA71A DE44227A) */
case 0x2BA22F63: /* XBOX-IMA Xbox (2BA22F63 DD118F45 AA27A5C3 46E9790E) */
/* ex. Broken Sword 3 (PC), Jacked (PC/Xbox), Burnout 2 (Xbox) */
vgmstream->coding_type = coding_XBOX;
vgmstream->interleave_block_size = 0; /* uses regular XBOX/MS-IMA interleave */
vgmstream->coding_type = coding_XBOX_IMA; /* PC and Xbox share the same data */
vgmstream->interleave_block_size = 0;
vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, 0x24 * channel_count, channel_count);
vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channel_count);
break;
default:

View File

@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_SAB;
switch(codec) {
case 0x01:
case 0x01: /* PC */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = is_stream ? align : 0x02;
@ -66,7 +66,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) {
break;
case 0x04:
case 0x04: /* PS2 */
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = is_stream ? align : 0x10;
@ -76,14 +76,14 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, vgmstream->channels);
break;
case 0x08:
vgmstream->coding_type = is_stream ? coding_XBOX_int : coding_XBOX;
case 0x08: /* Xbox */
vgmstream->coding_type = is_stream ? coding_XBOX_IMA_int : coding_XBOX_IMA;
vgmstream->layout_type = is_stream ? layout_interleave : layout_none;
vgmstream->interleave_block_size = is_stream ? align : 0x00;
vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->loop_start_sample = ms_ima_bytes_to_samples(loop_start, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->loop_end_sample = ms_ima_bytes_to_samples(loop_end, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, vgmstream->channels);
vgmstream->loop_start_sample = xbox_ima_bytes_to_samples(loop_start, vgmstream->channels);
vgmstream->loop_end_sample = xbox_ima_bytes_to_samples(loop_end, vgmstream->channels);
break;
default:

View File

@ -1,7 +1,8 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* SEG (found in Eragon) */
/* SEG - found in Eragon */
VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
@ -24,7 +25,7 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
}
else if (read_32bitBE(0x04,streamFile) == 0x78627800) /* "xbx\0" */
{
coding = coding_XBOX;
coding = coding_XBOX_IMA;
}
else goto fail;
@ -60,9 +61,9 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = 0x2000;
}
}
else if (coding_XBOX == coding)
else if (coding_XBOX_IMA == coding)
{
vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)/36/channel_count*64;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x0C,streamFile)-start_offset, channel_count);
vgmstream->meta_type = meta_XBOX_SEG;
vgmstream->layout_type = layout_none;
}

View File

@ -12,12 +12,12 @@ static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb,
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset, tables_offset, meta_offset, post_meta_offset;
off_t start_offset, tables_offset, meta_offset, post_meta_offset, name_offset = 0;
int32_t stream_size, subheader_size, loop_start, loop_end;
int total_subsongs, target_subsong = streamFile->stream_index;
int loop_flag = 0, channel_count, codec, sample_rate;
int aux_chunk_count;
int version, target_entry, aux_chunk_count;
int total_subsongs, target_subsong = streamFile->stream_index;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
@ -33,24 +33,25 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
read_32bitBE(0x04,streamFile) != 0x53534346) /* "SSCF" */
goto fail;
if (read_32bitBE(0x08,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */
read_32bitBE(0x08,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */
if (read_8bit(0x0c,streamFile) == 0x01) { /* big endian flag */
//size_offset = 0x14;
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
}
else if (read_32bitLE(0x08,streamFile) == 2 || /* version 2/3 LE, as seen in FFXIV for PC (and others) */
read_32bitLE(0x08,streamFile) == 3) {
} else {
//size_offset = 0x10;
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
}
else {
goto fail;
}
/* 0x0c: probably 0=LE, 1=BE */
/* 0x0d: unknown (always 0x04) */
/* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */
if (read_8bit(0x0d,streamFile) != 0x04)
goto fail;
/* v2: FFXIII demo (PS3), FFT0 test files (PC); v3: common; v4: Kingdom Hearts 2.8 (PS4) */
version = read_32bit(0x08,streamFile);
if (version != 2 && version != 3 && version != 4)
goto fail;
tables_offset = read_16bit(0x0e,streamFile); /* usually 0x30 or 0x20 */
#if 0
@ -74,7 +75,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* 0x14: always null? */
/* 0x18: table5? (unknown) start offset? */
/* 0x1c: unknown, often null */
/* each table entry is an uint32_t offset */
/* each table entry is an uint32_t offset; after entries there is padding */
/* if a table isn't present entries is 0 and offset points to next table */
/* find meta_offset in table3 (headers) and total subsongs */
@ -89,14 +90,16 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* manually find subsongs as entries can be dummy (ex. sfx banks in FF XIV or FF Type-0) */
for (i = 0; i < headers_entries; i++) {
off_t header_offset = read_32bit(headers_offset + i*0x04,streamFile);
off_t entry_offset = read_32bit(headers_offset + i*0x04,streamFile);
if (read_32bit(header_offset+0x0c,streamFile) == -1)
if (read_32bit(entry_offset+0x0c,streamFile) == -1)
continue; /* codec -1 when dummy */
total_subsongs++;
if (!meta_offset && total_subsongs == target_subsong)
meta_offset = header_offset;
if (!meta_offset && total_subsongs == target_subsong) {
meta_offset = entry_offset;
target_entry = i;
}
}
if (meta_offset == 0) goto fail;
/* SCD can contain 0 entries too */
@ -129,10 +132,24 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
post_meta_offset += read_32bit(post_meta_offset+0x04, streamFile);
}
/* find name if possible */
if (version == 4) {
int info_entries = read_16bit(tables_offset+0x00,streamFile);
int headers_entries = read_16bit(tables_offset+0x04,streamFile);
off_t info_offset = tables_offset+0x20;
/* not very exact as table1 and table3 entries may differ in V3, not sure about V4 */
if (info_entries == headers_entries) {
off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,streamFile);
name_offset = entry_offset+0x30;
}
}
#ifdef VGM_USE_VORBIS
/* special case using init_vgmstream_ogg_vorbis */
if (codec == 0x06) {
VGMSTREAM *ogg_vgmstream;
uint8_t ogg_version, ogg_byte;
vgm_vorbis_info_t inf = {0};
@ -176,7 +193,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
}
/* actual Ogg init */
return init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
if (ogg_vgmstream && name_offset)
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
return ogg_vgmstream;
}
#endif
@ -189,6 +209,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size;
vgmstream->meta_type = meta_SQEX_SCD;
if (name_offset)
read_string(vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
switch (codec) {
case 0x01: /* PCM */
@ -319,7 +341,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
}
#ifdef VGM_USE_FFMPEG
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx] */
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[200];
int32_t bytes;
@ -373,6 +395,27 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
}
#endif
#ifdef VGM_USE_ATRAC9
case 0x16: { /* ATRAC9 [Kingdom Hearts 2.8 (PS4)] */
atrac9_config cfg = {0};
/* post header has various typical ATRAC9 values */
cfg.channels = vgmstream->channels;
cfg.config_data = read_32bit(post_meta_offset+0x0c,streamFile);
cfg.encoder_delay = read_32bit(post_meta_offset+0x18,streamFile);
vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(post_meta_offset+0x10,streamFile); /* loop values above are also weird and ignored */
vgmstream->loop_start_sample = read_32bit(post_meta_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
vgmstream->loop_end_sample = read_32bit(post_meta_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
break;
}
#endif
case -1: /* used for dummy entries */
default:
VGM_LOG("SCD: unknown codec 0x%x\n", codec);

View File

@ -2,13 +2,14 @@
#include "../coding/coding.h"
static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size);
static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, int encryption, size_t header_size, size_t key_start);
/* SABF/MABF - Square Enix's "Sead" audio games [Dragon Quest Builders (PS3), Dissidia Opera Omnia (mobile), FF XV (PS4)] */
/* SABF/MABF - Square Enix's "sead" audio games [Dragon Quest Builders (PS3), Dissidia Opera Omnia (mobile), FF XV (PS4)] */
VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, mtrl_offset, meta_offset, post_meta_offset; //, info_offset, name_offset = 0;
size_t stream_size, subheader_size; //, name_size = 0;
off_t start_offset, tables_offset, mtrl_offset, meta_offset, post_meta_offset; //, info_offset, name_offset = 0;
size_t stream_size, descriptor_size, subheader_size, special_size; //, name_size = 0;
int loop_flag = 0, channel_count, codec, sample_rate, loop_start, loop_end;
int is_sab = 0, is_mab = 0;
@ -36,38 +37,43 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
// goto fail;
/* 0x04(1): version? (usually 0x02, rarely 0x01, ex FF XV title) */
/* 0x05(1): 0x00/01? */
/* 0x06(2): chunk size? (usually 0x10, rarely 0x20) */
if (read_16bitBE(0x06,streamFile) < 0x100) { /* use size as no apparent flag */
/* 0x06(2): version? (usually 0x10, rarely 0x20) */
if (read_16bitBE(0x06,streamFile) < 0x100) { /* use some value as no apparent flag */
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
}
/* 0x08(1): ?, 0x09(1): ?, 0x0a(2): ? */
/* 0x08(1): version 0x04?, 0x0a(2): ? */
descriptor_size = read_8bit(0x09,streamFile);
if (read_32bit(0x0c,streamFile) != get_streamfile_size(streamFile))
goto fail;
/* 0x10(10): file descriptor ("BGM", "Music", "SE", etc) */
/* 0x10(n): file descriptor ("BGM", "Music", "SE", etc, long names are ok), padded */
tables_offset = 0x10 + (descriptor_size + 0x01); /* string null seems counted for padding */
if (tables_offset % 0x10)
tables_offset += 0x10 - (tables_offset % 0x10);
/** offset tables **/
if (is_sab) {
if (read_32bitBE(0x20,streamFile) != 0x736E6420) goto fail; /* "snd " (info) */
if (read_32bitBE(0x30,streamFile) != 0x73657120) goto fail; /* "seq " (unknown) */
if (read_32bitBE(0x40,streamFile) != 0x74726B20) goto fail; /* "trk " (unknown) */
if (read_32bitBE(0x50,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */
//info_offset = read_32bit(0x28,streamFile);
//seq_offset = read_32bit(0x38,streamFile);
//trk_offset = read_32bit(0x48,streamFile);
mtrl_offset = read_32bit(0x58,streamFile);
if (read_32bitBE(tables_offset+0x00,streamFile) != 0x736E6420) goto fail; /* "snd " (info) */
if (read_32bitBE(tables_offset+0x10,streamFile) != 0x73657120) goto fail; /* "seq " (unknown) */
if (read_32bitBE(tables_offset+0x20,streamFile) != 0x74726B20) goto fail; /* "trk " (unknown) */
if (read_32bitBE(tables_offset+0x30,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */
//info_offset = read_32bit(tables_offset+0x08,streamFile);
//seq_offset = read_32bit(tables_offset+0x18,streamFile);
//trk_offset = read_32bit(tables_offset+0x28,streamFile);
mtrl_offset = read_32bit(tables_offset+0x38,streamFile);
}
else if (is_mab) {
if (read_32bitBE(0x20,streamFile) != 0x6D757363) goto fail; /* "musc" (info) */
if (read_32bitBE(0x30,streamFile) != 0x696E7374) goto fail; /* "inst" (unknown) */
if (read_32bitBE(0x40,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */
//info_offset = read_32bit(0x28,streamFile);
//inst_offset = read_32bit(0x38,streamFile);
mtrl_offset = read_32bit(0x48,streamFile);
if (read_32bitBE(tables_offset+0x00,streamFile) != 0x6D757363) goto fail; /* "musc" (info) */
if (read_32bitBE(tables_offset+0x10,streamFile) != 0x696E7374) goto fail; /* "inst" (unknown) */
if (read_32bitBE(tables_offset+0x20,streamFile) != 0x6D74726C) goto fail; /* "mtrl" (headers/streams) */
//info_offset = read_32bit(tables_offset+0x08,streamFile);
//inst_offset = read_32bit(tables_offset+0x18,streamFile);
mtrl_offset = read_32bit(tables_offset+0x28,streamFile);
}
else {
goto fail;
@ -114,7 +120,7 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
loop_end = read_32bit(meta_offset+0x10,streamFile);
subheader_size = read_32bit(meta_offset+0x14,streamFile); /* including subfile header */
stream_size = read_32bit(meta_offset+0x18,streamFile); /* not including subfile header */
/* 0x1c: null? */
special_size = read_32bit(meta_offset+0x1c,streamFile);
loop_flag = (loop_end > 0);
post_meta_offset = meta_offset + 0x20;
@ -122,7 +128,7 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
/** info section (get stream name) **/
//if (is_sab) { //todo load name based on entry id
/* "snd ": unknown flags/sizes and name */
/* "snd " */
/* 0x08(2): file number within descriptor */
/* 0x1a(2): base_entry size (-0x10?) */
//name_size = read_32bit(snd_offset+0x20,streamFile);
@ -130,7 +136,11 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
/* 0x24(4): unique id? (referenced in "seq" section) */
//}
//else if (is_mab) {
/* "musc": unknown flags sizes and names, another format */
/* "musc" */
//looks like a "music cue" section, pointing to one subsection per "material".
// ex. one cue may point to 3 named subsongs/sections.
// some common header info from all materials is repeated (ex. sample rate), while other
// (loops, maybe proper num_samples) are listed per material but don't always match thei header
//}
@ -161,6 +171,37 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
break;
}
#ifdef VGM_USE_VORBIS
case 0x03: { /* OGG [Final Fantasy XV Benchmark sfx (PC)] */
VGMSTREAM *ogg_vgmstream = NULL;
vgm_vorbis_info_t inf = {0};
off_t subfile_offset = post_meta_offset + subheader_size;
char filename[PATH_LIMIT];
streamFile->get_name(streamFile,filename,sizeof(filename));
inf.layout_type = layout_ogg_vorbis;
inf.meta_type = vgmstream->meta_type;
inf.total_subsongs = total_subsongs;
inf.stream_size = stream_size;
/* post header has some kind of repeated values, config/table? */
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, subfile_offset, &inf);
if (ogg_vgmstream) {
ogg_vgmstream->num_streams = vgmstream->num_streams;
ogg_vgmstream->stream_size = vgmstream->stream_size;
close_vgmstream(vgmstream);
return ogg_vgmstream;
}
else {
goto fail;
}
break;
}
#endif
#ifdef VGM_USE_ATRAC9
case 0x04: { /* ATRAC9 [Dragon Quest Builders (Vita), Final Fantaxy XV (PS4)] */
atrac9_config cfg = {0};
@ -170,12 +211,12 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
cfg.channels = vgmstream->channels;
cfg.config_data = read_32bit(post_meta_offset+0x0c,streamFile);
cfg.encoder_delay = read_32bit(post_meta_offset+0x18,streamFile);
VGM_LOG("1\n");
vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none;
VGM_LOG("2\n");
vgmstream->sample_rate = read_32bit(post_meta_offset+0x1c,streamFile); /* SAB's sample rate can be different but it's ignored */
vgmstream->num_samples = read_32bit(post_meta_offset+0x10,streamFile); /* loop values above are also weird and ignored */
vgmstream->loop_start_sample = read_32bit(post_meta_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
@ -210,10 +251,14 @@ VGM_LOG("2\n");
STREAMFILE *temp_streamFile = NULL;
off_t subfile_offset = post_meta_offset + 0x10;
size_t subfile_size = stream_size + subheader_size - 0x10;
/* post header has 0x10 unknown + HCA header */
/* post header: values from the HCA header, in file endianness + HCA header */
size_t key_start = special_size & 0xff;
size_t header_size = read_16bit(post_meta_offset+0x02, streamFile);
int encryption = read_16bit(post_meta_offset+0x0c, streamFile); //maybe 8bit?
/* encryption type 0x01 found in Final Fantasy XII TZA (PS4/PC) */
temp_streamFile = setup_sead_hca_streamfile(streamFile, subfile_offset, subfile_size);
temp_streamFile = setup_sead_hca_streamfile(streamFile, subfile_offset, subfile_size, encryption, header_size, key_start);
if (!temp_streamFile) goto fail;
temp_vgmstream = init_vgmstream_hca(temp_streamFile);
@ -249,7 +294,49 @@ fail:
return NULL;
}
static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size) {
typedef struct {
size_t header_size;
size_t key_start;
} sead_decryption_data;
/* Encrypted HCA */
static size_t sead_decryption_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, sead_decryption_data* data) {
/* Found in FFXII_TZA.exe (same key in SCD Ogg V3) */
static const uint8_t encryption_key[0x100] = {
0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F
0x32, 0x52, 0x16, 0x1B, 0x3C, 0xA1, 0x54, 0x7B, 0x1B, 0x97, 0xA6, 0x93, 0x1A, 0x4B, 0xAA, 0xA6, // 10-1F
0x7A, 0x7B, 0x1B, 0x97, 0xA6, 0xF7, 0x02, 0xBB, 0xAA, 0xA6, 0xBB, 0xF7, 0x2A, 0x51, 0xBE, 0x03, // 20-2F
0xF4, 0x2A, 0x51, 0xBE, 0x03, 0xF4, 0x2A, 0x51, 0xBE, 0x12, 0x06, 0x56, 0x27, 0x32, 0x32, 0x36, // 30-3F
0x32, 0xB2, 0x1A, 0x3B, 0xBC, 0x91, 0xD4, 0x7B, 0x58, 0xFC, 0x0B, 0x55, 0x2A, 0x15, 0xBC, 0x40, // 40-4F
0x92, 0x0B, 0x5B, 0x7C, 0x0A, 0x95, 0x12, 0x35, 0xB8, 0x63, 0xD2, 0x0B, 0x3B, 0xF0, 0xC7, 0x14, // 50-5F
0x51, 0x5C, 0x94, 0x86, 0x94, 0x59, 0x5C, 0xFC, 0x1B, 0x17, 0x3A, 0x3F, 0x6B, 0x37, 0x32, 0x32, // 60-6F
0x30, 0x32, 0x72, 0x7A, 0x13, 0xB7, 0x26, 0x60, 0x7A, 0x13, 0xB7, 0x26, 0x50, 0xBA, 0x13, 0xB4, // 70-7F
0x2A, 0x50, 0xBA, 0x13, 0xB5, 0x2E, 0x40, 0xFA, 0x13, 0x95, 0xAE, 0x40, 0x38, 0x18, 0x9A, 0x92, // 80-8F
0xB0, 0x38, 0x00, 0xFA, 0x12, 0xB1, 0x7E, 0x00, 0xDB, 0x96, 0xA1, 0x7C, 0x08, 0xDB, 0x9A, 0x91, // 90-9F
0xBC, 0x08, 0xD8, 0x1A, 0x86, 0xE2, 0x70, 0x39, 0x1F, 0x86, 0xE0, 0x78, 0x7E, 0x03, 0xE7, 0x64, // A0-AF
0x51, 0x9C, 0x8F, 0x34, 0x6F, 0x4E, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, // B0-BF
0x41, 0xFC, 0x3B, 0x70, 0x71, 0x64, 0x33, 0x32, 0x12, 0x32, 0x32, 0x36, 0x70, 0x34, 0x2B, 0x56, // C0-CF
0x22, 0x70, 0x3A, 0x13, 0xB7, 0x26, 0x60, 0xBA, 0x1B, 0x94, 0xAA, 0x40, 0x38, 0x00, 0xFA, 0xB2, // D0-DF
0xE2, 0xA2, 0x67, 0x32, 0x32, 0x12, 0x32, 0xB2, 0x32, 0x32, 0x32, 0x32, 0x75, 0xA3, 0x26, 0x7B, // E0-EF
0x83, 0x26, 0xF9, 0x83, 0x2E, 0xFF, 0xE3, 0x16, 0x7D, 0xC0, 0x1E, 0x63, 0x21, 0x07, 0xE3, 0x01, // F0-FF
};
size_t bytes_read;
int i;
bytes_read = streamfile->read(streamfile, dest, offset, length);
/* decrypt data (xor) */
if (offset >= data->header_size) {
for (i = 0; i < bytes_read; i++) {
dest[i] ^= encryption_key[(data->key_start + (offset - data->header_size) + i) % 0x100];
}
}
return bytes_read;
}
static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, int encryption, size_t header_size, size_t key_start) {
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
/* setup subfile */
@ -261,6 +348,18 @@ static STREAMFILE* setup_sead_hca_streamfile(STREAMFILE *streamFile, off_t subfi
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
if (encryption) {
sead_decryption_data io_data = {0};
size_t io_data_size = sizeof(sead_decryption_data);
io_data.header_size = header_size;
io_data.key_start = key_start;
new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, sead_decryption_read);
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
}
new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,"hca");
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;

View File

@ -5,12 +5,12 @@
/* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */
VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamHeader = NULL;
STREAMFILE * streamHeader = NULL, *streamData = NULL;
off_t start_offset, chunk_offset, first_offset = 0x60, name_offset = 0;
size_t chunk_size, stream_size = 0;
int is_separate;
int loop_flag, channels, codec;
int is_dual, is_external;
int loop_flag, channels, codec, location;
int sample_rate, num_samples, loop_start_sample, loop_end_sample;
uint32_t at9_config_data = 0;
int total_subsongs, target_subsong = streamFile->stream_index;
@ -19,10 +19,10 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
/* check extension, case insensitive */
/* .sxd: header+data (SXDF), .sxd1: header (SXDF) + .sxd2 = data (SXDS) */
if (!check_extensions(streamFile,"sxd,sxd2")) goto fail;
is_separate = !check_extensions(streamFile,"sxd");
is_dual = !check_extensions(streamFile,"sxd");
/* sxd1+sxd2: use sxd1 as header; otherwise use the current file as header */
if (is_separate) {
if (is_dual) {
if (read_32bitBE(0x00,streamFile) != 0x53584453) /* "SXDS" */
goto fail;
streamHeader = open_stream_ext(streamFile, "sxd1");
@ -50,7 +50,7 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
table_offset = chunk_offset + 0x08 + 4*(target_subsong-1);
header_offset = table_offset + read_32bitLE(table_offset,streamHeader);
/* 0x00(4): type/location? (00/01=sxd/RAM?, 02/03=sxd2/stream?) */
location = read_32bitLE(header_offset+0x00,streamHeader);
codec = read_8bit (header_offset+0x04,streamHeader);
channels = read_8bit (header_offset+0x05,streamHeader);
sample_rate = read_32bitLE(header_offset+0x08,streamHeader);
@ -69,7 +69,7 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
off_t max_offset = chunk_offset + chunk_size;
/* manually try to find certain tag, no idea about the actual format
* (most variable in Soul Sacrifice; extra size isn't found in the SXD AFAIK) */
* (most variable in Soul Sacrifice; extra data size isn't found in the header AFAIK) */
while (extra_offset < max_offset) {
uint32_t tag = read_32bitBE(extra_offset, streamHeader);
if (tag == 0x0A010000 || tag == 0x0A010600) {
@ -85,16 +85,33 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
loop_flag = loop_start_sample != -1 && loop_end_sample != -1;
/* from current offset in sxd, absolute in sxd2 */
if (is_separate) {
start_offset = stream_offset;
/* usually sxd=header+data and sxd1=header + sxd2=data, but rarely sxd1 contain data [The Last Guardian (PS4)] */
switch(location) { /* might not be exact but seems the only difference in TLG */
case 0x00: /* some Chaos Rings 2 sfx */
case 0x01: /* most common */
case 0x05: /* some Gradity Rush 2 sfx */
is_external = 0; /* RAM asset? */
break;
case 0x02: /* some Chaos Rings 3 sfx */
case 0x03: /* most common */
is_external = 1; /* stream asset? */
break;
default:
VGM_LOG("SXD: unknown location 0x%x\n", location);
goto fail;
}
if (is_external) {
start_offset = stream_offset; /* absolute if external */
} else {
start_offset = header_offset+0x24 + stream_offset;
start_offset = header_offset+0x24 + stream_offset; /* from current entry offset if internal */
}
}
/* get stream name (NAME is tied to REQD/cues, and SFX cues repeat WAVEs, but should work ok for streams) */
if (is_separate && find_chunk_le(streamHeader, 0x4E414D45,first_offset,0, &chunk_offset,NULL)) { /* "NAME" */
if (is_dual && find_chunk_le(streamHeader, 0x4E414D45,first_offset,0, &chunk_offset,NULL)) { /* "NAME" */
/* table: relative offset (32b) + hash? (32b) + cue index (32b) */
int i;
int num_entries = read_16bitLE(chunk_offset+0x04,streamHeader); /* can be bigger than streams */
@ -107,6 +124,22 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
}
}
if (is_external && !is_dual) {
VGM_LOG("SXD: found single sxd with external data\n");
goto fail;
}
if (is_external) {
streamData = streamFile;
} else {
streamData = streamHeader;
}
if (start_offset > get_streamfile_size(streamData)) {
VGM_LOG("SXD: wrong location?\n");
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
@ -136,7 +169,7 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
break;
#ifdef VGM_USE_ATRAC9
case 0x42: { /* ATRAC9 [Soul Sacrifice (Vita), Freedom Wars (Vita)] */
case 0x42: { /* ATRAC9 [Soul Sacrifice (Vita), Freedom Wars (Vita), Gravity Rush 2 (PS4)] */
atrac9_config cfg = {0};
cfg.channels = vgmstream->channels;
@ -157,14 +190,14 @@ VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile) {
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,streamData,start_offset))
goto fail;
if (is_separate && streamHeader) close_streamfile(streamHeader);
if (is_dual) close_streamfile(streamHeader);
return vgmstream;
fail:
if (is_separate && streamHeader) close_streamfile(streamHeader);
if (is_dual) close_streamfile(streamHeader);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -95,7 +95,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
/* type to coding conversion */
switch (txth.codec) {
case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX; 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;
@ -205,7 +205,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = txth.interleave;
vgmstream->layout_type = layout_none;
break;
case coding_XBOX:
case coding_XBOX_IMA:
vgmstream->layout_type = layout_none;
break;
case coding_NGC_DTK:
@ -474,7 +474,6 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h
else if (0==strcmp(key,"interleave")) {
if (0==strcmp(val,"half_size")) {
txth->interleave = txth->data_size / txth->channels;
VGM_LOG("int=%x, ds=%x\n", txth->interleave, txth->data_size);
}
else {
if (!parse_num(streamFile,val, &txth->interleave)) goto fail;
@ -635,7 +634,7 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
if (!txth->interleave) return 0;
return ms_ima_bytes_to_samples(bytes, txth->interleave, txth->channels);
case XBOX:
return ms_ima_bytes_to_samples(bytes, 0x24 * txth->channels, txth->channels);
return xbox_ima_bytes_to_samples(bytes, txth->channels);
case NGC_DSP:
return dsp_bytes_to_samples(bytes, txth->channels);
case PSX:

View File

@ -79,6 +79,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
case 0x57696E2070636D20: /* "Win pcm " */
case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4) */
case 0x4E78202070636D20: /* "Nx pcm " (Nx = Switch) */
/* chunks: "data" */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
@ -181,6 +182,48 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
}
#endif
#ifdef VGM_USE_FFMPEG
case 0x4E7820204E782020: { /* "Nx Nx " */
/* chunks: "MARK" (optional seek table), "STRG" (optional description) */
uint8_t buf[0x100];
size_t bytes, skip, opus_size;
ffmpeg_custom_config cfg = {0};
/* a standard Switch Opus header */
skip = read_32bitLE(start_offset + 0x1c, streamFile);
opus_size = read_32bitLE(start_offset + 0x10, streamFile) + 0x08;
start_offset += opus_size;
data_size -= opus_size;
cfg.type = FFMPEG_SWITCH_OPUS;
bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (((ffmpeg_codec_data*)vgmstream->codec_data)->skipSamples <= 0)
ffmpeg_set_skip_samples(vgmstream->codec_data, skip);
{
off_t chunk_offset = off + 0x20 + 0xc; /* after "fmt" */
while (chunk_offset < header_size) {
if (read_32bitBE(chunk_offset,streamFile) == 0x4164496E) { /*"AdIn" additional info */
off_t adin_offset = read_32bitLE(chunk_offset+0x04,streamFile);
vgmstream->num_samples = read_32bitLE(adin_offset,streamFile);
break;
}
chunk_offset += 0xc;
}
}
break;
}
#endif
default:
VGM_LOG("RAKI: unknown platform %x and type %x\n", platform, type);
goto fail;

View File

@ -119,6 +119,7 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
start_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_size + sb.section3_size;
start_offset += sb.stream_offset;
}
//;VGM_LOG("start offset=%lx, external=%i\n", start_offset, sb.is_external);
/* build the VGMSTREAM */
@ -154,9 +155,9 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
break;
case RAW_XBOX:
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ms_ima_bytes_to_samples(sb.stream_size, 0x24*sb.channels,sb.channels);
vgmstream->num_samples = xbox_ima_bytes_to_samples(sb.stream_size, sb.channels);
break;
case RAW_DSP:
@ -886,5 +887,21 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
/* Surf's Up (2007)(PC) */
if (sb->version == 0x00190005 && is_sb0) {
sb->section1_entry_size = 0x68;
sb->section2_entry_size = 0x74;
sb->external_flag_offset = 0x28; /* maybe 0x2c */
sb->channels_offset = 0x3c;
sb->sample_rate_offset = 0x40;
sb->num_samples_offset = 0x48;
sb->stream_type_offset = 0x5c;
sb->extra_name_offset = 0x58;
sb->has_extra_name_flag = 1;
return 1;
}
return 0;
}

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/*
const short wad_coef[16][2] =
{
@ -33,8 +34,7 @@ const short wad_coef[16] =
};
/* WAC - WAD - WAM (Beyond Good & Evil GC/PS2/Xbox/Wii) */
/* Note: A "Flat Layout" has no interleave */
/* WAC/WAD/WAM/WAA - from Beyond Good & Evil (PS2/Xbox/GC/Wii) */
VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
@ -56,7 +56,7 @@ VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) {
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */
read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */
read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt\0x20" */
read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt " */
read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */
goto fail;
@ -84,11 +84,11 @@ VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) {
switch((uint16_t)read_16bitLE(0x14,streamFile)) {
case 0x0069: // XBOX IMA ADPCM
start_offset = 0x2E;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/36/channel_count*64;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x2A,streamFile), channel_count);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/36/channel_count*64;
vgmstream->loop_end_sample = xbox_ima_bytes_to_samples(read_32bitLE(0x2A,streamFile),channel_count);
}
break;
case 0xFFFF: // PS2 ADPCM
@ -154,7 +154,7 @@ VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) {
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
if (vgmstream->coding_type == coding_XBOX) {
if (vgmstream->coding_type == coding_XBOX_IMA) {
/* xbox interleaving is a little odd */
vgmstream->ch[i].channel_start_offset=start_offset;
} else {

View File

@ -1,68 +1,50 @@
#include "meta.h"
#include "../util.h"
/*
WVS (found in Metal Arms - Glitch in the System)
XBOX and GameCube
*/
#include "../coding/coding.h"
/* WVS - found in Metal Arms - Glitch in the System (Xbox) */
VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag=0;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("wvs",filename_extension(filename))) goto fail;
if((read_16bitLE(0x0C,streamFile)!=0x69) &&
(read_16bitLE(0x08,streamFile)!=0x4400) &&
(read_32bitLE(0x0,streamFile)!=get_streamfile_size(streamFile)+0x20))
/* check extension */
if (!check_extensions(streamFile,"wvs"))
goto fail;
/* Loop seems to be set if offset(0x0A) == 0x472C */
loop_flag = (read_16bitLE(0x0A,streamFile)==0x472C);
if (read_16bitLE(0x0C,streamFile) != 0x69 && /* codec */
read_16bitLE(0x08,streamFile) != 0x4400)
goto fail;
/* Always stereo files */
channel_count=read_16bitLE(0x0E,streamFile);
start_offset = 0x20;
data_size = read_32bitLE(0x00,streamFile);
loop_flag = (read_16bitLE(0x0a,streamFile) == 0x472C); /* loop seems to be like this */
channel_count = read_16bitLE(0x0e,streamFile); /* always stereo files */
if (data_size + start_offset != get_streamfile_size(streamFile))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* allways 2 channels @ 44100 Hz */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(0,streamFile) / 36 * 64 / vgmstream->channels;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_WVS;
if(loop_flag) {
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
}
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0x20;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -194,11 +194,12 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
break;
case IMA: /* common */
/* slightly modified MS IMA with interleaved sub-blocks and LE/BE header */
/* slightly modified XBOX-IMA with interleaved sub-blocks and LE/BE header */
/* Wwise uses common codecs (ex. 0x0002 MSADPCM) so this parser should go AFTER riff.c avoid misdetection */
if (ww.bits_per_sample != 4) goto fail;
if (ww.block_align != 0x24 * ww.channels) goto fail;
vgmstream->coding_type = coding_WWISE_IMA;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = ww.block_align;
@ -207,7 +208,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
if (ww.truncated) /* enough to get real samples */
ww.data_size = ww.file_size - ww.data_offset;
vgmstream->num_samples = ms_ima_bytes_to_samples(ww.data_size, ww.block_align, ww.channels);
vgmstream->num_samples = xbox_ima_bytes_to_samples(ww.data_size, ww.channels);
break;
#ifdef VGM_USE_VORBIS

View File

@ -58,11 +58,11 @@ VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) {
goto fail;
vgmstream->sample_rate = read_32bitLE(0x58, streamFile);
vgmstream->num_samples = ms_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), read_16bitLE(0x60, streamFile), channel_count);
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), channel_count);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
break;

View File

@ -29,8 +29,8 @@ VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile) {
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_16bitLE(0x06,streamFile) & 0xffff;
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_matx_blocked;
vgmstream->meta_type = meta_XBOX_MATX;

View File

@ -1,62 +1,37 @@
#include "meta.h"
#include "../util.h"
/* WAVM
WAVM is an headerless format which can be found on XBOX
known extensions : WAVM
2008-05-23 - Fastelbja : First version ...
*/
#include "../coding/coding.h"
/* WAVM - headerless format which can be found on XBOX */
VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset = 0;
int loop_flag, channel_count;
int loop_flag=0;
int channel_count;
int i;
/* check extension */
if (!check_extensions(streamFile,"wavm"))
goto fail;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("wavm",filename_extension(filename))) goto fail;
/* No loop on wavm */
start_offset = 0;
loop_flag = 0;
/* Always stereo files */
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* allways 2 channels @ 44100 Hz */
vgmstream->channels = 2;
vgmstream->sample_rate = 44100;
vgmstream->num_samples = xbox_ima_bytes_to_samples(get_streamfile_size(streamFile), vgmstream->channels);
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) / 36 * 64 / vgmstream->channels);
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_WAVM;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,65 +1,44 @@
#include "meta.h"
#include "../util.h"
/* XMU
XMU (found in Alter Echo)
*/
#include "../coding/coding.h"
/* XMU- found in Alter Echo (Xbox) */
VGMSTREAM * init_vgmstream_xbox_xmu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
size_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag=0;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xmu",filename_extension(filename))) goto fail;
if((read_32bitBE(0x00,streamFile)!=0x584D5520) &&
(read_32bitBE(0x08,streamFile)!=0x46524D54))
/* check extension */
if (!check_extensions(streamFile,"xmu"))
goto fail;
/* No Loop found atm */
loop_flag = read_8bit(0x16,streamFile);;
if (read_32bitBE(0x00,streamFile) != 0x584D5520 && /* "XMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
goto fail;
/* Always stereo files */
channel_count=read_8bit(0x14,streamFile);
start_offset = 0x800;
channel_count=read_8bit(0x14,streamFile); /* always stereo files */
loop_flag = read_8bit(0x16,streamFile); /* no Loop found atm */
data_size = read_32bitLE(0x7FC,streamFile); /* next to "DATA" */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(0x7FC,streamFile) / 36 * 64 / vgmstream->channels;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_XMU;
if(loop_flag) {
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
}
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0x800;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,72 +1,52 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* XVAS
XVAS (found in TMNT 2 & TMNT 3))
*/
#include "../coding/coding.h"
/* XVAS - found in TMNT 2 & TMNT 3 (Xbox) */
VGMSTREAM * init_vgmstream_xbox_xvas(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag=0;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xvas",filename_extension(filename))) goto fail;
if((read_32bitLE(0x00,streamFile)!=0x69) &&
(read_32bitLE(0x08,streamFile)!=0x48))
/* check extension */
if (!check_extensions(streamFile,"xvas"))
goto fail;
/* No Loop found atm */
loop_flag = (read_32bitLE(0x14,streamFile)==read_32bitLE(0x24,streamFile));
if (read_32bitLE(0x00,streamFile) != 0x69 && /* codec */
read_32bitLE(0x08,streamFile) != 0x48) /* block size (probably 0x24 for mono) */
goto fail;
/* Always stereo files */
channel_count=read_32bitLE(0x04,streamFile);
start_offset = 0x800;
channel_count = read_32bitLE(0x04,streamFile); /* always stereo files */
loop_flag = (read_32bitLE(0x14,streamFile) == read_32bitLE(0x24,streamFile));
data_size = read_32bitLE(0x24,streamFile);
data_size -= (data_size / 0x20000) * 0x20; /* blocks of 0x20000 with padding */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x0c,streamFile);
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(0x24,streamFile);
vgmstream->num_samples -= ((vgmstream->num_samples/0x20000)*0x20);
vgmstream->num_samples = vgmstream->num_samples / 36 * 64 / vgmstream->channels;
vgmstream->layout_type = layout_xvas_blocked;
vgmstream->meta_type = meta_XBOX_XVAS;
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
if(loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile);
vgmstream->loop_start_sample -= ((vgmstream->loop_start_sample/0x20000)*0x20);
vgmstream->loop_start_sample = vgmstream->loop_start_sample / 36 * 64 / vgmstream->channels;
size_t loop_size = read_32bitLE(0x10,streamFile);
loop_size -= (loop_size / 0x20000) * 0x20;
vgmstream->loop_start_sample = xbox_ima_bytes_to_samples(loop_size, vgmstream->channels);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0x800;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_xvas_blocked;
vgmstream->meta_type = meta_XBOX_XVAS;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
xvas_block_update(0x800,vgmstream);
xvas_block_update(start_offset,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,97 +1,82 @@
#include "meta.h"
#include "../util.h"
/* XWAV
XWAV use the common RIFF/WAVE format with Codec ID = 0x0069
It has been renamed to xwav to avoid vgmstream to handle all RIFF/WAV format
known extensions : XWAV
2008-05-24 - Fastelbja : First version ...
*/
#include "../coding/coding.h"
/* XWAV - renamed WAV with XBOX-IMA
* (could be parsed as RIFF/.lwav but has a custom loop chunk and multichannel) */
VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag=0;
int channel_count;
int loop_flag, channel_count;
off_t start_offset;
int i,j=0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xwav",filename_extension(filename))) goto fail;
/* Check for headers */
if(!((read_32bitBE(0x00,streamFile)==0x52494646) &&
(read_32bitBE(0x08,streamFile)==0x57415645) &&
(read_32bitBE(0x0C,streamFile)==0x666D7420) &&
(read_16bitLE(0x14,streamFile)==0x0069)))
/* check extension */
if (!check_extensions(streamFile,"xwav"))
goto fail;
/* No loop on wavm */
if(read_32bitBE(0x28,streamFile)==0x77736D70)
loop_flag = 1;
else
loop_flag = 0;
/* check for headers */
if(!((read_32bitBE(0x00,streamFile) == 0x52494646) && /* "RIFF" */
(read_32bitBE(0x08,streamFile) == 0x57415645) && /* "WAVE" */
(read_32bitBE(0x0C,streamFile) == 0x666D7420) && /* "fmt " */
(read_16bitLE(0x14,streamFile) == 0x0069))) /* codec */
goto fail;
/* Always stereo files */
/* loop chunk found on Koei/Omega Force games [Crimson Sea, Dynasty Warriors 5] */
loop_flag = (read_32bitBE(0x28,streamFile) == 0x77736D70); /* "wsmp" */
channel_count = read_16bitLE(0x16,streamFile);
/* search for "data" */
start_offset = 0x1C;
do {
if (read_32bitBE(start_offset,streamFile)==0x64617461)
break;
start_offset += 0x04;
} while (start_offset < (off_t)get_streamfile_size(streamFile));
if (start_offset >= (off_t)get_streamfile_size(streamFile))
goto fail;
start_offset += 0x04;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* hack for loop wave found on Dynasty warriors */
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset,streamFile), vgmstream->channels);
vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x4C,streamFile);
vgmstream->loop_end_sample = vgmstream->loop_start_sample + read_32bitLE(0x50,streamFile);
}
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
/* search for "data" */
start_offset=0x1C;
do {
if(read_32bitBE(start_offset,streamFile)==0x64617461)
break;
start_offset+=4;
} while (start_offset<(off_t)get_streamfile_size(streamFile));
if(start_offset>=(off_t)get_streamfile_size(streamFile))
goto fail;
start_offset+=4;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(start_offset,streamFile) / 36 * 64 / vgmstream->channels;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_RIFF;
/* open the file for reading by each channel */
//if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
// goto fail;
//custom init
{
if(channel_count>2) {
for (i=0;i<channel_count;i++,j++) {
if((j&2) && (i!=0)) {
j=0;
start_offset+=36*2;
int i, ch;
char filename[PATH_LIMIT];
streamFile->get_name(streamFile,filename,sizeof(filename));
if (channel_count > 2) { /* multichannel interleaved init */
for (i=0, ch=0;i<channel_count;i++,ch++) {
if ((ch&2) && (i!=0)) {
ch = 0;
start_offset += 0x24*2;
}
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = start_offset+4;
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x24);
vgmstream->ch[i].offset = start_offset + 0x04;
if (!vgmstream->ch[i].streamfile) goto fail;
}
} else {
}
else {
for (i=0; i < channel_count; i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = start_offset+4;
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x24);
vgmstream->ch[i].offset = start_offset + 0x04;
if (!vgmstream->ch[i].streamfile) goto fail;
}
@ -100,8 +85,7 @@ VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile) {
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -5,9 +5,10 @@
VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count;
int flags, codec, sample_rate, block_size, bps;
size_t xnb_size, data_size;
int loop_flag = 0, channel_count, num_samples = 0, loop_start = 0, loop_end = 0;
int big_endian, flags, codec, sample_rate, block_size, bps;
size_t data_size;
char platform;
/* check extension, case insensitive */
@ -17,65 +18,78 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
/* check header */
if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */
goto fail;
/* 0x04: platform: w = Microsoft Windows, m = Windows Phone 7, x = Xbox 360, 'a' = Android */
/* XNA Studio platforms: 'w' = Windows, 'm' = Windows Phone 7, 'x' = X360
* MonoGame extensions: 'i' = iOS, 'a' = Android, 'X' = MacOSX, 'P': PS4, etc */
platform = read_8bit(0x03,streamFile);
big_endian = (platform == 'x');
if (read_8bit(0x04,streamFile) != 0x05) /* XNA 4.0 version only */
goto fail;
flags = read_8bit(0x05,streamFile);
if (flags & 0x80) goto fail; /* compressed with XMemCompress */
//if (flags & 0x01) goto fail; /* XMA/big endian flag? */
//if (flags & 0x01) goto fail; /* "HiDef profile" content (no actual difference) */
if (flags & 0x80) goto fail; /* compressed with LZX/XMemCompress (at 0x0a is decompressed size) */
if (flags & 0x40) goto fail; /* compressed with LZ4, MonoGame extension [ex. Square Heroes (PS4)] */
/* full size */
if (read_32bitLE(0x06,streamFile) != get_streamfile_size(streamFile))
goto fail;
/* "check for truncated XNB" (???) */
xnb_size = read_32bitLE(0x06,streamFile);
if (get_streamfile_size(streamFile) < xnb_size) goto fail;
/* XNB contains "type reader" class references to parse "shared resource" data (can be any implemented filetype) */
{
char reader_name[255+1];
off_t current_chunk = 0xa;
off_t current_offset = 0x0a;
int reader_string_len;
uint32_t fmt_chunk_size;
const char * type_sound = "Microsoft.Xna.Framework.Content.SoundEffectReader"; /* partial "fmt" chunk or XMA */
//const char * type_song = "Microsoft.Xna.Framework.Content.SongReader"; /* just references a companion .wma */
/* type reader count, accept only one for now */
if (read_8bit(current_chunk++, streamFile) != 1)
if (read_8bit(current_offset++, streamFile) != 1)
goto fail;
reader_string_len = read_8bit(current_chunk++, streamFile); /* doesn't count null */
reader_string_len = read_8bit(current_offset++, streamFile); /* doesn't count null */
if (reader_string_len > 255) goto fail;
/* check SoundEffect type string */
if (read_string(reader_name,reader_string_len+1,current_chunk,streamFile) != reader_string_len)
if (read_string(reader_name,reader_string_len+1,current_offset,streamFile) != reader_string_len)
goto fail;
if ( strcmp(reader_name, type_sound) != 0 )
goto fail;
current_chunk += reader_string_len + 1;
current_chunk += 4; /* reader version */
current_offset += reader_string_len + 1;
current_offset += 4; /* reader version */
/* shared resource count */
if (read_8bit(current_chunk++, streamFile) != 1)
if (read_8bit(current_offset++, streamFile) != 1)
goto fail;
/* shared resource: partial "fmt" chunk */
fmt_chunk_size = read_32bitLE(current_chunk, streamFile);
current_chunk += 4;
fmt_chunk_size = read_32bitLE(current_offset, streamFile);
current_offset += 4;
{
codec = read_16bitLE(current_chunk+0x00, streamFile);
channel_count = read_16bitLE(current_chunk+0x02, streamFile);
sample_rate = read_32bitLE(current_chunk+0x04, streamFile);
block_size = read_16bitLE(current_chunk+0x0c, streamFile);
bps = read_16bitLE(current_chunk+0x0e, streamFile);
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
int16_t (*read_16bit)(off_t,STREAMFILE*) = big_endian ? read_16bitBE : read_16bitLE;
codec = read_16bit(current_offset+0x00, streamFile);
channel_count = read_16bit(current_offset+0x02, streamFile);
sample_rate = read_32bit(current_offset+0x04, streamFile);
block_size = read_16bit(current_offset+0x0c, streamFile);
bps = read_16bit(current_offset+0x0e, streamFile);
if (codec == 0x166) {
xma2_parse_fmt_chunk_extra(streamFile, current_offset, &loop_flag, &num_samples, &loop_start, &loop_end, big_endian);
}
}
current_chunk += fmt_chunk_size;
current_offset += fmt_chunk_size;
data_size = read_32bitLE(current_chunk, streamFile);
current_chunk += 4;
data_size = read_32bitLE(current_offset, streamFile);
current_offset += 4;
start_offset = current_chunk;
start_offset = current_offset;
}
@ -87,14 +101,14 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_XNB;
switch (codec) {
case 0x01:
case 0x01: /* Dragon's Blade (Android) */
vgmstream->coding_type = bps == 8 ? coding_PCM8_U_int : coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = block_size / channel_count;
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, bps);
break;
case 0x02:
case 0x02: /* White Noise Online (PC) */
vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = block_size;
@ -108,6 +122,29 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, block_size, channel_count);
break;
#ifdef VGM_USE_FFMPEG
case 0x166: { /* Terraria (X360) */
uint8_t buf[0x100];
int32_t bytes, block_size, block_count;
block_size = 0x10000; /* guessed */
block_count = data_size / block_size + (data_size % block_size ? 1 : 0);
bytes = ffmpeg_make_riff_xma2(buf,0x100, num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
break;
}
#endif
default:
VGM_LOG("XNB: unknown codec 0x%x\n", codec);
goto fail;

View File

@ -295,11 +295,11 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
}
}
else if (xwb.version <= XACT1_1_MAX && xwb.codec == XBOX_ADPCM) {
xwb.block_align = 0x24 * xwb.channels;
xwb.num_samples = ms_ima_bytes_to_samples(xwb.stream_size, xwb.block_align, xwb.channels);
xwb.block_align = 0x24 * xwb.channels; /* not really needed... */
xwb.num_samples = xbox_ima_bytes_to_samples(xwb.stream_size, xwb.channels);
if (xwb.loop_flag) {
xwb.loop_start_sample = ms_ima_bytes_to_samples(xwb.loop_start, xwb.block_align, xwb.channels);
xwb.loop_end_sample = ms_ima_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.block_align, xwb.channels);
xwb.loop_start_sample = xbox_ima_bytes_to_samples(xwb.loop_start, xwb.channels);
xwb.loop_end_sample = xbox_ima_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.channels);
}
}
else if (xwb.version <= XACT2_2_MAX && xwb.codec == MS_ADPCM && xwb.loop_flag) {
@ -367,7 +367,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
break;
case XBOX_ADPCM: /* Silent Hill 4 (Xbox) */
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
break;
@ -798,7 +798,6 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head
/* get name offset */
for (i = start_sound; i < xsb.xsb_sounds_count; i++) {
xsb_sound *s = &(xsb.xsb_sounds[i]);
VGM_LOG("wa=%i, sel=%i, si=%i vs ti=%i\n", s->wavebank, cfg__selected_wavebank, s->stream_index, target_stream);
if (s->wavebank == cfg__selected_wavebank-1
&& s->stream_index == target_stream-1){
name_offset = s->name_offset;

View File

@ -15,8 +15,11 @@
#include <sys/types.h>
#include "streamtypes.h"
#include "util.h"
#if defined(ANDROID)
#include <unistd.h>
#endif
#if defined(__MSVCRT__) || defined(_MSC_VER)
#if (defined(__MSVCRT__) || defined(_MSC_VER)) && !defined(ANDROID)
#include <io.h>
#define fseeko fseek
#define ftello ftell

View File

@ -265,7 +265,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_adsc,
init_vgmstream_ngc_dsp_mpds,
init_vgmstream_dsp_str_ig,
init_vgmstream_psx_mgav,
init_vgmstream_ea_swvr,
init_vgmstream_ngc_dsp_sth_str1,
init_vgmstream_ngc_dsp_sth_str2,
init_vgmstream_ngc_dsp_sth_str3,
@ -968,7 +968,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
case layout_thp_blocked:
case layout_filp_blocked:
case layout_blocked_ivaud:
case layout_psx_mgav_blocked:
case layout_blocked_ea_swvr:
case layout_ps2_adm_blocked:
case layout_dsp_bdsp_blocked:
case layout_tra_blocked:
@ -1010,11 +1010,17 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_CRI_ADX_enc_8:
case coding_CRI_ADX_enc_9:
return (vgmstream->interleave_block_size - 2) * 2;
case coding_L5_555:
return 32;
case coding_NGC_DSP:
case coding_NGC_DSP_subint:
return 14;
case coding_NGC_AFC:
return 16;
case coding_NGC_DTK:
return 28;
case coding_G721:
return 1;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
@ -1052,12 +1058,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_NWA5:
case coding_SASSC:
return 1;
case coding_NDS_IMA:
case coding_DAT4_IMA:
return (vgmstream->interleave_block_size-4)*2;
case coding_NGC_DTK:
return 28;
case coding_G721:
case coding_IMA:
case coding_DVI_IMA:
case coding_SNDS_IMA:
@ -1067,22 +1068,36 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_IMA_int:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
case coding_AICA:
return 2;
case coding_NGC_AFC:
return 16;
case coding_XBOX_IMA:
case coding_XBOX_IMA_int:
case coding_FSB_IMA:
return 64;
case coding_APPLE_IMA4:
return 64;
case coding_MS_IMA:
case coding_REF_IMA:
return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
case coding_RAD_IMA:
case coding_WWISE_IMA:
return (vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels;
case coding_NDS_IMA:
case coding_DAT4_IMA:
return (vgmstream->interleave_block_size - 0x04) * 2;
case coding_AWC_IMA:
return (0x800 - 0x04) * 2;
case coding_RAD_IMA_mono:
return 32;
case coding_XA:
case coding_PSX:
case coding_PSX_badflags:
case coding_PSX_bmdx:
case coding_HEVAG:
case coding_XA:
return 28;
case coding_PSX_cfg:
return (vgmstream->interleave_block_size - 1) * 2; /* decodes 1 byte into 2 bytes */
case coding_XBOX:
case coding_XBOX_int:
case coding_FSB_IMA:
return 64;
case coding_EA_XA:
case coding_EA_XA_int:
case coding_EA_XA_V2:
@ -1090,24 +1105,20 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return 28;
case coding_EA_XAS:
return 128;
case coding_WS:
/* only works if output sample size is 8 bit, which always is for WS ADPCM */
return vgmstream->ws_output_size;
case coding_MSADPCM:
return (vgmstream->interleave_block_size-(7-1)*vgmstream->channels)*2/vgmstream->channels;
case coding_APPLE_IMA4:
return 64;
case coding_MS_IMA:
case coding_RAD_IMA:
case coding_WWISE_IMA:
case coding_REF_IMA:
return (vgmstream->interleave_block_size-4*vgmstream->channels)*2/vgmstream->channels;
case coding_AWC_IMA:
return (0x800-4)*2;
case coding_RAD_IMA_mono:
return 32;
case coding_WS: /* only works if output sample size is 8 bit, which always is for WS ADPCM */
return vgmstream->ws_output_size;
case coding_AICA:
return 2;
case coding_NDS_PROCYON:
return 30;
case coding_L5_555:
return 32;
case coding_LSF:
return 54;
#ifdef VGM_USE_G7221
case coding_G7221C:
return 32000/50;
@ -1120,18 +1131,15 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
#endif
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
{
if (vgmstream->codec_data) {
ffmpeg_codec_data *data = (ffmpeg_codec_data*)vgmstream->codec_data;
if (data) {
/* must know the full block size for edge loops */
return data->sampleBufferBlock;
return data->sampleBufferBlock; /* must know the full block size for edge loops */
}
else {
return 0;
}
break;
#endif
case coding_LSF:
return 54;
case coding_MTAF:
return 128*2;
case coding_MTA2:
@ -1168,17 +1176,23 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_CRI_ADX_enc_8:
case coding_CRI_ADX_enc_9:
return vgmstream->interleave_block_size;
case coding_L5_555:
return 18;
case coding_NGC_DSP:
return 0x08;
case coding_NGC_DSP_subint:
return 0x08 * vgmstream->channels;
case coding_NGC_AFC:
return 0x09;
case coding_NGC_DTK:
return 0x20;
case coding_G721:
return 0;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
case coding_PCM16_int:
return 2;
return 0x02;
case coding_PCM8:
case coding_PCM8_U:
case coding_PCM8_int:
@ -1187,9 +1201,10 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_ULAW:
case coding_ULAW_int:
case coding_ALAW:
return 1;
return 0x01;
case coding_PCMFLOAT:
return 4;
return 0x04;
case coding_SDX2:
case coding_SDX2_int:
case coding_CBD2:
@ -1200,7 +1215,14 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_NWA4:
case coding_NWA5:
case coding_SASSC:
return 1;
return 0x01;
case coding_IMA:
case coding_IMA_int:
case coding_DVI_IMA:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
return 0x01;
case coding_MS_IMA:
case coding_RAD_IMA:
case coding_NDS_IMA:
@ -1212,30 +1234,28 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 0x800;
case coding_RAD_IMA_mono:
return 0x14;
case coding_NGC_DTK:
return 32;
case coding_G721:
case coding_SNDS_IMA:
case coding_OTNS_IMA:
return 0;
case coding_UBI_IMA: /* variable (PCM then IMA) */
return 0;
case coding_NGC_AFC:
return 9;
case coding_XBOX_IMA:
case coding_XBOX_IMA_int:
case coding_FSB_IMA:
return 0x24;
case coding_APPLE_IMA4:
return 0x22;
case coding_XA:
return 0x0e*vgmstream->channels;
case coding_PSX:
case coding_PSX_badflags:
case coding_PSX_bmdx:
case coding_HEVAG:
case coding_NDS_PROCYON:
return 16;
return 0x10;
case coding_PSX_cfg:
return vgmstream->interleave_block_size;
case coding_XA:
return 14*vgmstream->channels;
case coding_XBOX:
case coding_XBOX_int:
case coding_FSB_IMA:
return 36;
case coding_EA_XA:
return 0x1E;
case coding_EA_XA_int:
@ -1246,20 +1266,20 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 0; /* variable (ADPCM frames of 0x0f or PCM frames of 0x3d) */
case coding_EA_XAS:
return 0x4c*vgmstream->channels;
case coding_MSADPCM:
return vgmstream->interleave_block_size;
case coding_WS:
return vgmstream->current_block_size;
case coding_IMA:
case coding_IMA_int:
case coding_DVI_IMA:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
return 0x01;
case coding_AICA:
return 1;
case coding_APPLE_IMA4:
return 34;
return 0x01;
case coding_NDS_PROCYON:
return 0x10;
case coding_L5_555:
return 0x12;
case coding_LSF:
return 28;
return 0x1C;
#ifdef VGM_USE_G7221
case coding_G7221C:
case coding_G7221:
@ -1273,7 +1293,6 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
#endif
case coding_MSADPCM:
case coding_MTAF:
return vgmstream->interleave_block_size;
case coding_MTA2:
@ -1286,7 +1305,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_ATRAC9:
return 0; /* varies with config data, usually 0x100-200 */
#endif
default:
default: /* Vorbis, MPEG, ACM, etc */
return 0;
}
}
@ -1475,14 +1494,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_XBOX:
case coding_XBOX_IMA:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do,chan);
}
break;
case coding_XBOX_int:
case coding_XBOX_IMA_int:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_xbox_ima_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,

View File

@ -134,8 +134,8 @@ typedef enum {
coding_DVI_IMA_int, /* DVI IMA ADPCM (mono/interleave, high nibble first) */
coding_3DS_IMA, /* 3DS IMA ADPCM */
coding_MS_IMA, /* Microsoft IMA ADPCM */
coding_XBOX, /* XBOX IMA ADPCM */
coding_XBOX_int, /* XBOX IMA ADPCM (interleaved) */
coding_XBOX_IMA, /* XBOX IMA ADPCM */
coding_XBOX_IMA_int, /* XBOX IMA ADPCM (interleaved/mono) */
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */
coding_RAD_IMA, /* Radical IMA ADPCM */
@ -244,7 +244,7 @@ typedef enum {
layout_gsb_blocked,
layout_thp_blocked,
layout_filp_blocked,
layout_psx_mgav_blocked,
layout_blocked_ea_swvr,
layout_ps2_adm_blocked,
layout_dsp_bdsp_blocked,
layout_mxch_blocked,
@ -551,7 +551,7 @@ typedef enum {
meta_DSP_DDSP, /* Various (2 dsp files stuck together */
meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */
meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */
meta_PSX_MGAV, /* Future Cop L.A.P.D. */
meta_EA_SWVR, /* Future Cop L.A.P.D., Freekstyle */
meta_NGC_DSP_STH_STR, /* SpongeBob Squarepants (NGC), Taz Wanted (NGC), Cubix (NGC), Tak (WII)*/
meta_PS2_B1S, /* 7 Wonders of the ancient world */
meta_PS2_WAD, /* The golden Compass */
@ -666,6 +666,7 @@ typedef enum {
meta_XWC, /* Starbreeze games */
meta_SQEX_SAB, /* Square-Enix newest middleware (sound) */
meta_SQEX_MAB, /* Square-Enix newest middleware (music) */
meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */
#ifdef VGM_USE_MP4V2
meta_MP4, /* AAC (iOS) */