mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Fix multistream MPEG SCD [Final Fantaxy XIII-2 (PS3)]
This commit is contained in:
parent
5cc215b408
commit
b65765a56e
@ -18,6 +18,8 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
|
||||
}
|
||||
data->channels_per_frame = info.channels;
|
||||
data->samples_per_frame = info.frame_samples;
|
||||
data->bitrate_per_frame = info.bit_rate;
|
||||
data->sample_rate_per_frame = info.sample_rate;
|
||||
|
||||
|
||||
/* extra checks per type */
|
||||
@ -50,6 +52,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
|
||||
break;
|
||||
|
||||
case MPEG_P3D:
|
||||
case MPEG_SCD:
|
||||
if (data->config.interleave <= 0)
|
||||
goto fail; /* needs external fixed size */
|
||||
break;
|
||||
@ -127,9 +130,21 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
|
||||
break;
|
||||
|
||||
case MPEG_P3D: /* fixed interleave, not frame-aligned (ie. blocks may end/start in part of a frame) */
|
||||
current_data_size = data->config.interleave / 4; /* to ensure we don't feed mpg123 too much */
|
||||
current_interleave = data->config.interleave; /* fixed interleave (0x400) */
|
||||
//todo: last block is smaller that interleave, not sure how it's divided
|
||||
case MPEG_SCD:
|
||||
current_interleave = data->config.interleave;
|
||||
#if 0 //todo
|
||||
/* check if current interleave block is short */
|
||||
{
|
||||
off_t block_offset = stream->offset - stream->channel_start_offset;
|
||||
size_t next_block = data->streams_size*data->config.interleave;
|
||||
|
||||
if (data->config.data_size && block_offset + next_block >= data->config.data_size) {
|
||||
size_t short_interleave = (data->config.data_size % next_block) / data->streams_size;
|
||||
current_interleave = short_interleave;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
current_data_size = current_interleave;
|
||||
break;
|
||||
|
||||
default: /* standard frames (CBR or VBR) */
|
||||
@ -154,6 +169,26 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
|
||||
/* skip interleave once block is done, if defined */
|
||||
if (current_interleave && ((stream->offset - stream->channel_start_offset) % current_interleave == 0)) {
|
||||
stream->offset += current_interleave * (data->streams_size-1); /* skip a block each stream */
|
||||
|
||||
#if 0 //todo fix last block interleave
|
||||
int i;
|
||||
|
||||
/* skip other blocks one by one (to handle if next last block has short interleave) */
|
||||
for (i = 0; i < data->streams_size - 1; i++) {
|
||||
off_t block_offset = stream->offset - stream->channel_start_offset;
|
||||
size_t next_block = data->streams_size*data->config.interleave;
|
||||
|
||||
if (data->config.data_size && block_offset + next_block >= data->config.data_size) {
|
||||
/* other stream's data is in last block (short interleave) */
|
||||
size_t short_interleave = (data->config.data_size % next_block) / data->streams_size;
|
||||
stream->offset += short_interleave;
|
||||
}
|
||||
else {
|
||||
/* other stream's data is in normal block (regular interleave) */
|
||||
stream->offset += current_interleave;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -383,7 +383,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
|
||||
|
||||
/* extra EOF check for edge cases when the caller tries to read more samples than possible */
|
||||
if (!ms->buffer_full && stream->offset >= stream_size) {
|
||||
VGM_LOG("MPEG: EOF found but more data is requested\n");
|
||||
VGM_LOG("MPEG: EOF found but more data is requested in stream %i\n", num_stream);
|
||||
goto decode_fail;
|
||||
}
|
||||
|
||||
@ -603,7 +603,12 @@ long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data) {
|
||||
return (int64_t)bytes * data->mi.rate * 8 / (data->mi.bitrate * 1000);
|
||||
}
|
||||
else {
|
||||
return 0; /* a bit too complex for what is worth */
|
||||
/* needed for SCD */
|
||||
if (data->streams_size && data->bitrate_per_frame) {
|
||||
return (int64_t)(bytes / data->streams_size) * data->sample_rate_per_frame * 8 / (data->bitrate_per_frame * 1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,9 @@ static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, vo
|
||||
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset, tables_offset, headers_offset, meta_offset, post_meta_offset, stream_size;
|
||||
off_t start_offset, tables_offset, headers_offset, meta_offset, post_meta_offset;
|
||||
int headers_entries;
|
||||
int32_t loop_start, loop_end;
|
||||
int32_t stream_size, loop_start, loop_end;
|
||||
|
||||
int target_stream = streamFile->stream_index;
|
||||
int loop_flag = 0, channel_count, codec_id, sample_rate;
|
||||
@ -80,7 +80,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile);
|
||||
|
||||
/** stream header **/
|
||||
stream_size = read_32bit(meta_offset+0x00, streamFile);
|
||||
stream_size = read_32bit(meta_offset+0x00,streamFile);
|
||||
channel_count = read_32bit(meta_offset+0x04,streamFile);
|
||||
sample_rate = read_32bit(meta_offset+0x08,streamFile);
|
||||
codec_id = read_32bit(meta_offset+0x0c,streamFile);
|
||||
@ -200,12 +200,16 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06: /* OGG [Final Fantasy XIII-2 (PS3), Final Fantasy XIV (PC)] */
|
||||
case 0x06: /* OGG [Final Fantasy XIII-2 (PC), Final Fantasy XIV (PC)] */
|
||||
goto fail; /* handled above */
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
case 0x07: { /* MPEG [Final Fantasy XIII (PS3)] */
|
||||
mpeg_codec_data *mpeg_data = NULL;
|
||||
mpeg_custom_config cfg = {0};
|
||||
|
||||
cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)] */
|
||||
cfg.data_size = stream_size;
|
||||
|
||||
/* Drakengard 3, some Kingdom Hearts */
|
||||
if (vgmstream->sample_rate == 47999)
|
||||
@ -213,10 +217,13 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
if (vgmstream->sample_rate == 44099)
|
||||
vgmstream->sample_rate = 44100;
|
||||
|
||||
mpeg_data = init_mpeg_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels);
|
||||
|
||||
mpeg_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg);
|
||||
if (!mpeg_data) goto fail;
|
||||
vgmstream->codec_data = mpeg_data;
|
||||
vgmstream->layout_type = layout_none;
|
||||
/* to setup initial interleave in vgmstream_open_stream */
|
||||
vgmstream->layout_type = layout_mpeg_custom;
|
||||
vgmstream->interleave_block_size = cfg.interleave;
|
||||
|
||||
vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data);
|
||||
vgmstream->num_samples -= vgmstream->num_samples%576;
|
||||
@ -226,7 +233,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);
|
||||
vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576;
|
||||
}
|
||||
vgmstream->interleave_block_size = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -880,6 +880,7 @@ typedef enum {
|
||||
MPEG_XVAG, /* N streams of fixed interleave (frame-aligned, several data-frames of fixed size) */
|
||||
MPEG_FSB, /* N streams of 1 data-frame+padding (=interleave) */
|
||||
MPEG_P3D, /* N streams of fixed interleave (not frame-aligned) */
|
||||
MPEG_SCD, /* N streams of fixed interleave (not frame-aligned) */
|
||||
MPEG_EA, /* 1 stream (maybe N streams in absolute offsets?) */
|
||||
MPEG_EAL31, /* EALayer3 v1 (SCHl), custom frames with v1 header */
|
||||
MPEG_EAL31b, /* EALayer3 v1 (SNS), custom frames with v1 header + minor changes */
|
||||
@ -894,6 +895,7 @@ typedef struct {
|
||||
int channels; /* max channels */
|
||||
int fsb_padding; /* fsb padding mode */
|
||||
int chunk_size; /* size of a data portion */
|
||||
int data_size; /* playable size */
|
||||
int interleave; /* size of stream interleave */
|
||||
int encryption; /* encryption mode */
|
||||
int big_endian;
|
||||
@ -939,6 +941,9 @@ typedef struct {
|
||||
/* for internal use, assumed to be constant for all frames */
|
||||
int channels_per_frame;
|
||||
int samples_per_frame;
|
||||
/* for some calcs */
|
||||
int bitrate_per_frame;
|
||||
int sample_rate_per_frame;
|
||||
|
||||
/* custom MPEG internals */
|
||||
int custom; /* flag */
|
||||
|
Loading…
x
Reference in New Issue
Block a user