Fix XMA gapless/looping/samples

fixes: standard, wem, xwc, xwb, xnb, xwx, rak, pk, txth, genh, seg, rsd, past, p3d, nub-xma, gtd, gsp, fsb, eaac, cxs, awc, aac
This commit is contained in:
bnnm 2018-11-18 17:01:31 +01:00
parent ef64889a28
commit 467ca19450
25 changed files with 172 additions and 145 deletions

View File

@ -110,6 +110,8 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) {
bytes = ffmpeg_make_riff_xma2(buf, 0x100, awc.num_samples, substream_size, layer_channels, awc.sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf, 0x100, awc.num_samples, substream_size, layer_channels, awc.sample_rate, block_count, block_size);
data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, substream_offset,substream_size); data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, substream_offset,substream_size);
xma_fix_raw_samples(data->layers[i], temp_streamFile, substream_offset,substream_size, 0, 0,0); /* samples are ok? */
close_streamfile(temp_streamFile); close_streamfile(temp_streamFile);
if (!data->layers[i]->codec_data) goto fail; if (!data->layers[i]->codec_data) goto fail;
} }
@ -128,6 +130,8 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) {
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, awc.stream_offset,awc.stream_size, 0, 0,0); /* samples are ok? */
} }
break; break;

View File

@ -849,6 +849,8 @@ static layered_layout_data* build_layered_eaaudiocore_eaxma(STREAMFILE *streamDa
data->layers[i]->coding_type = coding_FFmpeg; data->layers[i]->coding_type = coding_FFmpeg;
data->layers[i]->layout_type = layout_none; data->layers[i]->layout_type = layout_none;
xma_fix_raw_samples(data->layers[i], temp_streamFile, 0x00,stream_size, 0, 0,0); /* samples are ok? */
} }
#else #else
goto fail; goto fail;

View File

@ -363,6 +363,8 @@ VGMSTREAM * init_vgmstream_fsb(STREAMFILE *streamFile) {
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, fsb.stream_offset,fsb.stream_size, 0, 0,0); /* samples look ok */
break; break;
} }
#endif #endif

View File

@ -314,7 +314,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
break; break;
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x0A: {/* FMOD_SOUND_FORMAT_XMA [Dark Souls 2 (X360)] */ case 0x0A: {/* FMOD_SOUND_FORMAT_XMA [Minecraft Story Mode (X360)] */
uint8_t buf[0x100]; uint8_t buf[0x100];
int bytes, block_size, block_count; int bytes, block_size, block_count;
@ -323,9 +323,11 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, fsb5.stream_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, fsb5.stream_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, fsb5.stream_offset,fsb5.stream_size); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, fsb5.stream_offset,fsb5.stream_size);
if ( !vgmstream->codec_data ) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, fsb5.stream_offset,fsb5.stream_size, 0, 0,0); /* samples look ok */
break; break;
} }
#endif #endif

View File

@ -304,7 +304,6 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
else { else {
goto fail; goto fail;
} }
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size); ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
@ -313,8 +312,9 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* force encoder delay */ if (genh.codec == XMA1 || genh.codec == XMA2) {
if (genh.skip_samples_mode && genh.skip_samples >= 0) { xma_fix_raw_samples(vgmstream, streamFile, genh.start_offset,genh.data_size, 0, 0,0);
} else if (genh.skip_samples_mode && genh.skip_samples >= 0) { /* force encoder delay */
ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples); ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
} }

View File

@ -12,7 +12,7 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
int codec_id; int codec_id;
/* check extensions */ /* checks */
if (!check_extensions(streamFile,"gsb")) if (!check_extensions(streamFile,"gsb"))
goto fail; goto fail;
@ -116,14 +116,13 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
/* 0x00: fmt0x166 header (BE), 0x34: seek table */ /* 0x00: fmt0x166 header (BE), 0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, datasize, streamHeader, 1); bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, datasize, streamHeader, 1);
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,0); /* samples are ok */
break; break;
} }
#endif #endif

View File

@ -94,6 +94,8 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1);
break; break;
} }
#endif #endif

View File

@ -10,10 +10,9 @@ VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile) {
int num_samples, loop_start_sample, loop_end_sample; int num_samples, loop_start_sample, loop_end_sample;
/* check extension, case insensitive */ /* checks */
if ( !check_extensions(streamFile,"xma")) /* (probably meant to be .nub) */ if ( !check_extensions(streamFile,"xma")) /* (probably meant to be .nub) */
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x786D6100) /* "xma\0" */ if (read_32bitBE(0x00,streamFile) != 0x786D6100) /* "xma\0" */
goto fail; goto fail;
@ -55,19 +54,17 @@ VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile) {
} else { /* "fmt " */ } else { /* "fmt " */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1); bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, streamFile, 1);
} }
if (bytes <= 0) goto fail; vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);;
if ( !vgmstream->codec_data ) goto fail; if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1); /* samples needs adjustment */
} }
#else #else
goto fail; goto fail;
#endif #endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -11,11 +11,9 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) {
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
/* check extension, case insensitive */ /* checks */
if (!check_extensions(streamFile,"p3d")) if (!check_extensions(streamFile,"p3d"))
goto fail; goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x503344FF && /* "P3D"\FF (LE: PC) */ if (read_32bitBE(0x0,streamFile) != 0x503344FF && /* "P3D"\FF (LE: PC) */
read_32bitBE(0x0,streamFile) != 0xFF443350) /* \FF"D3P" (BE: PS3, X360) */ read_32bitBE(0x0,streamFile) != 0xFF443350) /* \FF"D3P" (BE: PS3, X360) */
goto fail; goto fail;
@ -164,12 +162,12 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) {
size_t bytes; size_t bytes;
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->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); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail; if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, 0, 1,1); /* samples needs adjustment */
break; break;
} }
#endif #endif

