Fix hang on full loops with xma1 formats

This commit is contained in:
bnnm 2023-01-20 16:09:08 +01:00
parent 501af6ad8c
commit 2b0399d7f5
15 changed files with 281 additions and 420 deletions

View File

@ -624,6 +624,7 @@ ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32
ffmpeg_codec_data* init_ffmpeg_xma1_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int channels, int sample_rate, int stream_mode);
ffmpeg_codec_data* init_ffmpeg_xma_chunk(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size);
ffmpeg_codec_data* init_ffmpeg_xma_chunk_split(STREAMFILE* sf_head, STREAMFILE* sf_data, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size);
/* ffmpeg_decoder_custom_opus.c (helper-things) */
typedef struct {
@ -683,7 +684,6 @@ ffmpeg_codec_data* init_ffmpeg_mp4_custom_lyn(STREAMFILE* sf, mp4_custom_t* mp4)
/* coding_utils */
int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay);
int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size);
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian);
int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align);
/* MS audio format's sample info (struct to avoid passing so much stuff, separate for reusing) */

View File

@ -139,41 +139,6 @@ int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, si
return riff_size;
}
static int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec);
/* Makes a XMA1/2 RIFF header for FFmpeg using a "fmt " chunk (XMAWAVEFORMAT or XMA2WAVEFORMATEX) as a base:
* Useful to preserve the stream layout */
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian) {
size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4;
uint8_t chunk[0x100];
if (buf_size < riff_size || fmt_size > 0x100)
goto fail;
if (read_streamfile(chunk,fmt_offset,fmt_size, sf) != fmt_size)
goto fail;
if (big_endian) {
int codec = read_16bitBE(fmt_offset,sf);//TODO read from buf
ffmpeg_fmt_chunk_swap_endian(chunk, fmt_size, codec);
}
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, fmt_size);/*fmt size*/
memcpy(buf+0x14, chunk, fmt_size);
memcpy(buf+0x14+fmt_size, "data", 4);
put_32bitLE(buf+0x14+fmt_size+4, data_size); /* data size */
return riff_size;
fail:
return -1;
}
int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align) {
size_t riff_size = 4+4+ 4 + 0x1a + 4+4;
@ -232,61 +197,6 @@ int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_
}
static int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec) {
int i;
/* swap from LE to BE or the other way around, doesn't matter */
switch(codec) {
case 0x165: { /* XMA1 */
put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*FormatTag*/
put_16bitLE(chunk + 0x02, get_16bitBE(chunk + 0x02));/*BitsPerSample*/
put_16bitLE(chunk + 0x04, get_16bitBE(chunk + 0x04));/*EncodeOptions*/
put_16bitLE(chunk + 0x06, get_16bitBE(chunk + 0x06));/*LargestSkip*/
put_16bitLE(chunk + 0x08, get_16bitBE(chunk + 0x08));/*NumStreams*/
// put_8bit(chunk + 0x0a, get_8bit(chunk + 0x0a));/*LoopCount*/
// put_8bit(chunk + 0x0b, get_8bit(chunk + 0x0b));/*Version*/
for (i = 0xc; i < chunk_size; i += 0x14) { /* reverse endianness for each stream */
put_32bitLE(chunk + i + 0x00, get_32bitBE(chunk + i + 0x00));/*PsuedoBytesPerSec*/
put_32bitLE(chunk + i + 0x04, get_32bitBE(chunk + i + 0x04));/*SampleRate*/
put_32bitLE(chunk + i + 0x08, get_32bitBE(chunk + i + 0x08));/*LoopStart*/
put_32bitLE(chunk + i + 0x0c, get_32bitBE(chunk + i + 0x0c));/*LoopEnd*/
// put_8bit(chunk + i + 0x10, get_8bit(chunk + i + 0x10));/*SubframeData*/
// put_8bit(chunk + i + 0x11, get_8bit(chunk + i + 0x11));/*Channels*/
put_16bitLE(chunk + i + 0x12, get_16bitBE(chunk + i + 0x12));/*ChannelMask*/
}
break;
}
case 0x166: { /* XMA2 */
put_16bitLE(chunk + 0x00, get_16bitBE(chunk + 0x00));/*wFormatTag*/
put_16bitLE(chunk + 0x02, get_16bitBE(chunk + 0x02));/*nChannels*/
put_32bitLE(chunk + 0x04, get_32bitBE(chunk + 0x04));/*nSamplesPerSec*/
put_32bitLE(chunk + 0x08, get_32bitBE(chunk + 0x08));/*nAvgBytesPerSec*/
put_16bitLE(chunk + 0x0c, get_16bitBE(chunk + 0x0c));/*nBlockAlign*/
put_16bitLE(chunk + 0x0e, get_16bitBE(chunk + 0x0e));/*wBitsPerSample*/
put_16bitLE(chunk + 0x10, get_16bitBE(chunk + 0x10));/*cbSize*/
put_16bitLE(chunk + 0x12, get_16bitBE(chunk + 0x12));/*NumStreams*/
put_32bitLE(chunk + 0x14, get_32bitBE(chunk + 0x14));/*ChannelMask*/
put_32bitLE(chunk + 0x18, get_32bitBE(chunk + 0x18));/*SamplesEncoded*/
put_32bitLE(chunk + 0x1c, get_32bitBE(chunk + 0x1c));/*BytesPerBlock*/
put_32bitLE(chunk + 0x20, get_32bitBE(chunk + 0x20));/*PlayBegin*/
put_32bitLE(chunk + 0x24, get_32bitBE(chunk + 0x24));/*PlayLength*/
put_32bitLE(chunk + 0x28, get_32bitBE(chunk + 0x28));/*LoopBegin*/
put_32bitLE(chunk + 0x2c, get_32bitBE(chunk + 0x2c));/*LoopLength*/
/* put_8bit(chunk + 0x30, get_8bit(chunk + 0x30));*//*LoopCount*/
/* put_8bit(chunk + 0x31, get_8bit(chunk + 0x31));*//*EncoderVersion*/
put_16bitLE(chunk + 0x32, get_16bitBE(chunk + 0x32));/*BlockCount*/
break;
}
default:
goto fail;
}
return 1;
fail:
return 0;
}
/* ******************************************** */
/* XMA PARSING */

