mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +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;
|
} eaac_header;
|
||||||
|
|
||||||
static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *streamData, eaac_header *eaac);
|
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).
|
/* 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) */
|
/* rest is optional, depends on used flags and codec (handled below) */
|
||||||
eaac.stream_offset = start_offset;
|
eaac.stream_offset = start_offset;
|
||||||
|
|
||||||
|
|
||||||
/* V0: SNR+SNS, V1: SPR+SPS (no apparent differences, other than block flags) */
|
/* V0: SNR+SNS, V1: SPR+SPS (no apparent differences, other than block flags) */
|
||||||
if (eaac.version != EAAC_VERSION_V0 && eaac.version != EAAC_VERSION_V1) {
|
if (eaac.version != EAAC_VERSION_V0 && eaac.version != EAAC_VERSION_V1) {
|
||||||
VGM_LOG("EA EAAC: unknown version\n");
|
VGM_LOG("EA EAAC: unknown version\n");
|
||||||
@ -586,28 +586,10 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
|
|||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
case EAAC_CODEC_EAXMA: { /* "EXm0": EA-XMA [Dante's Inferno (X360)] */
|
case EAAC_CODEC_EAXMA: { /* "EXm0": EA-XMA [Dante's Inferno (X360)] */
|
||||||
uint8_t buf[0x100];
|
vgmstream->layout_data = build_layered_eaaudiocore_eaxma(streamData, &eaac);
|
||||||
int bytes, block_size, block_count;
|
if (!vgmstream->layout_data) goto fail;
|
||||||
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->coding_type = coding_FFmpeg;
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
vgmstream->layout_type = layout_none;
|
vgmstream->layout_type = layout_layered;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -783,3 +765,69 @@ fail:
|
|||||||
free_layout_segmented(data);
|
free_layout_segmented(data);
|
||||||
return NULL;
|
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) {
|
switch(data->codec) {
|
||||||
#if 0
|
|
||||||
case 0x03: { /* EA-XMA */
|
case 0x03: { /* EA-XMA */
|
||||||
/* block format: 0x04=num-samples, (size*4 + N XMA packets) per stream (with 1/2ch XMA headers) */
|
/* block format: 0x04=num-samples, (size*4 + N XMA packets) per stream (with 1/2ch XMA headers) */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
data->skip_size = 0x04 + 0x04;
|
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->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...? */
|
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);
|
data->extra_size = XMA_FRAME_SIZE - (data->data_size % XMA_FRAME_SIZE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
case 0x05: /* EALayer3 v1 */
|
case 0x05: /* EALayer3 v1 */
|
||||||
case 0x06: /* EALayer3 v2 "PCM" */
|
case 0x06: /* EALayer3 v2 "PCM" */
|
||||||
case 0x07: /* EALayer3 v2 "Spike" */
|
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;
|
bytes_consumed = offset - data->logical_offset;
|
||||||
|
|
||||||
switch(data->codec) {
|
switch(data->codec) {
|
||||||
#if 0
|
|
||||||
case 0x03: { /* EA-XMA */
|
case 0x03: { /* EA-XMA */
|
||||||
if (bytes_consumed < data->data_size) { /* offset falls within actual data */
|
if (bytes_consumed < data->data_size) { /* offset falls within actual data */
|
||||||
to_read = data->data_size - bytes_consumed;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
to_read = data->data_size - bytes_consumed;
|
to_read = data->data_size - bytes_consumed;
|
||||||
if (to_read > length)
|
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 */
|
/* get size of the logical stream */
|
||||||
while (physical_offset < max_physical_offset) {
|
while (physical_offset < max_physical_offset) {
|
||||||
uint32_t block_flag, block_size, data_size, skip_size;
|
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_flag = (uint8_t)read_8bit(physical_offset+0x00,streamfile);
|
||||||
block_size = read_32bitBE(physical_offset+0x00,streamfile) & 0x00FFFFFF;
|
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 */
|
break; /* unknown block */
|
||||||
|
|
||||||
switch(data->codec) {
|
switch(data->codec) {
|
||||||
#if 0
|
|
||||||
case 0x03: /* EA-XMA */
|
case 0x03: /* EA-XMA */
|
||||||
skip_size = 0x04 + 0x04;
|
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...? */
|
skip_size += read_32bitBE(physical_offset + skip_size, streamfile) / 4; /* why size*4...? */
|
||||||
}
|
}
|
||||||
data_size = read_32bitBE(physical_offset + skip_size, streamfile) / 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)
|
if (data_size % XMA_FRAME_SIZE)
|
||||||
data_size += XMA_FRAME_SIZE - (data_size % XMA_FRAME_SIZE); /* extra padding */
|
data_size += XMA_FRAME_SIZE - (data_size % XMA_FRAME_SIZE); /* extra padding */
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case 0x05: /* EALayer3 v1 */
|
case 0x05: /* EALayer3 v1 */
|
||||||
case 0x06: /* EALayer3 v2 "PCM" */
|
case 0x06: /* EALayer3 v2 "PCM" */
|
||||||
case 0x07: /* EALayer3 v2 "Spike" */
|
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 */
|
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;
|
data->logical_size = logical_size;
|
||||||
return data->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.physical_offset = stream_offset;
|
||||||
io_data.logical_size = eaac_io_size(streamFile, &io_data); /* force init */
|
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 */
|
/* setup subfile */
|
||||||
new_streamFile = open_wrap_streamfile(streamFile);
|
new_streamFile = open_wrap_streamfile(streamFile);
|
||||||
if (!new_streamFile) goto fail;
|
if (!new_streamFile) goto fail;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user