View File

@ -1025,13 +1025,15 @@ VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile) {
datasize = read_32bitBE(0x808, streamFile); datasize = read_32bitBE(0x808, streamFile);
bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, datasize); ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, datasize);
if (!ffmpeg_data) goto fail; if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* for some reason (dev trickery?) .rsd don't set skip in the bitstream, though they should */
//xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,0);
ffmpeg_set_skip_samples(ffmpeg_data, 512+64);
} }
#else #else
goto fail; goto fail;
@ -1053,13 +1055,15 @@ VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile) {
datasize = read_32bitBE(0x808, streamFile); datasize = read_32bitBE(0x808, streamFile);
bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, datasize); ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, datasize);
if (!ffmpeg_data) goto fail; if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* for some reason (dev trickery?) .rsd don't set skip in the bitstream, though they should */
//xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,0);
ffmpeg_set_skip_samples(ffmpeg_data, 512+64);
} }
#else #else
goto fail; goto fail;

View File

@ -92,6 +92,8 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok */
break; break;
} }
#endif #endif

View File

@ -334,23 +334,23 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */ case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */
ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[200]; uint8_t buf[200];
int32_t bytes; int32_t bytes;
/* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */ /* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1); bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1);
if (bytes <= 0) goto fail; ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size); vgmstream->num_samples = ffmpeg_data->totalSamples;
if (!ffmpeg_data) goto fail; vgmstream->loop_start_sample = loop_start;
vgmstream->codec_data = ffmpeg_data; vgmstream->loop_end_sample = loop_end;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ffmpeg_data->totalSamples; xma_fix_raw_samples(vgmstream, streamFile, start_offset,stream_size, 0, 0,0); /* samples are ok, loops? */
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
break; break;
} }

View File

@ -108,13 +108,17 @@ VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile) {
datasize = dataSize; datasize = dataSize;
bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize); ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, datasize, 0, 1,1);
if (loop_flag) { /* reapply adjusted samples */
vgmstream->loop_end_sample = vgmstream->num_samples;
}
} }
#else #else
goto fail; goto fail;

View File

@ -335,7 +335,6 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
else { else {
goto fail; goto fail;
} }
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, txth.start_offset,txth.data_size); ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
@ -344,8 +343,9 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* force encoder delay */ if (txth.codec == XMA1 || txth.codec == XMA2) {
if (txth.skip_samples_set) { xma_fix_raw_samples(vgmstream, streamFile, txth.start_offset,txth.data_size, 0, 0,0);
} else if (txth.skip_samples_set) { /* force encoder delay */
ffmpeg_set_skip_samples(ffmpeg_data, txth.skip_samples); ffmpeg_set_skip_samples(ffmpeg_data, txth.skip_samples);
} }

View File

@ -190,6 +190,8 @@ static VGMSTREAM * init_vgmstream_ubi_bao_main(ubi_bao_header * bao, STREAMFILE
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->stream_size = data_size; vgmstream->stream_size = data_size;
xma_fix_raw_samples(vgmstream, streamData, start_offset,data_size, 0, 0,0);
break; break;
} }

View File

