Updated VGMStream to r1050-873-ga4cf9afd.
parent
df85ce80cd
commit
cf8fd45f02
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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[] = {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue