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 */
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;
/* 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, 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);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
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;
/* 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;
//stream->adpcm_history1_32 = hist1;
//stream->adpcm_step_index = step_index;
}
/* MS IMA with fixed frame size and custom multichannel nibble layout.
/* 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(offset-stream->offset==32+3) // ??
stream->offset+=36;
if (channelspacing==1) { /* mono */
if (offset-stream->offset == 32+3) // ??
stream->offset += 0x24;
} else {
if(offset-stream->offset==64+(4*(channel%2))+3) // ??
stream->offset+=36*channelspacing;
if (offset-stream->offset == 64+(4*(channel%2))+3) // ??
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) {
@ -45,9 +40,9 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples;
}
if (channel_count == 1){
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
} else if (channel_count == 2){
} else if (channel_count == 2) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile);
}
@ -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,7 +232,8 @@ 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;
vgmstream->interleave_smallblock_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 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++) {
if (read_dsp_header(&header, header_size * i, streamFile)) goto fail;
@ -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 (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);
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 */
/* 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;
}
}
return vgmstream;
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,72 +938,44 @@ 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, 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 */
/* check extension */
if (!check_extensions(streamFile,"rsd"))
goto fail;
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);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
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;
}
}
return vgmstream;
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
@ -185,7 +226,7 @@ VGM_LOG("2\n");
#endif
#ifdef VGM_USE_MPEG
case 0x06: { /* MSF subfile (MPEG mode) [Dragon Quest Builders (PS3)] */
case 0x06: { /* MSF subfile (MPEG mode) [Dragon Quest Builders (PS3)] */
mpeg_codec_data *mpeg_data = NULL;
mpeg_custom_config cfg = {0};
@ -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,10 +50,10 @@ 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?) */
codec = read_8bit (header_offset+0x04,streamHeader);
channels = read_8bit (header_offset+0x05,streamHeader);
sample_rate = read_32bitLE(header_offset+0x08,streamHeader);
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);
/* 0x0c(4): unknown size? (0x4000/0x3999/0x3333/etc, not related to extra data) */
/* 0x10(4): ? + volume? + pan? (can be 0 for music) */
num_samples = read_32bitLE(header_offset+0x14,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

@ -78,7 +78,8 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
switch(((uint64_t)platform << 32) | type) {
case 0x57696E2070636D20: /* "Win pcm " */
case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4)*/
case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4) */
case 0x4E78202070636D20: /* "Nx pcm " (Nx = Switch) */
/* chunks: "data" */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
@ -162,7 +163,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
#endif
#ifdef VGM_USE_ATRAC9
case 0x5649544161743920: { /*"VITAat9 "*/
case 0x5649544161743920: { /* "VITAat9 " */
/* chunks: "fact" (equivalent to a RIFF "fact", num_samples + skip_samples), "data" */
atrac9_config cfg = {0};
@ -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,146 +1,146 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/*
const short wad_coef[16][2] =
{
{0x4002,0x2003},
{0x2016,0xc600},
{0xC600,0x98ab},
{0x96bf,0x29c5},
{0x2003,0x0081},
{0x0e00,0x2004},
{0x8e01,0xc500},
{0x70bf,0x8128},
{0x288e,0xc600},
{0x016e,0x0e5b},
{0xbe20,0x2003},
{0x03c6,0xc600},
{0x0048,0xe85a},
{0xbe28,0x28c6},
{0xc600,0x00F6},
{0xbeab,0x5520}
{0x4002,0x2003},
{0x2016,0xc600},
{0xC600,0x98ab},
{0x96bf,0x29c5},
{0x2003,0x0081},
{0x0e00,0x2004},
{0x8e01,0xc500},
{0x70bf,0x8128},
{0x288e,0xc600},
{0x016e,0x0e5b},
{0xbe20,0x2003},
{0x03c6,0xc600},
{0x0048,0xe85a},
{0xbe28,0x28c6},
{0xc600,0x00F6},
{0xbeab,0x5520}
};*/
const short wad_coef[16] =
{
0x04ab, 0xfced,
0x0789, 0xfedf,
0x09a2, 0xfae5,
0x0c90, 0xfac1,
0x084d, 0xfaa4,
0x0982, 0xfdf7,
0x0af6, 0xfafa,
0x0be6, 0xfbf5
0x04ab, 0xfced,
0x0789, 0xfedf,
0x09a2, 0xfae5,
0x0c90, 0xfac1,
0x084d, 0xfaa4,
0x0982, 0xfdf7,
0x0af6, 0xfafa,
0x0be6, 0xfbf5
};
/* 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];
int i;
int i;
off_t start_offset;
int loop_flag;
int channel_count;
int coef1_start;
int coef2_start;
int second_channel_start = -1;
int channel_count;
int coef1_start;
int coef2_start;
int second_channel_start = -1;
// Check file extensions
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("waa",filename_extension(filename)) &&
strcasecmp("wac",filename_extension(filename)) &&
strcasecmp("wad",filename_extension(filename)) &&
strcasecmp("wam",filename_extension(filename))) goto fail;
strcasecmp("wac",filename_extension(filename)) &&
strcasecmp("wad",filename_extension(filename)) &&
strcasecmp("wam",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */
read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */
read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt\0x20" */
read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */
read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */
read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt " */
read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */
goto fail;
/* files don't contain looping information,
so the looping is not done depending on extension.
wam and waa contain ambient sounds and music, so often they contain
looped music. Change extension to wac or wad to make the sound non-looping.
*/
/* files don't contain looping information,
so the looping is not done depending on extension.
wam and waa contain ambient sounds and music, so often they contain
looped music. Change extension to wac or wad to make the sound non-looping.
*/
loop_flag = strcasecmp("wac",filename_extension(filename)) &&
strcasecmp("wad",filename_extension(filename));
strcasecmp("wad",filename_extension(filename));
channel_count = (uint16_t)read_16bitLE(0x16,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* Check what encoder is needed */
//FIXME: //PC version uses pcm, but which encoder?
/* Check what encoder is needed */
//FIXME: //PC version uses pcm, but which encoder?
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
vgmstream->meta_type = meta_WAA_WAC_WAD_WAM;
vgmstream->meta_type = meta_WAA_WAC_WAD_WAM;
vgmstream->layout_type = layout_none;
switch((uint16_t)read_16bitLE(0x14,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;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/36/channel_count*64;
}
start_offset = 0x2E;
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 = xbox_ima_bytes_to_samples(read_32bitLE(0x2A,streamFile),channel_count);
}
break;
case 0xFFFF: // PS2 ADPCM
start_offset = 0x2E;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
}
start_offset = 0x2E;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
}
second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+start_offset;
break;
case 0xFFFE: // GameCube/WII DSP
start_offset = 0x5C;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
}
if(read_16bitLE(0x24,streamFile)==0x00)//is a wii file with no coeff table
{
//FIXME: WII version of WAM/WAD/WAC need some coeff table from somewhere
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = wad_coef[i];
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = wad_coef[i];
}
goto fail;
}
else
{
second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+0x8A;
/* Retrieveing the coef tables */
coef1_start = 0x2E;
coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C;
start_offset = 0x5C;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
}
if(read_16bitLE(0x24,streamFile)==0x00)//is a wii file with no coeff table
{
//FIXME: WII version of WAM/WAD/WAC need some coeff table from somewhere
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = wad_coef[i];
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = wad_coef[i];
}
goto fail;
}
else
{
second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+0x8A;
/* Retrieveing the coef tables */
coef1_start = 0x2E;
coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C;
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile);
}
}
}
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile);
}
}
}
break;
default:
goto fail;
}
default:
goto fail;
}
@ -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;
/* check extension */
if (!check_extensions(streamFile,"wvs"))
goto fail;
if((read_16bitLE(0x0C,streamFile)!=0x69) &&
(read_16bitLE(0x08,streamFile)!=0x4400) &&
(read_32bitLE(0x0,streamFile)!=get_streamfile_size(streamFile)+0x20))
goto fail;
if (read_16bitLE(0x0C,streamFile) != 0x69 && /* codec */
read_16bitLE(0x08,streamFile) != 0x4400)
goto fail;
/* Loop seems to be set if offset(0x0A) == 0x472C */
loop_flag = (read_16bitLE(0x0A,streamFile)==0x472C);
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 */
/* Always stereo files */
channel_count=read_16bitLE(0x0E,streamFile);
/* build the VGMSTREAM */
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;
}
@ -75,7 +57,7 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -94,7 +76,7 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* fill in the vital statistics */
start_offset = 0x60;
if (channel_count == 1) {
@ -103,8 +85,8 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) {
vgmstream->sample_rate = 44100;
}
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/8/channel_count*14; //(read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14;
if (loop_flag) {

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 */
loop_flag = 0;
start_offset = 0;
loop_flag = 0;
channel_count = 2;
/* Always stereo files */
channel_count=2;
/* build the VGMSTREAM */
/* 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 */
if (!check_extensions(streamFile,"xmu"))
goto fail;
/* 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 && /* "XMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
goto fail;
if((read_32bitBE(0x00,streamFile)!=0x584D5520) &&
(read_32bitBE(0x08,streamFile)!=0x46524D54))
goto fail;
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" */
/* No Loop found atm */
loop_flag = read_8bit(0x16,streamFile);;
/* Always stereo files */
channel_count=read_8bit(0x14,streamFile);
/* build the VGMSTREAM */
/* 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 */
if (!check_extensions(streamFile,"xvas"))
goto fail;
/* 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 && /* codec */
read_32bitLE(0x08,streamFile) != 0x48) /* block size (probably 0x24 for mono) */
goto fail;
if((read_32bitLE(0x00,streamFile)!=0x69) &&
(read_32bitLE(0x08,streamFile)!=0x48))
goto fail;
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 */
/* No Loop found atm */
loop_flag = (read_32bitLE(0x14,streamFile)==read_32bitLE(0x24,streamFile));
/* Always stereo files */
channel_count=read_32bitLE(0x04,streamFile);
/* build the VGMSTREAM */
/* 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->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
if(loop_flag) {
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;
}
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->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_xvas_blocked;
vgmstream->meta_type = meta_XBOX_XVAS;
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;
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_open_stream(vgmstream, streamFile, start_offset))
goto fail;
if (!vgmstream->ch[i].streamfile) 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,107 +1,91 @@
#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 extension */
if (!check_extensions(streamFile,"xwav"))
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)))
goto fail;
/* 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;
/* No loop on wavm */
if(read_32bitBE(0x28,streamFile)==0x77736D70)
loop_flag = 1;
else
loop_flag = 0;
/* Always stereo files */
channel_count=read_16bitLE(0x16,streamFile);
/* build the VGMSTREAM */
/* 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 */
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->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);
}
/* 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));
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = start_offset+4;
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;
}
if (!vgmstream->ch[i].streamfile) goto fail;
}
} 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;
}
}
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
else {
for (i=0; i < channel_count; i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x24);
vgmstream->ch[i].offset = start_offset + 0x04;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
}
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:
{
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
if (data) {
/* must know the full block size for edge loops */
return data->sampleBufferBlock;
if (vgmstream->codec_data) {
ffmpeg_codec_data *data = (ffmpeg_codec_data*)vgmstream->codec_data;
return data->sampleBufferBlock; /* must know the full block size for edge loops */
}
else {
return 0;
}
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) */