Updated VGMStream to r1050-873-ga4cf9afd.

CQTexperiment
Christopher Snowhill 2017-12-17 20:35:01 -08:00
parent df85ce80cd
commit cf8fd45f02
16 changed files with 107 additions and 91 deletions

View File

@ -18,6 +18,8 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
} }
data->channels_per_frame = info.channels; data->channels_per_frame = info.channels;
data->samples_per_frame = info.frame_samples; 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 */ /* extra checks per type */
@ -50,6 +52,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m
break; break;
case MPEG_P3D: case MPEG_P3D:
case MPEG_SCD:
if (data->config.interleave <= 0) if (data->config.interleave <= 0)
goto fail; /* needs external fixed size */ goto fail; /* needs external fixed size */
break; break;
@ -94,7 +97,9 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
mpeg_frame_info info; mpeg_frame_info info;
size_t current_data_size = 0; size_t current_data_size = 0;
size_t current_padding = 0; size_t current_padding = 0;
size_t current_interleave = 0; size_t current_interleave_pre = 0; /* interleaved data size before current stream */
size_t current_interleave_post = 0; /* interleaved data size after current stream */
size_t current_interleave = 0; /* interleave in this block (usually this + pre + post = interleave*streams = block) */
/* Get data size to give to the decoder, per stream. Usually 1 frame at a time, /* Get data size to give to the decoder, per stream. Usually 1 frame at a time,
@ -102,11 +107,18 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
switch(data->type) { switch(data->type) {
case MPEG_XVAG: /* frames of fixed size (though we could read frame info too) */ case MPEG_XVAG: /* frames of fixed size (though we could read frame info too) */
current_data_size = data->config.chunk_size;
current_interleave = data->config.interleave; /* big interleave */ current_interleave = data->config.interleave; /* big interleave */
current_interleave_pre = current_interleave*num_stream;
current_interleave_post = current_interleave*(data->streams_size-1) - current_interleave_pre;
current_data_size = data->config.chunk_size;
break; break;
case MPEG_FSB: /* frames with padding + interleave */ case MPEG_FSB: /* frames with padding + interleave */
current_interleave = data->config.interleave; /* constant for multi-stream FSbs (1 frame + padding) */
current_interleave_pre = current_interleave*num_stream;
current_interleave_post = current_interleave*(data->streams_size-1) - current_interleave_pre;
if ( !mpeg_get_frame_info(stream->streamfile, stream->offset, &info) ) if ( !mpeg_get_frame_info(stream->streamfile, stream->offset, &info) )
goto fail; goto fail;
current_data_size = info.frame_size; current_data_size = info.frame_size;
@ -119,17 +131,28 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
: 0; : 0;
} }
/* frame interleave (ie. read 1 data-frame, skip 1 data-frame per stream) */
current_interleave = data->config.interleave; /* constant for multi-stream FSbs */
VGM_ASSERT(data->streams_size > 1 && current_interleave != current_data_size+current_padding, VGM_ASSERT(data->streams_size > 1 && current_interleave != current_data_size+current_padding,
"MPEG FSB: %i streams with non-constant interleave found @ 0x%08lx\n", data->streams_size, stream->offset); "MPEG FSB: %i streams with non-constant interleave found @ 0x%08lx\n", data->streams_size, stream->offset);
break; break;
case MPEG_P3D: /* fixed interleave, not frame-aligned (ie. blocks may end/start in part of a frame) */ 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 */ case MPEG_SCD:
current_interleave = data->config.interleave; /* fixed interleave (0x400) */ current_interleave = data->config.interleave;
//todo: last block is smaller that interleave, not sure how it's divided
#if 1
/* 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)
current_interleave = (data->config.data_size % next_block) / data->streams_size; /* short_interleave*/
}
#endif
current_interleave_pre = current_interleave*num_stream;
current_interleave_post = current_interleave*(data->streams_size-1) - current_interleave_pre;
current_data_size = current_interleave;
break; break;
default: /* standard frames (CBR or VBR) */ default: /* standard frames (CBR or VBR) */
@ -143,19 +166,26 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
goto fail; goto fail;
} }
/* This assumes all streams' offsets start in the first stream, and advances
* the 'full interleaved block' at once, ex:
* start at s0=0x00, s1=0x00, interleave=0x40 (block = 0x40*2=0x80)
* @0x00 read 0x40 of s0, skip 0x40 of s1 (block of 0x80 done) > new offset = 0x80
* @0x00 skip 0x40 of s0, read 0x40 of s1 (block of 0x80 done) > new offset = 0x800
*/
/* read single frame */ /* read chunk (skipping other interleaves if needed) */
ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset, current_data_size, stream->streamfile); ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset + current_interleave_pre, current_data_size, stream->streamfile);
/* update offsets */ /* update offsets and skip other streams */
stream->offset += current_data_size + current_padding; stream->offset += current_data_size + current_padding;
/* skip interleave once block is done, if defined */ /* skip rest of block (interleave per stream) once this stream's interleaved data is done, if defined */
if (current_interleave && ((stream->offset - stream->channel_start_offset) % current_interleave == 0)) { if (current_interleave && ((stream->offset - stream->channel_start_offset + current_interleave_pre + current_interleave_post) % current_interleave == 0)) {
stream->offset += current_interleave * (data->streams_size-1); /* skip a block each stream */ stream->offset += current_interleave_pre + current_interleave_post;
} }
return 1; return 1;
fail: fail:
return 0; return 0;