@ -5,7 +5,7 @@
/* RAKI - Ubisoft audio format [Rayman Legends, Just Dance 2017 (multi)] */ /* RAKI - Ubisoft audio format [Rayman Legends, Just Dance 2017 (multi)] */
VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, off, fmt_offset; off_t start_offset, offset, fmt_offset;
size_t header_size, data_size; size_t header_size, data_size;
int big_endian; int big_endian;
int loop_flag, channel_count, block_align, bits_per_sample; int loop_flag, channel_count, block_align, bits_per_sample;
@ -15,22 +15,24 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* basic checks */ /* checks */
/* .rak: Just Dance 2017; .ckd: Rayman Legends (technically .wav.ckd/rak) */ /* .rak: Just Dance 2017
if (!check_extensions(streamFile,"rak,ckd")) goto fail; * .ckd: Rayman Legends (technically .wav.ckd/rak) */
if (!check_extensions(streamFile,"rak,ckd"))
goto fail;
/* some games (ex. Rayman Legends PS3) have a 32b file type before the RAKI data. However /* some games (ex. Rayman Legends PS3) have a 32b file type before the RAKI data. However
* offsets are absolute and expect the type exists, so it's part of the file and not an extraction defect. */ * offsets are absolute and expect the type exists, so it's part of the file and not an extraction defect. */
if ((read_32bitBE(0x00,streamFile) == 0x52414B49)) /* "RAKI" */ if ((read_32bitBE(0x00,streamFile) == 0x52414B49)) /* "RAKI" */
off = 0x0; offset = 0x00;
else if ((read_32bitBE(0x04,streamFile) == 0x52414B49)) /* type varies between platforms (0x09, 0x0b) so ignore */ else if ((read_32bitBE(0x04,streamFile) == 0x52414B49)) /* type varies between platforms (0x09, 0x0b) so ignore */
off = 0x4; offset = 0x04;
else else
goto fail; goto fail;
/* 0x04: version? (0x00, 0x07, 0x0a, etc); */ /* 0x04: version? (0x00, 0x07, 0x0a, etc); */
platform = read_32bitBE(off+0x08,streamFile); /* string */ platform = read_32bitBE(offset+0x08,streamFile); /* string */
type = read_32bitBE(off+0x0c,streamFile); /* string */ type = read_32bitBE(offset+0x0c,streamFile); /* string */
switch(platform) { switch(platform) {
case 0x57696920: /* "Wii " */ case 0x57696920: /* "Wii " */
@ -48,15 +50,15 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
break; break;
} }
header_size = read_32bit(off+0x10,streamFile); header_size = read_32bit(offset+0x10,streamFile);
start_offset = read_32bit(off+0x14,streamFile); start_offset = read_32bit(offset+0x14,streamFile);
/* 0x18: number of chunks */ /* 0x18: number of chunks */
/* 0x1c: unk */ /* 0x1c: unk */
/* the format has a chunk offset table, and the first one always "fmt" and points /* the format has a chunk offset table, and the first one always "fmt" and points
* to a RIFF "fmt" chunk (even for WiiU or PS3) */ * to a RIFF "fmt"-style chunk (even for WiiU or PS3) */
if (read_32bitBE(off+0x20,streamFile) != 0x666D7420) goto fail; /*"fmt "*/ if (read_32bitBE(offset+0x20,streamFile) != 0x666D7420) goto fail; /* "fmt " */
fmt_offset = read_32bit(off+0x24,streamFile); fmt_offset = read_32bit(offset+0x24,streamFile);
//fmt_size = read_32bit(off+0x28,streamFile); //fmt_size = read_32bit(off+0x28,streamFile);
loop_flag = 0; /* not seen */ loop_flag = 0; /* not seen */
@ -106,7 +108,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
/* we need to know if the file uses "datL" and is full-interleave */ /* we need to know if the file uses "datL" and is full-interleave */
if (channel_count > 1) { if (channel_count > 1) {
off_t chunk_off = off+ 0x20 + 0xc; /* after "fmt" */ off_t chunk_off = offset+ 0x20 + 0xc; /* after "fmt" */
while (chunk_off < header_size) { while (chunk_off < header_size) {
if (read_32bitBE(chunk_off,streamFile) == 0x6461744C) { /*"datL" found */ if (read_32bitBE(chunk_off,streamFile) == 0x6461744C) { /*"datL" found */
size_t chunk_size = read_32bit(chunk_off+0x8,streamFile); size_t chunk_size = read_32bit(chunk_off+0x8,streamFile);
@ -122,7 +124,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
{ {
/* get coef offsets; could check "dspL" and "dspR" chunks after "fmt " better but whatevs (only "dspL" if mono) */ /* get coef offsets; could check "dspL" and "dspR" chunks after "fmt " better but whatevs (only "dspL" if mono) */
off_t dsp_coefs = read_32bitBE(off+0x30,streamFile); /* after "dspL"; spacing is consistent but could vary */ off_t dsp_coefs = read_32bitBE(offset+0x30,streamFile); /* after "dspL"; spacing is consistent but could vary */
dsp_read_coefs(vgmstream,streamFile, dsp_coefs+0x1c, 0x60, big_endian); dsp_read_coefs(vgmstream,streamFile, dsp_coefs+0x1c, 0x60, big_endian);
/* dsp_coefs + 0x00-0x1c: ? (special coefs or adpcm history?) */ /* dsp_coefs + 0x00-0x1c: ? (special coefs or adpcm history?) */
} }
@ -149,15 +151,16 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
int bytes, block_count; int bytes, block_count;
block_count = data_size / block_align + (data_size % block_align ? 1 : 0); block_count = data_size / block_align + (data_size % block_align ? 1 : 0);
bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_align);
if (bytes <= 0) goto fail;
bytes = ffmpeg_make_riff_xma2(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_align);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail; if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(fmt_offset+0x18,streamFile); vgmstream->num_samples = read_32bit(fmt_offset+0x18,streamFile);
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* should apply to num_samples? */
break; break;
} }
#endif #endif
@ -199,7 +202,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
{ {
off_t chunk_offset = off + 0x20 + 0xc; /* after "fmt" */ off_t chunk_offset = offset + 0x20 + 0xc; /* after "fmt" */
while (chunk_offset < header_size) { while (chunk_offset < header_size) {
if (read_32bitBE(chunk_offset,streamFile) == 0x4164496E) { /*"AdIn" additional info */ if (read_32bitBE(chunk_offset,streamFile) == 0x4164496E) { /*"AdIn" additional info */
off_t adin_offset = read_32bitLE(chunk_offset+0x04,streamFile); off_t adin_offset = read_32bitLE(chunk_offset+0x04,streamFile);

View File

@ -36,9 +36,9 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_VAWX; vgmstream->meta_type = meta_VAWX;
switch(codec) { switch(codec) {
case 2: /* VAG */ case 2: /* PS-ADPCM */
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = channel_count == 6 ? layout_blocked_vawx : layout_interleave ; vgmstream->layout_type = channel_count == 6 ? layout_blocked_vawx : layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile);
@ -66,6 +66,8 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile); vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);
/* may be only applying end_skip to num_samples? */
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0);
break; break;
} }

View File

@ -19,6 +19,7 @@ typedef struct {
size_t fmt_size; size_t fmt_size;
off_t data_offset; off_t data_offset;
size_t data_size; size_t data_size;
off_t chunk_offset;
/* standard fmt stuff */ /* standard fmt stuff */
wwise_codec codec; wwise_codec codec;
@ -104,9 +105,9 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
ww.format = (uint16_t)read_16bit(ww.fmt_offset+0x00,streamFile); ww.format = (uint16_t)read_16bit(ww.fmt_offset+0x00,streamFile);
if (ww.format == 0x0165) { /* XMA2WAVEFORMAT (always "fmt"+"XMA2", unlike .xma that may only have "XMA2") */ if (ww.format == 0x0165) { /* XMA2WAVEFORMAT (always "fmt"+"XMA2", unlike .xma that may only have "XMA2") */
off_t xma2_offset; if (!find_chunk(streamFile, 0x584D4132,first_offset,0, &ww.chunk_offset,NULL, ww.big_endian, 0))
if (!find_chunk(streamFile, 0x584D4132,first_offset,0, &xma2_offset,NULL, ww.big_endian, 0)) goto fail; goto fail;
xma2_parse_xma2_chunk(streamFile, xma2_offset,&ww.channels,&ww.sample_rate, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample); xma2_parse_xma2_chunk(streamFile, ww.chunk_offset,&ww.channels,&ww.sample_rate, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample);
} else { /* WAVEFORMATEX */ } else { /* WAVEFORMATEX */
ww.channels = read_16bit(ww.fmt_offset+0x02,streamFile); ww.channels = read_16bit(ww.fmt_offset+0x02,streamFile);
ww.sample_rate = read_32bit(ww.fmt_offset+0x04,streamFile); ww.sample_rate = read_32bit(ww.fmt_offset+0x04,streamFile);
@ -122,9 +123,10 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
/* find loop info */ /* find loop info */
if (ww.format == 0x0166) { /* XMA2WAVEFORMATEX */ if (ww.format == 0x0166) { /* XMA2WAVEFORMATEX */
xma2_parse_fmt_chunk_extra(streamFile, ww.fmt_offset, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample, ww.big_endian); ww.chunk_offset = ww.fmt_offset;
xma2_parse_fmt_chunk_extra(streamFile, ww.chunk_offset, &ww.loop_flag, &ww.num_samples, &ww.loop_start_sample, &ww.loop_end_sample, ww.big_endian);
} }
else if (find_chunk(streamFile, 0x736D706C,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"smpl". common */ else if (find_chunk(streamFile, 0x736D706C,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"smpl", common */
if (loop_size >= 0x34 if (loop_size >= 0x34
&& read_32bit(loop_offset+0x1c, streamFile)==1 /*loop count*/ && read_32bit(loop_offset+0x1c, streamFile)==1 /*loop count*/
&& read_32bit(loop_offset+0x24+4, streamFile)==0) { && read_32bit(loop_offset+0x24+4, streamFile)==0) {
@ -139,7 +141,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
//} //}
/* other Wwise specific: */ /* other Wwise specific: */
//"JUNK": optional padding for usually aligment (0-size JUNK exists too) //"JUNK": optional padding for aligment (0-size JUNK exists too)
//"akd ": seem to store extra info for Wwise editor (wave peaks/loudness/HDR envelope?) //"akd ": seem to store extra info for Wwise editor (wave peaks/loudness/HDR envelope?)
} }
@ -162,7 +164,6 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
case 0xFFFE: ww.codec = PCM; break; /* "PCM for Wwise Authoring" */ case 0xFFFE: ww.codec = PCM; break; /* "PCM for Wwise Authoring" */
case 0xFFFF: ww.codec = VORBIS; break; case 0xFFFF: ww.codec = VORBIS; break;
default: default:
VGM_LOG("WWISE: unknown codec 0x%x \n", ww.format);
goto fail; goto fail;
} }
@ -250,7 +251,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
if (ww.block_align != 0 || ww.bits_per_sample != 0) goto fail; /* always 0 for Worbis */ if (ww.block_align != 0 || ww.bits_per_sample != 0) goto fail; /* always 0 for Worbis */
/* autodetect format (field are mostly common, see the end of the file) */ /* autodetect format (fields are mostly common, see the end of the file) */
if (find_chunk(streamFile, 0x766F7262,first_offset,0, &vorb_offset,&vorb_size, ww.big_endian, 0)) { /*"vorb"*/ if (find_chunk(streamFile, 0x766F7262,first_offset,0, &vorb_offset,&vorb_size, ww.big_endian, 0)) { /*"vorb"*/
/* older Wwise (~<2012) */ /* older Wwise (~<2012) */
@ -273,7 +274,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
cfg.setup_type = WWV_EXTERNAL_CODEBOOKS; /* setup_type will be corrected later */ cfg.setup_type = WWV_EXTERNAL_CODEBOOKS; /* setup_type will be corrected later */
break; break;
case 0x2a: /* uncommon (mid 2011), [inFamous 2 (PS3)] */ case 0x2a: /* uncommon (mid 2011) [inFamous 2 (PS3)] */
data_offsets = 0x10; data_offsets = 0x10;
block_offsets = 0x28; block_offsets = 0x28;
cfg.header_type = WWV_TYPE_2; cfg.header_type = WWV_TYPE_2;
@ -296,9 +297,9 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
ww.data_size -= audio_offset; ww.data_size -= audio_offset;
/* detect setup type: /* detect setup type:
* - full inline: ~2009, ex. The King of Fighters XII X360, The Saboteur PC * - full inline: ~2009, ex. The King of Fighters XII (X360), The Saboteur (PC)
* - trimmed inline: ~2010, ex. Army of Two: 40 days X360 (some multiplayer files) * - trimmed inline: ~2010, ex. Army of Two: 40 days (X360) some multiplayer files
* - external: ~2010, ex. Assassin's Creed Brotherhood X360, Dead Nation X360 */ * - external: ~2010, ex. Assassin's Creed Brotherhood (X360), Dead Nation (X360) */
if (vorb_size == 0x34) { if (vorb_size == 0x34) {
size_t setup_size = (uint16_t)read_16bit(start_offset + setup_offset, streamFile); size_t setup_size = (uint16_t)read_16bit(start_offset + setup_offset, streamFile);
uint32_t id = (uint32_t)read_32bitBE(start_offset + setup_offset + 0x06, streamFile); uint32_t id = (uint32_t)read_32bitBE(start_offset + setup_offset + 0x06, streamFile);
@ -329,12 +330,12 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
cfg.packet_type = WWV_MODIFIED; cfg.packet_type = WWV_MODIFIED;
/* setup not detectable by header, so we'll try both; hopefully libvorbis will reject wrong codebooks /* setup not detectable by header, so we'll try both; hopefully libvorbis will reject wrong codebooks
* - standard: early (<2012), ex. The King of Fighters XIII X360 (2011/11), .ogg (cbs are from aoTuV, too) * - standard: early (<2012), ex. The King of Fighters XIII (X360)-2011/11, .ogg (cbs are from aoTuV, too)
* - aoTuV603: later (>2012), ex. Sonic & All-Stars Racing Transformed PC (2012/11), .wem */ * - aoTuV603: later (>2012), ex. Sonic & All-Stars Racing Transformed (PC)-2012/11, .wem */
cfg.setup_type = is_wem ? WWV_AOTUV603_CODEBOOKS : WWV_EXTERNAL_CODEBOOKS; /* aoTuV came along .wem */ cfg.setup_type = is_wem ? WWV_AOTUV603_CODEBOOKS : WWV_EXTERNAL_CODEBOOKS; /* aoTuV came along .wem */
break; break;
//case 0x2a: /* Rocksmith 2011 X360? */ //case 0x2a: /* Rocksmith 2011 (X360)? */
//non mod packets? TYPE_06? (possibly detectable by checking setup's granule, should be 0) //non mod packets? TYPE_06? (possibly detectable by checking setup's granule, should be 0)
default: default:
VGM_LOG("WWISE: unknown extra size 0x%x\n", vorb_size); VGM_LOG("WWISE: unknown extra size 0x%x\n", vorb_size);
@ -348,10 +349,10 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
cfg.blocksize_0_exp = read_8bit(extra_offset + block_offsets + 0x01, streamFile); /* big */ cfg.blocksize_0_exp = read_8bit(extra_offset + block_offsets + 0x01, streamFile); /* big */
ww.data_size -= audio_offset; ww.data_size -= audio_offset;
/* Normal packets are used rarely (ex. Oddworld New 'n' Tasty! PSV). They are hard to detect (decoding /* Normal packets are used rarely (ex. Oddworld New 'n' Tasty! (PSV)). They are hard to detect (decoding
* will mostly work with garbage results) but we'll try. Setup size and "fmt" bitrate fields may matter too. */ * will mostly work with garbage results) but we'll try. Setup size and "fmt" bitrate fields may matter too. */
if (ww.extra_size == 0x30) { if (ww.extra_size == 0x30) {
/* all blocksizes I've seen are 0x08+0x0B except Oddworld PSV, that uses 0x09+0x09 /* all blocksizes I've seen are 0x08+0x0B except Oddworld (PSV), that uses 0x09+0x09
* (maybe lower spec machines = needs simpler packets) */ * (maybe lower spec machines = needs simpler packets) */
if (cfg.blocksize_0_exp == cfg.blocksize_1_exp) if (cfg.blocksize_0_exp == cfg.blocksize_1_exp)
cfg.packet_type = WWV_STANDARD; cfg.packet_type = WWV_STANDARD;
@ -395,7 +396,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = 0x08; /* ww.block_align = 0x8 in older Wwise, samples per block in newer Wwise */ vgmstream->interleave_block_size = 0x08; /* ww.block_align = 0x8 in older Wwise, samples per block in newer Wwise */
/* find coef position */ /* find coef position */
if (find_chunk(streamFile, 0x57696948,first_offset,0, &wiih_offset,&wiih_size, ww.big_endian, 0)) { /*"WiiH"*/ /* older Wwise */ if (find_chunk(streamFile, 0x57696948,first_offset,0, &wiih_offset,&wiih_size, ww.big_endian, 0)) { /*"WiiH", older Wwise */
vgmstream->num_samples = dsp_bytes_to_samples(ww.data_size, ww.channels); vgmstream->num_samples = dsp_bytes_to_samples(ww.data_size, ww.channels);
if (wiih_size != 0x2e * ww.channels) goto fail; if (wiih_size != 0x2e * ww.channels) goto fail;
} }
@ -442,6 +443,9 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
vgmstream->num_samples = ww.num_samples; /* set while parsing XMAWAVEFORMATs */ vgmstream->num_samples = ww.num_samples; /* set while parsing XMAWAVEFORMATs */
/* Wwise loops are always pre-adjusted (old or new) and only num_samples is off */
xma_fix_raw_samples(vgmstream, streamFile, ww.data_offset,ww.data_size, ww.chunk_offset, 1,0);
/* "XMAc": rare Wwise extension, XMA2 physical loop regions (loop_start_b, loop_end_b, loop_subframe_data) /* "XMAc": rare Wwise extension, XMA2 physical loop regions (loop_start_b, loop_end_b, loop_subframe_data)
* Can appear even in the file doesn't loop, maybe it's meant to be the playable physical region */ * Can appear even in the file doesn't loop, maybe it's meant to be the playable physical region */
//VGM_ASSERT(find_chunk(streamFile, 0x584D4163,first_offset,0, NULL,NULL, ww.big_endian, 0), "WWISE: XMAc chunk found\n"); //VGM_ASSERT(find_chunk(streamFile, 0x584D4163,first_offset,0, NULL,NULL, ww.big_endian, 0), "WWISE: XMAc chunk found\n");

View File

@ -55,7 +55,6 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
vgmstream->num_samples = msd.num_samples; vgmstream->num_samples = msd.num_samples;
vgmstream->loop_start_sample = msd.loop_start_sample; vgmstream->loop_start_sample = msd.loop_start_sample;
vgmstream->loop_end_sample = msd.loop_end_sample; vgmstream->loop_end_sample = msd.loop_end_sample;
//skip_samples = msd.skip_samples; //todo add skip samples
} }
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
@ -68,12 +67,12 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
/* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */ /* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1); bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,100, fmt_offset,fmt_size, data_size, streamFile, 1);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail; if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, fmt_offset, 1,1);
} }
#else #else
goto fail; goto fail;

View File

@ -1,31 +1,29 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* CXS - found in Eternal Sonata (Xbox 360) */ /* CXS - found in Eternal Sonata (X360) */
VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
int loop_flag, channel_count; int loop_flag, channel_count;
/* check extension, case insensitive */ /* checks */
if ( !check_extensions(streamFile,"cxs")) if ( !check_extensions(streamFile,"cxs"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x43585320) /* "CXS " */ if (read_32bitBE(0x00,streamFile) != 0x43585320) /* "CXS " */
goto fail; goto fail;
loop_flag = read_32bitBE(0x18,streamFile) > 0; loop_flag = read_32bitBE(0x18,streamFile) > 0;
channel_count = read_32bitBE(0x0c,streamFile); channel_count = read_32bitBE(0x0c,streamFile);
start_offset = read_32bitBE(0x04,streamFile) + read_32bitBE(0x28,streamFile); /* assumed, seek table always at 0x800 */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
start_offset = read_32bitBE(0x04,streamFile) + read_32bitBE(0x28,streamFile); /* assumed, seek table always at 0x800 */
/* 0x04: data start? */ /* 0x04: data start? */
vgmstream->sample_rate = read_32bitBE(0x08,streamFile); vgmstream->sample_rate = read_32bitBE(0x08,streamFile);
vgmstream->channels = channel_count; /*0x0c*/ vgmstream->num_samples = read_32bitBE(0x10,streamFile);
vgmstream->num_samples = read_32bitBE(0x10,streamFile) + 576; /*todo add proper encoder_delay*/
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile);
/* 0x1c: below */ /* 0x1c: below */
@ -50,6 +48,8 @@ VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE *streamFile) {
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,datasize, 0, 0,1); /* num samples are ok */
} }
#else #else
goto fail; goto fail;

View File

@ -10,10 +10,9 @@ VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) {
int num_samples, loop_start_sample, loop_end_sample; int num_samples, loop_start_sample, loop_end_sample;
/* check extension, case insensitive */ /* checks */
if ( !check_extensions(streamFile,"past")) if ( !check_extensions(streamFile,"past"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */ if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */
goto fail; goto fail;
@ -51,6 +50,8 @@ VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) {
if ( !vgmstream->codec_data ) goto fail; if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1);
} }
#else #else
goto fail; goto fail;

View File

@ -1,7 +1,7 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* XMA - Microsoft format derived from WMAPRO, found in X360/XBone games */ /* XMA - Microsoft format derived from RIFF, found in X360/XBone games */
VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, chunk_offset, first_offset = 0xc; off_t start_offset, chunk_offset, first_offset = 0xc;
@ -69,7 +69,7 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
goto fail; goto fail;
/* fix samples; for now only XMA1 is fixed, but XMA2 num_samples don't include skip samples and xmaencode.exe doesn't use it */ /* get xma1 samples, later fixed */
if (is_xma1) { if (is_xma1) {
ms_sample_data msd = {0}; ms_sample_data msd = {0};
@ -96,12 +96,11 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->meta_type = meta_XMA_RIFF;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start_sample; vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample; vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_XMA_RIFF;
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
{ {
@ -118,6 +117,8 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
if ( !vgmstream->codec_data ) goto fail; if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1);
} }
#else #else
goto fail; goto fail;

View File

@ -4,18 +4,16 @@
/* XNB - Microsoft XNA Game Studio 4.0 format */ /* XNB - Microsoft XNA Game Studio 4.0 format */
VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset, xma_chunk_offset = 0;
int loop_flag = 0, channel_count, num_samples = 0, loop_start = 0, loop_end = 0; 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; int big_endian, flags, codec, sample_rate, block_size, bps;
size_t data_size; size_t data_size;
char platform; char platform;
/* check extension, case insensitive */ /* checks */
if ( !check_extensions(streamFile,"xnb")) if (!check_extensions(streamFile,"xnb"))
goto fail; goto fail;
/* check header */
if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */ if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */
goto fail; goto fail;
@ -24,7 +22,7 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
platform = read_8bit(0x03,streamFile); platform = read_8bit(0x03,streamFile);
big_endian = (platform == 'x'); big_endian = (platform == 'x');
if (read_8bit(0x04,streamFile) != 0x05) /* XNA 4.0 version only */ if (read_8bit(0x04,streamFile) != 0x05) /* XNA 4.0 version only */
goto fail; goto fail;
flags = read_8bit(0x05,streamFile); flags = read_8bit(0x05,streamFile);
@ -82,6 +80,7 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
if (codec == 0x166) { if (codec == 0x166) {
xma2_parse_fmt_chunk_extra(streamFile, current_offset, &loop_flag, &num_samples, &loop_start, &loop_end, big_endian); xma2_parse_fmt_chunk_extra(streamFile, current_offset, &loop_flag, &num_samples, &loop_start, &loop_end, big_endian);
xma_chunk_offset = current_offset;
} }
} }
@ -138,8 +137,6 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
block_count = data_size / block_size + (data_size % block_size ? 1 : 0); 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); 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); vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
@ -148,6 +145,8 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start; vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end; vgmstream->loop_end_sample = loop_end;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, xma_chunk_offset, 1,1);
break; break;
} }
#endif #endif

View File

@ -69,6 +69,8 @@ typedef struct {
uint32_t loop_end_sample; uint32_t loop_end_sample;
int is_crackdown; int is_crackdown;
int fix_xma_num_samples;
int fix_xma_loop_samples;
} xwb_header; } xwb_header;
static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile); static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile);
@ -366,7 +368,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.loop_start_sample = msadpcm_bytes_to_samples(xwb.loop_start, block_size, xwb.channels); xwb.loop_start_sample = msadpcm_bytes_to_samples(xwb.loop_start, block_size, xwb.channels);
xwb.loop_end_sample = msadpcm_bytes_to_samples(xwb.loop_start + xwb.loop_end, block_size, xwb.channels); xwb.loop_end_sample = msadpcm_bytes_to_samples(xwb.loop_start + xwb.loop_end, block_size, xwb.channels);
} }
else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) { else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
/* v38: byte offset, v40+: sample offset, v39: ? */ /* v38: byte offset, v40+: sample offset, v39: ? */
/* need to manually find sample offsets, thanks to Microsoft's dumb headers */ /* need to manually find sample offsets, thanks to Microsoft's dumb headers */
ms_sample_data msd = {0}; ms_sample_data msd = {0};
@ -386,44 +388,27 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.loop_start_sample = msd.loop_start_sample; xwb.loop_start_sample = msd.loop_start_sample;
xwb.loop_end_sample = msd.loop_end_sample; xwb.loop_end_sample = msd.loop_end_sample;
/* for XWB v22 (and below?) this seems normal [Project Gotham Racing (X360)] */
if (xwb.num_samples == 0)
xwb.num_samples = msd.num_samples;
/* if provided, xwb.num_samples is equal to msd.num_samples after proper adjustments (+ 128 - start_skip - end_skip) */ /* if provided, xwb.num_samples is equal to msd.num_samples after proper adjustments (+ 128 - start_skip - end_skip) */
xwb.fix_xma_loop_samples = 1;
xwb.fix_xma_num_samples = 0;
#if 1 /* for XWB v22 (and below?) this seems normal [Project Gotham Racing (X360)] */
//todo add padding back until FFmpeg decoding + msd.loops are fixed (affects edge loops) if (xwb.num_samples == 0) {
// (in rare cases this causes a glitch in FFmpeg due to missing samples) xwb.num_samples = msd.num_samples;
xwb.num_samples += 64 + 512; xwb.fix_xma_num_samples = 1;
#endif }
} }
else if ((xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) { else if ((xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
/* unlike prev versions, xwb.num_samples is the full size without adjustments */ /* unlike prev versions, xwb.num_samples is the full size without adjustments */
xwb.fix_xma_loop_samples = 1;
xwb.fix_xma_num_samples = 1;
#if 0 //todo apply once FFmpeg decode is ok /* Crackdown does use xwb.num_samples after adjustments (but not loops) */
/* apply extra output + skips (see ms_audio_get_samples, approximate as find out with first and last frames) */
int start_skip = 512;
int end_skip = 0;
xwb.num_samples += 128;
xwb.num_samples -= start_skip;
xwb.num_samples -= end_skip;
if (xwb.loop_flag) {
xwb.loop_start_sample += 128;
xwb.loop_start_sample -= start_skip;
xwb.loop_end_sample += 128;
xwb.loop_end_sample -= start_skip;
}
#endif
/* Crackdown does use xwb.num_samples after adjustments (but not loops), fix it back */
if (xwb.is_crackdown) { if (xwb.is_crackdown) {
xwb.num_samples += 512 - 128; xwb.fix_xma_num_samples = 0;
} }
} }
VGM_LOG("fix: num=%i, loop=%i\n", xwb.fix_xma_num_samples,xwb.fix_xma_loop_samples);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(xwb.channels,xwb.loop_flag); vgmstream = allocate_vgmstream(xwb.channels,xwb.loop_flag);
@ -467,6 +452,15 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, xwb.stream_offset,xwb.stream_size, 0, xwb.fix_xma_num_samples,xwb.fix_xma_loop_samples);
/* this fixes some XMA1, perhaps the above isn't reading end_skip correctly (doesn't happen for all files though) */
if (vgmstream->loop_flag &&
vgmstream->loop_end_sample > vgmstream->num_samples) {
VGM_LOG("XWB: fix XMA1 looping\n");
vgmstream->loop_end_sample = vgmstream->num_samples;
}
break; break;
} }
@ -482,6 +476,8 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, xwb.stream_offset,xwb.stream_size, 0, xwb.fix_xma_num_samples,xwb.fix_xma_loop_samples);
break; break;
} }