View File

@ -415,12 +415,16 @@ static int ffmpeg_make_riff_xma_chunk(STREAMFILE* sf, uint8_t* buf, int buf_size
}
ffmpeg_codec_data* init_ffmpeg_xma_chunk(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size) {
return init_ffmpeg_xma_chunk_split(sf, sf, data_offset, data_size, chunk_offset, chunk_size);
}
ffmpeg_codec_data* init_ffmpeg_xma_chunk_split(STREAMFILE* sf_head, STREAMFILE* sf_data, uint32_t data_offset, uint32_t data_size, uint32_t chunk_offset, uint32_t chunk_size) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int is_xma1 = 0;
int bytes = ffmpeg_make_riff_xma_chunk(sf, buf, sizeof(buf), data_size, chunk_offset, chunk_size, &is_xma1);
data = init_ffmpeg_header_offset(sf, buf, bytes, data_offset, data_size);
int bytes = ffmpeg_make_riff_xma_chunk(sf_head, buf, sizeof(buf), data_size, chunk_offset, chunk_size, &is_xma1);
data = init_ffmpeg_header_offset(sf_data, buf, bytes, data_offset, data_size);
if (!data) goto fail;
/* n5.1.2 XMA1 hangs on seeks near end (infinite loop), presumably due to missing flush in wmapro.c's ff_xma1_decoder + frame skip samples */

View File