View File

@ -150,6 +150,8 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
} }
// todo rarely there is a block between granules (ex. EAL3 v2P in FIFA 2016)
/* get second frame/granule (MPEG1 only) if first granule was found */ /* get second frame/granule (MPEG1 only) if first granule was found */
granule_found = 0; granule_found = 0;
while (eaf_0.common_size && eaf_0.mpeg1 && !granule_found) { while (eaf_0.common_size && eaf_0.mpeg1 && !granule_found) {
@ -665,6 +667,7 @@ static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, i
if (!ok) goto fail; if (!ok) goto fail;
stream->offset += eaf.eaframe_size; stream->offset += eaf.eaframe_size;
//;VGM_LOG("s%i: skipping %x, now at %lx\n", num_stream,eaf.eaframe_size,stream->offset);
} }
//;VGM_LOG("s%i: skipped %i frames, now at %lx\n", num_stream,skips,stream->offset); //;VGM_LOG("s%i: skipped %i frames, now at %lx\n", num_stream,skips,stream->offset);

View File

@ -166,9 +166,6 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start
} }
/* write output */
config->interleave = data->config.interleave; /* for FSB */
return data; return data;
fail: fail:
@ -382,7 +379,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 */ /* extra EOF check for edge cases when the caller tries to read more samples than possible */
if (!ms->buffer_full && stream->offset >= stream_size) { 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; goto decode_fail;
} }
@ -602,7 +599,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); return (int64_t)bytes * data->mi.rate * 8 / (data->mi.bitrate * 1000);
} }
else { 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;
} }
} }

View File

