mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-31 12:23:44 +01:00
Fix hang on full loops with xma1 formats
This commit is contained in:
parent
501af6ad8c
commit
2b0399d7f5
@ -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) */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -3,53 +3,53 @@
|
||||
#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;
|
||||
int codec;
|
||||
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
263
src/meta/gtd.c
263
src/meta/gtd.c
@ -1,136 +1,127 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
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;
|
||||
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 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"))
|
||||
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 */
|
||||
/* 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);
|
||||
|
||||
start_offset = read_32bitBE(0x58,streamFile); /* always 0x800 */
|
||||
data_size = read_32bitBE(0x5c,streamFile);
|
||||
/* 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" */
|
||||
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 */
|
||||
|
||||
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);
|
||||
loop_flag = loop_end_offset > loop_start_offset;
|
||||
at9_config_data = read_32bitBE(0x28,streamFile);
|
||||
/* 0x18-0x28: fixed/unknown values */
|
||||
|
||||
stpr_offset = 0x2c;
|
||||
if (read_32bitBE(stpr_offset,streamFile) == 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?) */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->loop_start_sample = loop_start_sample;
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case ATRAC9: {
|
||||
atrac9_config cfg = {0};
|
||||
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.config_data = at9_config_data;
|
||||
|
||||
vgmstream->codec_data = init_atrac9(&cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_ATRAC9;
|
||||
vgmstream->layout_type = layout_none;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = atrac9_bytes_to_samples(loop_start_offset - start_offset, vgmstream->codec_data);
|
||||
vgmstream->loop_end_sample = atrac9_bytes_to_samples(loop_end_offset - start_offset, vgmstream->codec_data);
|
||||
}
|
||||
vgmstream->num_samples = atrac9_bytes_to_samples(data_size, vgmstream->codec_data);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* open the file for reading */
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
typedef enum { XMA2, ATRAC9 } gtd_codec;
|
||||
|
||||
/* 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, channels, sample_rate;
|
||||
int num_samples, loop_start_sample, loop_end_sample;
|
||||
uint32_t at9_config_data;
|
||||
gtd_codec codec;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "GHS "))
|
||||
goto fail;
|
||||
if ( !check_extensions(sf,"gtd"))
|
||||
goto fail;
|
||||
|
||||
|
||||
/* header type, not formally specified */
|
||||
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;
|
||||
|
||||
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,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,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,sf) + read_32bitLE(0x0c,sf) == get_streamfile_size(sf)) { /* ATRAC9 */
|
||||
|
||||
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,sf);
|
||||
/* 0x18-0x28: fixed/unknown values */
|
||||
|
||||
stpr_offset = 0x2c;
|
||||
if (read_32bitBE(stpr_offset,sf) == 0x53545052) { /* "STPR" */
|
||||
name_offset = stpr_offset + 0xE8; /* there are offsets fields but seems to work */
|
||||
}
|
||||
|
||||
codec = ATRAC9;
|
||||
}
|
||||
else {
|
||||
/* there is a PS3 variation with MSF inside */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->loop_start_sample = loop_start_sample;
|
||||
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,sf);
|
||||
|
||||
switch(codec) {
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
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, sf, start_offset, data_size, chunk_offset, 1,1);
|
||||
break;
|
||||
#endif
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case ATRAC9: {
|
||||
atrac9_config cfg = {0};
|
||||
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.config_data = at9_config_data;
|
||||
|
||||
vgmstream->codec_data = init_atrac9(&cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_ATRAC9;
|
||||
vgmstream->layout_type = layout_none;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = atrac9_bytes_to_samples(loop_start_offset - start_offset, vgmstream->codec_data);
|
||||
vgmstream->loop_end_sample = atrac9_bytes_to_samples(loop_end_offset - start_offset, vgmstream->codec_data);
|
||||
}
|
||||
vgmstream->num_samples = atrac9_bytes_to_samples(data_size, vgmstream->codec_data);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1,89 +1,83 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* ASTB - found in Dead Rising (X360) */
|
||||
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, data_size;
|
||||
int loop_flag, channel_count;
|
||||
int i, xma_streams;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if ( !check_extensions(streamFile,"ast"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x41535442) /* "ASTB" */
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x04,streamFile) != get_streamfile_size(streamFile)) goto fail;
|
||||
if (read_16bitBE(0x30,streamFile) != 0x165) goto fail; /* only seen XMA1 */
|
||||
|
||||
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) */
|
||||
for (i = 0; i < xma_streams; i++) {
|
||||
channel_count += read_8bit(0x3c + 0x14*i + 0x11,streamFile);
|
||||
}
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,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->meta_type = meta_X360_AST;
|
||||
|
||||
{
|
||||
/* manually find sample offsets (XMA1 nonsense again) */
|
||||
ms_sample_data msd = {0};
|
||||
|
||||
msd.xma_version = 1;
|
||||
msd.channels = channel_count;
|
||||
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 */
|
||||
|
||||
xma_get_samples(&msd, streamFile);
|
||||
vgmstream->num_samples = msd.num_samples;
|
||||
vgmstream->loop_start_sample = msd.loop_start_sample;
|
||||
vgmstream->loop_end_sample = msd.loop_end_sample;
|
||||
}
|
||||
|
||||
#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->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
xma_fix_raw_samples(vgmstream, streamFile, 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) )
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* ASTB - found in Dead Rising (X360) */
|
||||
VGMSTREAM* init_vgmstream_x360_ast(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset, data_size;
|
||||
int loop_flag, channels;
|
||||
int i, xma_streams;
|
||||
|
||||
/* check */
|
||||
if (!is_id32be(0x00,sf, "ASTB"))
|
||||
goto fail;
|
||||
if (!check_extensions(sf,"ast"))
|
||||
goto fail;
|
||||
|
||||
if (read_u32be(0x04,sf) != get_streamfile_size(sf))
|
||||
goto fail;
|
||||
if (read_u16be(0x30,sf) != 0x165) /* only seen XMA1 */
|
||||
goto fail;
|
||||
|
||||
start_offset = read_u32be(0x10,sf);
|
||||
data_size = read_u32be(0x20,sf);
|
||||
xma_streams = read_u16be(0x38,sf);
|
||||
|
||||
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++) {
|
||||
channels += read_u8(0x3c + 0x14 * i + 0x11,sf);
|
||||
}
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_s32be(0x40,sf);
|
||||
vgmstream->meta_type = meta_X360_AST;
|
||||
|
||||
{
|
||||
/* manually find sample offsets (XMA1 nonsense again) */
|
||||
ms_sample_data msd = {0};
|
||||
|
||||
msd.xma_version = 1;
|
||||
msd.channels = channels;
|
||||
msd.data_offset = start_offset;
|
||||
msd.data_size = data_size;
|
||||
msd.loop_flag = loop_flag;
|
||||
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, sf);
|
||||
vgmstream->num_samples = msd.num_samples;
|
||||
vgmstream->loop_start_sample = msd.loop_start_sample;
|
||||
vgmstream->loop_end_sample = msd.loop_end_sample;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
off_t fmt_offset = 0x30;
|
||||
size_t fmt_size = 0x0c + xma_streams * 0x14;
|
||||
|
||||
/* XMA1 "fmt" chunk @ 0x20 (BE, unlike the usual LE) */
|
||||
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, sf, start_offset, data_size, fmt_offset, 1,1);
|
||||
}
|
||||
#else
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user