mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Redo EA-XMA with custom IO for fixes [Skate (X360), NFS: MW (X360)]
This commit is contained in:
parent
d8758f0cb5
commit
e3255344cf
@ -483,6 +483,7 @@ typedef struct {
|
||||
} eaac_header;
|
||||
|
||||
static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *streamData, eaac_header *eaac);
|
||||
static layered_layout_data* build_layered_eaaudiocore_eaxma(STREAMFILE *streamFile, eaac_header *eaac);
|
||||
|
||||
|
||||
/* EA newest header from RwAudioCore (RenderWare?) / EAAudioCore library (still generated by sx.exe).
|
||||
@ -508,7 +509,6 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
|
||||
/* rest is optional, depends on used flags and codec (handled below) */
|
||||
eaac.stream_offset = start_offset;
|
||||
|
||||
|
||||
/* V0: SNR+SNS, V1: SPR+SPS (no apparent differences, other than block flags) */
|
||||
if (eaac.version != EAAC_VERSION_V0 && eaac.version != EAAC_VERSION_V1) {
|
||||
VGM_LOG("EA EAAC: unknown version\n");
|
||||
@ -586,28 +586,10 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case EAAC_CODEC_EAXMA: { /* "EXm0": EA-XMA [Dante's Inferno (X360)] */
|
||||
uint8_t buf[0x100];
|
||||
int bytes, block_size, block_count;
|
||||
size_t stream_size, virtual_size;
|
||||
ffmpeg_custom_config cfg = {0};
|
||||
|
||||
stream_size = get_streamfile_size(streamData) - eaac.stream_offset; //todo not correct for banks
|
||||
virtual_size = ffmpeg_get_eaxma_virtual_size(vgmstream->channels, eaac.streamed, eaac.stream_offset,stream_size, streamData);
|
||||
block_size = 0x10000; /* todo unused and not correctly done by the parser */
|
||||
block_count = stream_size / block_size + (stream_size % block_size ? 1 : 0);
|
||||
|
||||
bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, virtual_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
cfg.type = FFMPEG_EA_XMA;
|
||||
cfg.virtual_size = virtual_size;
|
||||
cfg.channels = vgmstream->channels;
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_config(streamData, buf,bytes, eaac.stream_offset,stream_size, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
||||
vgmstream->layout_data = build_layered_eaaudiocore_eaxma(streamData, &eaac);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -783,3 +765,69 @@ fail:
|
||||
free_layout_segmented(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static layered_layout_data* build_layered_eaaudiocore_eaxma(STREAMFILE *streamData, eaac_header *eaac) {
|
||||
layered_layout_data* data = NULL;
|
||||
STREAMFILE* temp_streamFile = NULL;
|
||||
int i, layers = (eaac->channels+1) / 2;
|
||||
|
||||
|
||||
/* init layout */
|
||||
data = init_layout_layered(layers);
|
||||
if (!data) goto fail;
|
||||
|
||||
/* open each layer subfile (1/2ch streams: 2ch+2ch..+1ch or 2ch+2ch..+2ch).
|
||||
* EA-XMA uses completely separate 1/2ch streams, unlike standard XMA that interleaves 1/2ch streams
|
||||
* with a skip counter to reinterleave (so EA-XMA streams don't have skips set) */
|
||||
for (i = 0; i < layers; i++) {
|
||||
int layer_channels = (i+1 == layers && eaac->channels % 2 == 1) ? 1 : 2; /* last layer can be 1/2ch */
|
||||
|
||||
/* build the layer VGMSTREAM */
|
||||
data->layers[i] = allocate_vgmstream(layer_channels, eaac->loop_flag);
|
||||
if (!data->layers[i]) goto fail;
|
||||
|
||||
data->layers[i]->sample_rate = eaac->sample_rate;
|
||||
data->layers[i]->num_samples = eaac->num_samples;
|
||||
data->layers[i]->loop_start_sample = eaac->loop_start;
|
||||
data->layers[i]->loop_end_sample = eaac->loop_end;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
uint8_t buf[0x100];
|
||||
int bytes, block_size, block_count;
|
||||
size_t stream_size;
|
||||
|
||||
temp_streamFile = setup_eaac_streamfile(streamData, eaac->version, eaac->codec, eaac->streamed,i,layers, eaac->stream_offset);
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
stream_size = get_streamfile_size(temp_streamFile);
|
||||
block_size = 0x10000; /* unused */
|
||||
block_count = stream_size / block_size + (stream_size % block_size ? 1 : 0);
|
||||
|
||||
bytes = ffmpeg_make_riff_xma2(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, block_count, block_size);
|
||||
data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_streamFile, buf,bytes, 0x00, stream_size);
|
||||
if (!data->layers[i]->codec_data) goto fail;
|
||||
|
||||
data->layers[i]->coding_type = coding_FFmpeg;
|
||||
data->layers[i]->layout_type = layout_none;
|
||||
}
|
||||
#else
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
if ( !vgmstream_open_stream(data->layers[i], temp_streamFile, 0x00) ) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* setup layered VGMSTREAMs */
|
||||
if (!setup_layout_layered(data))
|
||||
goto fail;
|
||||
close_streamfile(temp_streamFile);
|
||||
return data;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
free_layout_layered(data);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -66,13 +66,12 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
|
||||
}
|
||||
|
||||
switch(data->codec) {
|
||||
#if 0
|
||||
case 0x03: { /* EA-XMA */
|
||||
/* block format: 0x04=num-samples, (size*4 + N XMA packets) per stream (with 1/2ch XMA headers) */
|
||||
int i;
|
||||
|
||||
data->skip_size = 0x04 + 0x04;
|
||||
for (i = 0; i < data->stream_number - 1; i++) {
|
||||
for (i = 0; i < data->stream_number; i++) {
|
||||
data->skip_size += read_32bitBE(data->physical_offset+data->skip_size, streamfile) / 4;
|
||||
}
|
||||
data->data_size = read_32bitBE(data->physical_offset+data->skip_size, streamfile) / 4; /* why size*4...? */
|
||||
@ -82,7 +81,7 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
|
||||
data->extra_size = XMA_FRAME_SIZE - (data->data_size % XMA_FRAME_SIZE);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case 0x05: /* EALayer3 v1 */
|
||||
case 0x06: /* EALayer3 v2 "PCM" */
|
||||
case 0x07: /* EALayer3 v2 "Spike" */
|
||||
@ -121,7 +120,6 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
|
||||
bytes_consumed = offset - data->logical_offset;
|
||||
|
||||
switch(data->codec) {
|
||||
#if 0
|
||||
case 0x03: { /* EA-XMA */
|
||||
if (bytes_consumed < data->data_size) { /* offset falls within actual data */
|
||||
to_read = data->data_size - bytes_consumed;
|
||||
@ -138,7 +136,7 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
to_read = data->data_size - bytes_consumed;
|
||||
if (to_read > length)
|
||||
@ -175,7 +173,7 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) {
|
||||
/* get size of the logical stream */
|
||||
while (physical_offset < max_physical_offset) {
|
||||
uint32_t block_flag, block_size, data_size, skip_size;
|
||||
//int i;
|
||||
int i;
|
||||
|
||||
block_flag = (uint8_t)read_8bit(physical_offset+0x00,streamfile);
|
||||
block_size = read_32bitBE(physical_offset+0x00,streamfile) & 0x00FFFFFF;
|
||||
@ -193,10 +191,9 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) {
|
||||
break; /* unknown block */
|
||||
|
||||
switch(data->codec) {
|
||||
#if 0
|
||||
case 0x03: /* EA-XMA */
|
||||
skip_size = 0x04 + 0x04;
|
||||
for (i = 0; i < data->stream_number - 1; i++) {
|
||||
for (i = 0; i < data->stream_number; i++) {
|
||||
skip_size += read_32bitBE(physical_offset + skip_size, streamfile) / 4; /* why size*4...? */
|
||||
}
|
||||
data_size = read_32bitBE(physical_offset + skip_size, streamfile) / 4;
|
||||
@ -205,7 +202,7 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) {
|
||||
if (data_size % XMA_FRAME_SIZE)
|
||||
data_size += XMA_FRAME_SIZE - (data_size % XMA_FRAME_SIZE); /* extra padding */
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 0x05: /* EALayer3 v1 */
|
||||
case 0x06: /* EALayer3 v2 "PCM" */
|
||||
case 0x07: /* EALayer3 v2 "Spike" */
|
||||
@ -239,6 +236,12 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) {
|
||||
break; /* stop on last block */
|
||||
}
|
||||
|
||||
/* logical size can be bigger in EA-XMA though */
|
||||
if (physical_offset > get_streamfile_size(streamfile)) {
|
||||
VGM_LOG("EA EAAC: wrong size %lx\n", physical_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data->logical_size = logical_size;
|
||||
return data->logical_size;
|
||||
}
|
||||
@ -264,11 +267,6 @@ static STREAMFILE* setup_eaac_streamfile(STREAMFILE *streamFile, int version, in
|
||||
io_data.physical_offset = stream_offset;
|
||||
io_data.logical_size = eaac_io_size(streamFile, &io_data); /* force init */
|
||||
|
||||
if (io_data.logical_size > get_streamfile_size(streamFile)) {
|
||||
VGM_LOG("EA EAAC: wrong logical size\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* setup subfile */
|
||||
new_streamFile = open_wrap_streamfile(streamFile);
|
||||
if (!new_streamFile) goto fail;
|
||||
|
Loading…
x
Reference in New Issue
Block a user