@ -162,6 +162,7 @@ static const char* extension_list[] = {
"leg", "leg",
"lmp4", //fake extension, for MP4s "lmp4", //fake extension, for MP4s
"logg", //fake extension, for OGGs "logg", //fake extension, for OGGs
"lopus", //fake extension, for OPUS
"lpcm", "lpcm",
"lps", "lps",
"lsf", "lsf",
@ -569,9 +570,6 @@ static const layout_info layout_info_list[] = {
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
{layout_ogg_vorbis, "Ogg"}, {layout_ogg_vorbis, "Ogg"},
#endif #endif
#ifdef VGM_USE_MPEG
{layout_mpeg_custom, "Custom MPEG Audio"},
#endif
}; };
static const meta_info meta_info_list[] = { static const meta_info meta_info_list[] = {

View File

@ -2,7 +2,7 @@
#include "../coding/coding.h" #include "../coding/coding.h"
#include "../vgmstream.h" #include "../vgmstream.h"
/* EA "SNS "blocks (most common in .SNS) */ /* EA SNS/SPS blocks */
void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) { void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile; STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
uint32_t block_size, block_samples; uint32_t block_size, block_samples;
@ -21,16 +21,10 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
return; return;
} }
/* 0x80: last block /* At 0x00(1): block flag
* 0x40: new block for some codecs? * - in SNS: 0x00=normal block, 0x80=last block (not mandatory)
* 0x08: ? * - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */
* 0x04: new block for some codecs? block_size &= 0x00FFFFFF;
* 0x01: last block for some codecs?
* 0x00: none? */
if (block_size & 0xFF000000) {
//VGM_ASSERT(!(block_size & 0x80000000), "EA SNS: unknown flag found at %lx\n", block_offset);
block_size &= 0x00FFFFFF;
}
for (i = 0; i < vgmstream->channels; i++) { for (i = 0; i < vgmstream->channels; i++) {
off_t channel_start = 0x00; off_t channel_start = 0x00;

View File

@ -3,7 +3,9 @@
/* Tests each start/mult/add vs derived key8/9 (if provided), as most where brute forced. /* Tests each start/mult/add vs derived key8/9 (if provided), as most where brute forced.
* Mainly for debugging purposes (info from VGAudio / ADX_Decoder) */ * Ie. uncommenting this and adding a new key8/key9 + compiling with VGM_DEBUG_OUTPUT
* will print its derived key (useful as games often use the same key for hca and adx type 9).
* Mainly for debugging purposes (info from VGAudio / ADX_Decoder). */
//#define ADX_VERIFY_DERIVED_KEYS 1 //#define ADX_VERIFY_DERIVED_KEYS 1
@ -199,6 +201,9 @@ static const adxkey_info adxkey9_list[] = {
/* Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android) */ /* Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android) */
{0x3f10,0x3651,0x6d31, NULL,4867249871962584729}, // 438BF1F883653699 {0x3f10,0x3651,0x6d31, NULL,4867249871962584729}, // 438BF1F883653699
// Super Robot Wars X-Omega (voices) [iOS/Android]
{0x5152,0x7979,0x152b, NULL,165521992944278}, // 0000968A97978A96
}; };
static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]); static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]);

View File

@ -48,12 +48,10 @@ VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile) {
if (!check_extensions(streamFile,"sps")) if (!check_extensions(streamFile,"sps"))
goto fail; goto fail;
/* Very hacky but the original check for 0x48000000 rejected some playable files */ /* SPS block start: 0x00(1): block flag (header=0x48); 0x01(3): block size (usually 0x0c-0x14) */
if (((read_16bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x4800) && if (read_8bit(0x00, streamFile) != 0x48)
((read_8bit(0x00, streamFile) & 0xFFFFFF00) != 0x00))
goto fail; goto fail;
start_offset = read_32bitBE(0x00, streamFile) & 0x00FFFFFF;
start_offset = read_8bit(0x03, streamFile);
vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x04, start_offset, meta_EA_SPS); vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x04, start_offset, meta_EA_SPS);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;

View File

@ -287,9 +287,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
if (fsbh.mode & FSOUND_MPEG) { if (fsbh.mode & FSOUND_MPEG) {
/* FSB3: ?; FSB4: Shatter, Way of the Samurai 3/4, Forza Horizon 1/2, Dragon Age Origins */ /* FSB3: ?; FSB4: Shatter, Way of the Samurai 3/4, Forza Horizon 1/2, Dragon Age Origins */
#if defined(VGM_USE_MPEG) #if defined(VGM_USE_MPEG)
mpeg_custom_config cfg; mpeg_custom_config cfg = {0};
memset(&cfg, 0, sizeof(mpeg_custom_config));
cfg.fsb_padding = (vgmstream->channels > 2 ? 16 : cfg.fsb_padding = (vgmstream->channels > 2 ? 16 :
(fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED4 ? 4 : (fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED4 ? 4 :
(fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED ? 2 : 0))); (fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED ? 2 : 0)));
@ -299,10 +298,7 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg); vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
/* both to setup initial interleave in vgmstream_open_stream */
vgmstream->interleave_block_size = cfg.interleave;
vgmstream->layout_type = layout_mpeg_custom;
#else #else
goto fail; /* FFmpeg can't properly read FSB4 or FMOD's 0-padded MPEG data @ start_offset */ goto fail; /* FFmpeg can't properly read FSB4 or FMOD's 0-padded MPEG data @ start_offset */

View File

@ -265,10 +265,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, StartOffset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg); vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, StartOffset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
/* both to setup initial interleave in vgmstream_open_stream */
vgmstream->interleave_block_size = cfg.interleave;
vgmstream->layout_type = layout_mpeg_custom;
break; break;
} }
#endif #endif