@ -3,9 +3,9 @@
#include "../coding/coding.h"
/* GSP+GSB - from Tecmo's Super Swing Golf 1 & 2 (Wii), Quantum Theory (PS3/X360) */
VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamHeader = NULL;
VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_head = NULL;
int loop_flag, channel_count, sample_rate, num_samples, loop_start, loop_end;
off_t start_offset, chunk_offset, first_offset;
size_t data_size;
@ -13,43 +13,43 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
/* checks */
if (!check_extensions(streamFile,"gsb"))
if (!check_extensions(sf,"gsb"))
goto fail;
streamHeader = open_streamfile_by_ext(streamFile, "gsp");
if (!streamHeader) goto fail;
sf_head = open_streamfile_by_ext(sf, "gsp");
if (!sf_head) goto fail;
if (read_32bitBE(0x00,streamHeader) != 0x47534E44) /* "GSND" */
if (!is_id32be(0x00,sf_head, "GSND"))
goto fail;
/* 0x04: version? */
/* 0x08: 1? */
/* 0x0c: 0? */
first_offset = read_32bitBE(0x10,streamHeader); /* usually 0x14 */
first_offset = read_32bitBE(0x10,sf_head); /* usually 0x14 */
if (!find_chunk_be(streamHeader, 0x48454144,first_offset,1, &chunk_offset,NULL)) /* "HEAD" */
if (!find_chunk_be(sf_head, 0x48454144,first_offset,1, &chunk_offset,NULL)) /* "HEAD" */
goto fail;
/* 0x00: header size */
/* 0x04: num_chunks */
if (!find_chunk_be(streamHeader, 0x44415441,first_offset,1, &chunk_offset,NULL)) /* "DATA" */
if (!find_chunk_be(sf_head, 0x44415441,first_offset,1, &chunk_offset,NULL)) /* "DATA" */
goto fail;
data_size = read_32bitBE(chunk_offset + 0x00,streamHeader);
codec = read_32bitBE(chunk_offset + 0x04,streamHeader);
sample_rate = read_32bitBE(chunk_offset + 0x08,streamHeader);
data_size = read_32bitBE(chunk_offset + 0x00,sf_head);
codec = read_32bitBE(chunk_offset + 0x04,sf_head);
sample_rate = read_32bitBE(chunk_offset + 0x08,sf_head);
/* 0x0c: always 16? */
channel_count = read_16bitBE(chunk_offset + 0x0e,streamHeader);
channel_count = read_16bitBE(chunk_offset + 0x0e,sf_head);
/* 0x10: always 0? */
num_samples = read_32bitBE(chunk_offset + 0x14,streamHeader);
num_samples = read_32bitBE(chunk_offset + 0x14,sf_head);
/* 0x18: always 0? */
/* 0x1c: unk (varies with codec_id) */
if (!find_chunk_be(streamHeader, 0x42534943,first_offset,1, &chunk_offset,NULL)) /* "BSIC" */
if (!find_chunk_be(sf_head, 0x42534943,first_offset,1, &chunk_offset,NULL)) /* "BSIC" */
goto fail;
/* 0x00/0x04: probably volume/pan/etc floats (1.0) */
/* 0x08: null? */
loop_flag = read_8bit(chunk_offset+0x0c,streamHeader);
loop_start = read_32bitBE(chunk_offset+0x10,streamHeader);
loop_end = read_32bitBE(chunk_offset+0x14,streamHeader);
loop_flag = read_8bit(chunk_offset+0x0c,sf_head);
loop_start = read_32bitBE(chunk_offset+0x10,sf_head);
loop_end = read_32bitBE(chunk_offset+0x14,sf_head);
//if (!find_chunk_be(streamHeader, 0x4E414D45,first_offset,1, &chunk_offset,NULL)) /* "NAME" */
// goto fail;
@ -79,16 +79,16 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_gsb;
if (!find_chunk_be(streamHeader, 0x47434558,first_offset,1, &chunk_offset,NULL)) /* "GCEX" */
if (!find_chunk_be(sf_head, 0x47434558,first_offset,1, &chunk_offset,NULL)) /* "GCEX" */
goto fail;
//vgmstream->current_block_size = read_32bitBE(chunk_offset+0x00,streamHeader);
block_header_size = read_32bitBE(chunk_offset+0x04,streamHeader);
num_blocks = read_32bitBE(chunk_offset+0x08,streamHeader);
block_header_size = read_32bitBE(chunk_offset+0x04,sf_head);
num_blocks = read_32bitBE(chunk_offset+0x08,sf_head);
vgmstream->num_samples = (data_size - block_header_size * num_blocks) / 8 / vgmstream->channels * 14;
/* 0x0c+: unk */
dsp_read_coefs_be(vgmstream, streamHeader, chunk_offset+0x18, 0x30);
dsp_read_coefs_be(vgmstream, sf_head, chunk_offset+0x18, 0x30);
break;
}
#ifdef VGM_USE_FFMPEG
@ -100,7 +100,7 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay;
/* fix num_samples as header samples seem to be modified to match altered (49999/48001) sample rates somehow */
vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -112,21 +112,17 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
}
case 0x09: { /* XMA2 [Quantum Theory (PS3)] */
uint8_t buf[0x100];
int32_t bytes;
if (!find_chunk_be(streamHeader, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
if (!find_chunk_be(sf_head, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */
goto fail;
/* 0x00: fmt0x166 header (BE) */
/* 0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, chunk_offset,0x34, data_size, streamHeader, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf_head, sf, start_offset, data_size, chunk_offset, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, 0,0); /* samples are ok */
xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */
break;
}
#endif
@ -135,13 +131,13 @@ VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) {
}
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
close_streamfile(streamHeader);
close_streamfile(sf_head);
return vgmstream;
fail:
close_streamfile(streamHeader);
close_streamfile(sf_head);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -3,73 +3,73 @@
typedef enum { XMA2, ATRAC9 } gtd_codec;
/* GTD - found in Knights Contract (X360, PS3), Valhalla Knights 3 (PSV) */
VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
/* GTD - from Hexadrive's HexaEngine [Knights Contract (X360/PS3), Valhalla Knights 3 (Vita)] */
VGMSTREAM* init_vgmstream_gtd(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, chunk_offset, stpr_offset, name_offset = 0, loop_start_offset, loop_end_offset;
size_t data_size, chunk_size;
int loop_flag, channel_count, sample_rate;
int loop_flag, channels, sample_rate;
int num_samples, loop_start_sample, loop_end_sample;
uint32_t at9_config_data;
gtd_codec codec;
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"gtd"))
/* checks */
if (!is_id32be(0x00,sf, "GHS "))
goto fail;
if ( !check_extensions(sf,"gtd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x47485320) /* "GHS " */
goto fail;
/* header type, not formally specified */
if (read_32bitBE(0x04,streamFile) == 1 && read_16bitBE(0x0C,streamFile) == 0x0166) { /* XMA2 */
if (read_32bitBE(0x04,sf) == 1 && read_16bitBE(0x0C,sf) == 0x0166) { /* XMA2 */
/* 0x08(4): seek table size */
chunk_offset = 0x0c; /* custom header with a "fmt " data chunk inside */
chunk_size = 0x34;
channel_count = read_16bitBE(chunk_offset+0x02,streamFile);
sample_rate = read_32bitBE(chunk_offset+0x04,streamFile);
xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
channels = read_16bitBE(chunk_offset+0x02,sf);
sample_rate = read_32bitBE(chunk_offset+0x04,sf);
xma2_parse_fmt_chunk_extra(sf, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
start_offset = read_32bitBE(0x58,streamFile); /* always 0x800 */
data_size = read_32bitBE(0x5c,streamFile);
start_offset = read_32bitBE(0x58,sf); /* always 0x800 */
data_size = read_32bitBE(0x5c,sf);
/* 0x34(18): null, 0x54(4): seek table offset, 0x58(4): seek table size, 0x5c(8): null, 0x64: seek table */
stpr_offset = read_32bitBE(chunk_offset+0x54,streamFile) + read_32bitBE(chunk_offset+0x58,streamFile);
if (read_32bitBE(stpr_offset,streamFile) == 0x53545052) { /* "STPR" */
stpr_offset = read_32bitBE(chunk_offset+0x54,sf) + read_32bitBE(chunk_offset+0x58,sf);
if (read_32bitBE(stpr_offset,sf) == 0x53545052) { /* "STPR" */
name_offset = stpr_offset + 0xB8; /* there are offsets fields but seems to work */
}
codec = XMA2;
}
else if (0x34 + read_32bitLE(0x30,streamFile) + read_32bitLE(0x0c,streamFile) == get_streamfile_size(streamFile)) { /* ATRAC9 */
else if (0x34 + read_32bitLE(0x30,sf) + read_32bitLE(0x0c,sf) == get_streamfile_size(sf)) { /* ATRAC9 */
data_size = read_32bitLE(0x0c,streamFile);
start_offset = 0x34 + read_32bitLE(0x30,streamFile);
channel_count = read_32bitLE(0x10,streamFile);
sample_rate = read_32bitLE(0x14,streamFile);
loop_start_offset = read_32bitLE(0x1c, streamFile);
loop_end_offset = read_32bitLE(0x20, streamFile);
data_size = read_32bitLE(0x0c,sf);
start_offset = 0x34 + read_32bitLE(0x30,sf);
channels = read_32bitLE(0x10,sf);
sample_rate = read_32bitLE(0x14,sf);
loop_start_offset = read_32bitLE(0x1c, sf);
loop_end_offset = read_32bitLE(0x20, sf);
loop_flag = loop_end_offset > loop_start_offset;
at9_config_data = read_32bitBE(0x28,streamFile);
at9_config_data = read_32bitBE(0x28,sf);
/* 0x18-0x28: fixed/unknown values */
stpr_offset = 0x2c;
if (read_32bitBE(stpr_offset,streamFile) == 0x53545052) { /* "STPR" */
if (read_32bitBE(stpr_offset,sf) == 0x53545052) { /* "STPR" */
name_offset = stpr_offset + 0xE8; /* there are offsets fields but seems to work */
}
codec = ATRAC9;
}
else {
/* apparently there is a PS3 variation (MSF inside?) */
/* there is a PS3 variation with MSF inside */
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
@ -77,27 +77,20 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_GTD;
if (name_offset) //encoding is Shift-Jis in some PSV files
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamFile);
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf);
switch(codec) {
#ifdef VGM_USE_FFMPEG
case XMA2: {
uint8_t buf[0x100];
size_t bytes;
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);
case XMA2:
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = num_samples;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1);
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, chunk_offset, 1,1);
break;
}
#endif
#ifdef VGM_USE_ATRAC9
case ATRAC9: {
@ -125,11 +118,9 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile) {
}
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -111,12 +111,9 @@ VGMSTREAM* init_vgmstream_mzrt_v0(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0166: {
uint8_t buf[0x100];
int bytes;
size_t stream_size = get_streamfile_size(temp_sf);
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,sizeof(buf), 0x15,0x34, stream_size, sf, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00,stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf, temp_sf, 0x00, stream_size, 0x15, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -238,8 +238,6 @@ VGMSTREAM* init_vgmstream_isb(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x04: {
uint8_t buf[0x100];
size_t bytes;
off_t fmt_offset = start_offset;
size_t fmt_size = 0x20;
@ -247,8 +245,7 @@ VGMSTREAM* init_vgmstream_isb(STREAMFILE* sf) {
stream_size -= fmt_size;
/* XMA1 "fmt" chunk (BE, unlike the usual LE) */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,sizeof(buf), fmt_offset,fmt_size, stream_size, sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset, stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, stream_size, fmt_offset, fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -168,7 +168,7 @@ VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf) {
break;
#ifdef VGM_USE_FFMPEG
case XWMA: { /* [Senxin Aleste (AC)] */
case XWMA: { /* Senxin Aleste (AC) */
vgmstream->codec_data = init_ffmpeg_xwma(sf, psb.stream_offset[0], psb.stream_size[0], psb.format, psb.channels, psb.sample_rate, psb.avg_bitrate, psb.block_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
@ -182,11 +182,7 @@ VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf) {
}
case XMA2: { /* Sega Vintage Collection (X360) */
uint8_t buf[0x100];
size_t bytes;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, sizeof(buf), psb.fmt_offset, psb.fmt_size, psb.stream_size[0], sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, psb.stream_offset[0], psb.stream_size[0]);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, psb.stream_offset[0], psb.stream_size[0], psb.fmt_offset, psb.fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -310,14 +310,10 @@ VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */
uint8_t buf[0x100];
int32_t bytes;
/* extradata:
* 0x00: fmt0x166 header (BE X360, LE XBone)
* 0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, extradata_offset,0x34, stream_size, sf, big_endian);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, stream_size, extradata_offset, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -148,11 +148,7 @@ VGMSTREAM* init_vgmstream_ubi_ckd(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case XMA2: {
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, sizeof(buf), 0x14, 0x34, data_size, sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, 0x14, 0x34);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -273,8 +273,6 @@ VGMSTREAM* init_vgmstream_ubi_lyn(STREAMFILE* sf) {
}
case 0x0166: { /* XMA (X360), standard */
uint8_t buf[0x100];
int bytes;
off_t chunk_offset;
size_t chunk_size, seek_size;
@ -286,9 +284,8 @@ VGMSTREAM* init_vgmstream_ubi_lyn(STREAMFILE* sf) {
start_offset += (0x04 + 0x04 + chunk_size + 0x04 + seek_size);
data_size -= (0x04 + 0x04 + chunk_size + 0x04 + seek_size);
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, chunk_offset,chunk_size, data_size, sf, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -1118,10 +1118,9 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
// Probably a beta/custom encoder that creates some buggy frames, that a real X360 handles ok, but trips FFmpeg
// xmaencode decodes correctly if counters are fixed (otherwise has clicks on every frame).
case FMT_XMA1: {
uint8_t buf[0x100];
uint32_t sec1_num, sec2_num, sec3_num, bits_per_frame;
uint8_t flag;
size_t bytes, chunk_size, header_size, data_size;
size_t chunk_size, header_size, data_size;
off_t header_offset;
chunk_size = 0x20;
@ -1146,9 +1145,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
start_offset += header_size;
data_size = sec2_num * 0x800;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, data_size, sf_data, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf_data, start_offset, data_size, header_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -1158,8 +1155,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
}
case RAW_XMA1: {
uint8_t buf[0x100];
size_t bytes, chunk_size;
size_t chunk_size;
off_t header_offset;
VGM_ASSERT(sb->is_streamed, "UBI SB: Raw XMA used for streamed sound\n");
@ -1170,9 +1166,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h
if (header_offset == 0)
header_offset = sb->extra_offset;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, header_offset, chunk_size, sb->stream_size, sf_head, 1);
vgmstream->codec_data = init_ffmpeg_header_offset(sf_data, buf, bytes, start_offset, sb->stream_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf_head, sf_data, start_offset, sb->stream_size, header_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -301,9 +301,8 @@ VGMSTREAM* init_vgmstream_wbk_nslb(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
case 0x30: { /* RIFF XMA */
uint8_t buf[0x100];
off_t riff_fmt_offset, riff_data_offset;
size_t bytes, riff_fmt_size, riff_data_size;
size_t riff_fmt_size, riff_data_size;
sound_offset += 0x0c;
sound_size -= 0x0c;
@ -317,9 +316,8 @@ VGMSTREAM* init_vgmstream_wbk_nslb(STREAMFILE* sf) {
goto fail;
sound_offset = riff_data_offset;
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf, 0x100, riff_fmt_offset, riff_fmt_size, riff_data_size, sf, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, riff_data_offset, riff_data_size);
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, riff_data_offset, riff_data_size, riff_fmt_offset, riff_fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;

View File

@ -2,39 +2,39 @@
#include "../coding/coding.h"
/* ASTB - found in Dead Rising (X360) */
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_x360_ast(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, data_size;
int loop_flag, channel_count;
int loop_flag, channels;
int i, xma_streams;
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"ast"))
/* check */
if (!is_id32be(0x00,sf, "ASTB"))
goto fail;
if (!check_extensions(sf,"ast"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x41535442) /* "ASTB" */
if (read_u32be(0x04,sf) != get_streamfile_size(sf))
goto fail;
if (read_u16be(0x30,sf) != 0x165) /* only seen XMA1 */
goto fail;
if (read_32bitBE(0x04,streamFile) != get_streamfile_size(streamFile)) goto fail;
if (read_16bitBE(0x30,streamFile) != 0x165) goto fail; /* only seen XMA1 */
start_offset = read_u32be(0x10,sf);
data_size = read_u32be(0x20,sf);
xma_streams = read_u16be(0x38,sf);
xma_streams = read_16bitBE(0x38,streamFile);
loop_flag = read_8bit(0x3a,streamFile);
channel_count = 0; /* sum of all stream channels (though only 1/2ch ever seen) */
loop_flag = read_u8(0x3a,sf);
channels = 0; /* sum of all stream channels (though only 1/2ch ever seen) */
for (i = 0; i < xma_streams; i++) {
channel_count += read_8bit(0x3c + 0x14*i + 0x11,streamFile);
channels += read_u8(0x3c + 0x14 * i + 0x11,sf);
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
start_offset = read_32bitBE(0x10,streamFile);
data_size = read_32bitBE(0x20,streamFile);
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
vgmstream->sample_rate = read_s32be(0x40,sf);
vgmstream->meta_type = meta_X360_AST;
{
@ -42,16 +42,16 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
ms_sample_data msd = {0};
msd.xma_version = 1;
msd.channels = channel_count;
msd.channels = channels;
msd.data_offset = start_offset;
msd.data_size = data_size;
msd.loop_flag = loop_flag;
msd.loop_start_b = read_32bitBE(0x44,streamFile);
msd.loop_end_b = read_32bitBE(0x48,streamFile);
msd.loop_start_subframe = read_8bit(0x4c,streamFile) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
msd.loop_end_subframe = read_8bit(0x4c,streamFile) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
msd.loop_start_b = read_u32be(0x44,sf);
msd.loop_end_b = read_u32be(0x48,sf);
msd.loop_start_subframe = read_u8(0x4c,sf) & 0xF; /* lower 4b: subframe where the loop starts, 0..4 */
msd.loop_end_subframe = read_u8(0x4c,sf) >> 4; /* upper 4b: subframe where the loop ends, 0..3 */
xma_get_samples(&msd, streamFile);
xma_get_samples(&msd, sf);
vgmstream->num_samples = msd.num_samples;
vgmstream->loop_start_sample = msd.loop_start_sample;
vgmstream->loop_end_sample = msd.loop_end_sample;
@ -59,30 +59,24 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[100];
size_t bytes;
off_t fmt_offset = 0x30;
size_t fmt_size = 0x0c + xma_streams * 0x14;
/* 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);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, fmt_offset, fmt_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, fmt_offset, 1,1);
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, fmt_offset, 1,1);
}
#else
goto fail;
#endif
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;

View File

@ -2,36 +2,37 @@
#include "../coding/coding.h"
/* PASX - from Premium Agency games [SoulCalibur II HD (X360), Death By Cube (X360)] */
VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_x360_pasx(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, chunk_offset;
size_t data_size, chunk_size;
int loop_flag, channel_count, sample_rate;
int loop_flag, channels, sample_rate;
int num_samples, loop_start_sample, loop_end_sample;
/* checks */
if (!is_id32be(0x00,sf, "PASX"))
goto fail;
/* .past: Soul Calibur II HD
* .sgb: Death By Cube */
if ( !check_extensions(streamFile,"past,sgb"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x50415358) /* "PASX" */
if (!check_extensions(sf,"past,sgb"))
goto fail;
/* custom header with a "fmt " data chunk inside */
chunk_size = read_32bitBE(0x08,streamFile);
data_size = read_32bitBE(0x0c,streamFile);
chunk_offset = read_32bitBE(0x10,streamFile); /* 0x14: fmt offset end */
start_offset = read_32bitBE(0x18,streamFile);
chunk_size = read_32bitBE(0x08,sf);
data_size = read_32bitBE(0x0c,sf);
chunk_offset = read_32bitBE(0x10,sf); /* 0x14: fmt offset end */
start_offset = read_32bitBE(0x18,sf);
channel_count = read_16bitBE(chunk_offset+0x02,streamFile);
sample_rate = read_32bitBE(chunk_offset+0x04,streamFile);
xma2_parse_fmt_chunk_extra(streamFile, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
channels = read_16bitBE(chunk_offset+0x02,sf);
sample_rate = read_32bitBE(chunk_offset+0x04,sf);
xma2_parse_fmt_chunk_extra(sf, chunk_offset, &loop_flag, &num_samples, &loop_start_sample, &loop_end_sample, 1);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
@ -42,18 +43,12 @@ VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
{
uint8_t buf[0x100];
size_t bytes;
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);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->codec_data = init_ffmpeg_xma_chunk(sf, start_offset, data_size, chunk_offset, chunk_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, chunk_offset, 1,1);
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, chunk_offset, 1,1);
}
#else
goto fail;
@ -61,7 +56,7 @@ VGMSTREAM * init_vgmstream_x360_pasx(STREAMFILE *streamFile) {
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
if ( !vgmstream_open_stream(vgmstream, sf, start_offset) )
goto fail;
return vgmstream;