View File

@ -8,7 +8,9 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
size_t data_size; size_t data_size;
int loop_flag, channel_count, codec, num_samples; int loop_flag, channel_count, codec, num_samples;
/* check extensions (.xwc is the extension of the bigfile, individual files don't have one) */
/* checks */
/* .xwc: extension of the bigfile, individual files don't have one */
if ( !check_extensions(streamFile,"xwc")) if ( !check_extensions(streamFile,"xwc"))
goto fail; goto fail;
@ -16,7 +18,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
/* version */ /* version */
if (read_32bitBE(0x00,streamFile) == 0x00030000 && if (read_32bitBE(0x00,streamFile) == 0x00030000 &&
read_32bitBE(0x04,streamFile) == 0x00900000) { /* The Darkness */ read_32bitBE(0x04,streamFile) == 0x00900000) { /* The Darkness */
data_size = read_32bitLE(0x08, streamFile); /* including subheader */ data_size = read_32bitLE(0x08, streamFile) + 0x1c; /* not including subheader */
channel_count = read_32bitLE(0x0c, streamFile); channel_count = read_32bitLE(0x0c, streamFile);
/* 0x10: num_samples */ /* 0x10: num_samples */
/* 0x14: 0x8000? */ /* 0x14: 0x8000? */
@ -28,7 +30,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
} }
else if (read_32bitBE(0x00,streamFile) == 0x00040000 && else if (read_32bitBE(0x00,streamFile) == 0x00040000 &&
read_32bitBE(0x04,streamFile) == 0x00900000) { /* Riddick, Syndicate */ read_32bitBE(0x04,streamFile) == 0x00900000) { /* Riddick, Syndicate */
data_size = read_32bitLE(0x08, streamFile); /* including subheader */ data_size = read_32bitLE(0x08, streamFile) + 0x24; /* not including subheader */
channel_count = read_32bitLE(0x0c, streamFile); channel_count = read_32bitLE(0x0c, streamFile);
/* 0x10: num_samples */ /* 0x10: num_samples */
/* 0x14: 0x8000? */ /* 0x14: 0x8000? */
@ -42,15 +44,15 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
goto fail; goto fail;
} }
loop_flag = 0; /* seemingly not in the file */ loop_flag = 0;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->num_samples = num_samples;
vgmstream->meta_type = meta_XWC; vgmstream->meta_type = meta_XWC;
vgmstream->num_samples = num_samples;
switch(codec) { switch(codec) {
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
@ -59,7 +61,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
start_offset = 0x800; start_offset = 0x800;
vgmstream->num_samples = read_32bitLE(extra_offset+0x00, streamFile); /* with encoder delay */ //todo improve vgmstream->num_samples = read_32bitLE(extra_offset+0x00, streamFile); /* with encoder delay */ //todo improve
cfg.data_size = read_32bitLE(extra_offset+0x04, streamFile); //data_size - 0x28; cfg.data_size = read_32bitLE(extra_offset+0x04, streamFile); /* without padding */
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_STANDARD, &cfg); vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_STANDARD, &cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
@ -77,6 +79,7 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
seek_size = read_32bitLE(extra_offset+0x00, streamFile); seek_size = read_32bitLE(extra_offset+0x00, streamFile);
start_offset = extra_offset+0x04 + seek_size + read_32bitLE(extra_offset+0x04+seek_size, streamFile) + 0x08; start_offset = extra_offset+0x04 + seek_size + read_32bitLE(extra_offset+0x04+seek_size, streamFile) + 0x08;
start_offset += (start_offset % 0x800) ? 0x800 - (start_offset % 0x800) : 0; /* padded */ start_offset += (start_offset % 0x800) ? 0x800 - (start_offset % 0x800) : 0; /* padded */
data_size = data_size - start_offset;
sample_rate = read_32bitBE(extra_offset+0x04+seek_size+0x10, streamFile); sample_rate = read_32bitBE(extra_offset+0x04+seek_size+0x10, streamFile);
block_size = read_32bitBE(extra_offset+0x04+seek_size+0x1c, streamFile); block_size = read_32bitBE(extra_offset+0x04+seek_size+0x1c, streamFile);
@ -84,21 +87,22 @@ VGMSTREAM * init_vgmstream_xwc(STREAMFILE *streamFile) {
/* others: scrambled RIFF fmt BE values */ /* others: scrambled RIFF fmt BE values */
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, 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);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size - start_offset - 0x28);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = sample_rate;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok, fix delay */
break; break;
} }
case 0x564F5242: { /* "VORB" (PC) */ case 0x564F5242: { /* "VORB" (PC) */
start_offset = 0x30; start_offset = 0x30;
data_size = data_size - start_offset;
vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset, data_size - start_offset - 0x28); vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail; if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;