View File

@ -144,6 +144,9 @@ static const hcakey_info hcakey_list[] = {
// Pro Evolution Soccer 2018 / Winning Eleven 2018 (Android) // Pro Evolution Soccer 2018 / Winning Eleven 2018 (Android)
{14121473}, // 0000000000D77A01 {14121473}, // 0000000000D77A01
// Kirara Fantasia (Android/iOS)
{51408295487268137}, // 00B6A3928706E529
}; };

View File

@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) {
off_t offset = 0; off_t offset = 0;
/* check extension, case insensitive */ /* check extension, case insensitive */
if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */ if ( !check_extensions(streamFile,"opus,lopus")) /* no relation to Ogg Opus */
goto fail; goto fail;
/* variations, maybe custom */ /* variations, maybe custom */

View File

@ -145,18 +145,15 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case 0x6D703300: { /* "mp3\0" (PS3) */ case 0x6D703300: { /* "mp3\0" (PS3) */
mpeg_custom_config cfg; mpeg_custom_config cfg = {0};
memset(&cfg, 0, sizeof(mpeg_custom_config));
cfg.interleave = 0x400; cfg.interleave = 0x400;
cfg.data_size = data_size;
/* block_size * 3 = frame size (0x60*3=0x120 or 0x40*3=0xC0) but doesn't seem to have any significance) */ /* block_size * 3 = frame size (0x60*3=0x120 or 0x40*3=0xC0) but doesn't seem to have any significance) */
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_P3D, &cfg); vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_P3D, &cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
/* both to setup initial interleave in vgmstream_open_stream */
vgmstream->interleave_block_size = cfg.interleave;
vgmstream->layout_type = layout_mpeg_custom;
break; break;
} }
#endif #endif

View File

@ -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 * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; 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; int headers_entries;
int32_t loop_start, loop_end; int32_t stream_size, loop_start, loop_end;
int target_stream = streamFile->stream_index; int target_stream = streamFile->stream_index;
int loop_flag = 0, channel_count, codec_id, sample_rate; 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); meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile);
/** stream header **/ /** 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); channel_count = read_32bit(meta_offset+0x04,streamFile);
sample_rate = read_32bit(meta_offset+0x08,streamFile); sample_rate = read_32bit(meta_offset+0x08,streamFile);
codec_id = read_32bit(meta_offset+0x0c,streamFile); codec_id = read_32bit(meta_offset+0x0c,streamFile);
@ -200,33 +200,33 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
} }
break; 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 */ goto fail; /* handled above */
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case 0x07: { /* MPEG [Final Fantasy XIII (PS3)] */ case 0x07: { /* MPEG [Final Fantasy XIII (PS3)] */
mpeg_codec_data *mpeg_data = NULL; mpeg_codec_data *mpeg_data = NULL;
mpeg_custom_config cfg = {0};
/* Drakengard 3, some Kingdom Hearts */ cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */
if (vgmstream->sample_rate == 47999) cfg.data_size = stream_size;
vgmstream->sample_rate = 48000;
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; if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data; vgmstream->codec_data = mpeg_data;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* some Drakengard 3, Kingdom Hearts HD have adjusted sample rate (47999, 44099), for looping? */
vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data); vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data);
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data);
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);
//todo find if this actually helps
vgmstream->num_samples -= vgmstream->num_samples%576; vgmstream->num_samples -= vgmstream->num_samples%576;
if (loop_flag) { vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576;
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data); vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576;
vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576;
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; break;
} }
#endif #endif

View File

@ -82,25 +82,19 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case 0x08: { /* MPEG: The Last of Us, Uncharted 3, Medieval Moves */ case 0x08: { /* MPEG: The Last of Us, Uncharted 3, Medieval Moves */
mpeg_custom_config cfg; mpeg_custom_config cfg = {0};
int fixed_frame_size;
memset(&cfg, 0, sizeof(mpeg_custom_config));
/* "mpin": mpeg info */ /* "mpin": mpeg info */
/* 0x00/04: mpeg version/layer? other: unknown or repeats of "fmat" */ /* 0x00/04: mpeg version/layer? other: unknown or repeats of "fmat" */
if (!find_chunk(streamFile, 0x6D70696E,first_offset,0, &chunk_offset,NULL, !little_endian, 1)) goto fail; /*"mpin"*/ if (!find_chunk(streamFile, 0x6D70696E,first_offset,0, &chunk_offset,NULL, !little_endian, 1))
fixed_frame_size = read_32bit(chunk_offset+0x1c,streamFile); goto fail; /*"mpin"*/
cfg.chunk_size = fixed_frame_size; cfg.chunk_size = read_32bit(chunk_offset+0x1c,streamFile); /* fixed frame size */
cfg.interleave = fixed_frame_size * multiplier; cfg.interleave = cfg.chunk_size * multiplier;
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_XVAG, &cfg); vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_XVAG, &cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->layout_type = layout_none;
/* both to setup initial interleave in vgmstream_open_stream */
vgmstream->interleave_block_size = cfg.interleave;
vgmstream->layout_type = layout_mpeg_custom;
break; break;
} }
#endif #endif

View File

@ -922,9 +922,6 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
break; break;
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
case layout_ogg_vorbis: case layout_ogg_vorbis:
#endif
#ifdef VGM_USE_MPEG
case layout_mpeg_custom:
#endif #endif
case layout_none: case layout_none:
render_vgmstream_nolayout(buffer,sample_count,vgmstream); render_vgmstream_nolayout(buffer,sample_count,vgmstream);

View File

@ -262,9 +262,6 @@ typedef enum {
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
layout_ogg_vorbis, /* ogg vorbis file */ layout_ogg_vorbis, /* ogg vorbis file */
#endif #endif
#ifdef VGM_USE_MPEG
layout_mpeg_custom, /* usually straight data but may setup offset/interleave somehow */
#endif
} layout_t; } layout_t;
/* The meta type specifies how we know what we know about the file. /* The meta type specifies how we know what we know about the file.
@ -888,6 +885,7 @@ typedef enum {
MPEG_XVAG, /* N streams of fixed interleave (frame-aligned, several data-frames of fixed size) */ 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_FSB, /* N streams of 1 data-frame+padding (=interleave) */
MPEG_P3D, /* N streams of fixed interleave (not frame-aligned) */ 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_EA, /* 1 stream (maybe N streams in absolute offsets?) */
MPEG_EAL31, /* EALayer3 v1 (SCHl), custom frames with v1 header */ MPEG_EAL31, /* EALayer3 v1 (SCHl), custom frames with v1 header */
MPEG_EAL31b, /* EALayer3 v1 (SNS), custom frames with v1 header + minor changes */ MPEG_EAL31b, /* EALayer3 v1 (SNS), custom frames with v1 header + minor changes */
@ -902,6 +900,7 @@ typedef struct {
int channels; /* max channels */ int channels; /* max channels */
int fsb_padding; /* fsb padding mode */ int fsb_padding; /* fsb padding mode */
int chunk_size; /* size of a data portion */ int chunk_size; /* size of a data portion */
int data_size; /* playable size */
int interleave; /* size of stream interleave */ int interleave; /* size of stream interleave */
int encryption; /* encryption mode */ int encryption; /* encryption mode */
int big_endian; int big_endian;
@ -947,6 +946,9 @@ typedef struct {
/* for internal use, assumed to be constant for all frames */ /* for internal use, assumed to be constant for all frames */
int channels_per_frame; int channels_per_frame;
int samples_per_frame; int samples_per_frame;
/* for some calcs */
int bitrate_per_frame;
int sample_rate_per_frame;
/* custom MPEG internals */ /* custom MPEG internals */
int custom; /* flag */ int custom; /* flag */