Updated VGMStream to r1050-2066-g3dc52c5f

CQTexperiment
Chris Moeller 2019-02-12 00:05:35 -08:00
parent 451e508939
commit e76c1966c6
28 changed files with 3049 additions and 1347 deletions

View File

@ -210,6 +210,10 @@
835027131ED119E000C25929 /* mta2_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 835027121ED119E000C25929 /* mta2_decoder.c */; };
8350C0551E071881009E0A93 /* xma.c in Sources */ = {isa = PBXBuildFile; fileRef = 8350C0541E071881009E0A93 /* xma.c */; };
8350C05A1E071990009E0A93 /* ps2_svag_snk.c in Sources */ = {isa = PBXBuildFile; fileRef = 8350C0591E071990009E0A93 /* ps2_svag_snk.c */; };
8351F3292212B53400A606E4 /* dsa_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 8351F3252212B53300A606E4 /* dsa_decoder.c */; };
8351F32D2212B57000A606E4 /* 208.c in Sources */ = {isa = PBXBuildFile; fileRef = 8351F32A2212B57000A606E4 /* 208.c */; };
8351F32E2212B57000A606E4 /* ubi_bao_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8351F32B2212B57000A606E4 /* ubi_bao_streamfile.h */; };
8351F32F2212B57000A606E4 /* dsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8351F32C2212B57000A606E4 /* dsf.c */; };
836F6B4718BDB8880095E648 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836F6B4518BDB8880095E648 /* InfoPlist.strings */; };
836F6F1E18BDC2190095E648 /* acm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE018BDC2180095E648 /* acm_decoder.c */; };
836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE218BDC2180095E648 /* adx_decoder.c */; };
@ -849,6 +853,10 @@
835027121ED119E000C25929 /* mta2_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mta2_decoder.c; sourceTree = "<group>"; };
8350C0541E071881009E0A93 /* xma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xma.c; sourceTree = "<group>"; };
8350C0591E071990009E0A93 /* ps2_svag_snk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_svag_snk.c; sourceTree = "<group>"; };
8351F3252212B53300A606E4 /* dsa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsa_decoder.c; sourceTree = "<group>"; };
8351F32A2212B57000A606E4 /* 208.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 208.c; sourceTree = "<group>"; };
8351F32B2212B57000A606E4 /* ubi_bao_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ubi_bao_streamfile.h; sourceTree = "<group>"; };
8351F32C2212B57000A606E4 /* dsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsf.c; sourceTree = "<group>"; };
836F6B3918BDB8880095E648 /* libvgmstream.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libvgmstream.framework; sourceTree = BUILT_PRODUCTS_DIR; };
836F6B4418BDB8880095E648 /* libvgmstream-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "libvgmstream-Info.plist"; sourceTree = "<group>"; };
836F6B4618BDB8880095E648 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -1325,6 +1333,7 @@
831BA6221EAC61CB00CF89B0 /* coding_utils.c */,
836F6DE518BDC2180095E648 /* coding.h */,
834FE0AD215C798B000A5D3D /* derf_decoder.c */,
8351F3252212B53300A606E4 /* dsa_decoder.c */,
834FE0B1215C798C000A5D3D /* ea_mt_decoder_utk.h */,
8349A8DE1FE6251F00E26435 /* ea_mt_decoder.c */,
83AA5D0E1F6E2F5F0020821C /* ea_xa_decoder.c */,
@ -1438,6 +1447,7 @@
isa = PBXGroup;
children = (
836F6E2918BDC2180095E648 /* 2dx9.c */,
8351F32A2212B57000A606E4 /* 208.c */,
834FE0C8215C79E7000A5D3D /* a2m.c */,
8306B0C82098458D000302D4 /* aax_utf.h */,
836F6E2A18BDC2180095E648 /* aax.c */,
@ -1490,6 +1500,7 @@
8349A8EE1FE6257C00E26435 /* dec.c */,
834FE0CD215C79E8000A5D3D /* derf.c */,
836F6E4318BDC2180095E648 /* dmsg_segh.c */,
8351F32C2212B57000A606E4 /* dsf.c */,
83299FCF1E7660C7003A3242 /* dsp_adx.c */,
836F6E4418BDC2180095E648 /* dsp_bdsp.c */,
8349A8FF1FE6258000E26435 /* ea_1snh.c */,
@ -1735,6 +1746,7 @@
836F6EFB18BDC2190095E648 /* tun.c */,
830165971F256BD000CA0941 /* txth.c */,
8306B0D22098458F000302D4 /* txtp.c */,
8351F32B2212B57000A606E4 /* ubi_bao_streamfile.h */,
8306B0D420984590000302D4 /* ubi_bao.c */,
836F6EFC18BDC2190095E648 /* ubi_ckd.c */,
8306B0D720984590000302D4 /* ubi_jade.c */,
@ -1849,6 +1861,7 @@
834FE0EC215C79ED000A5D3D /* kma9_streamfile.h in Headers */,
8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */,
834FE0ED215C79ED000A5D3D /* fsb_interleave_streamfile.h in Headers */,
8351F32E2212B57000A606E4 /* ubi_bao_streamfile.h in Headers */,
8349A9111FE6258200E26435 /* bar_streamfile.h in Headers */,
836F6F2718BDC2190095E648 /* g72x_state.h in Headers */,
832BF82C21E0514B006F50F1 /* hca_keys_awb.h in Headers */,
@ -2164,6 +2177,7 @@
8306B0D920984590000302D4 /* ngc_str_cauldron.c in Sources */,
834FE0FB215C79ED000A5D3D /* xau_konami.c in Sources */,
83F0AA6121E2028C004BBC04 /* vsv.c in Sources */,
8351F32F2212B57000A606E4 /* dsf.c in Sources */,
83F0AA5F21E2028C004BBC04 /* smp.c in Sources */,
833A7A2E1ED11961003EC53E /* xau.c in Sources */,
836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */,
@ -2286,6 +2300,7 @@
836F6F6B18BDC2190095E648 /* agsc.c in Sources */,
836F700E18BDC2190095E648 /* ps2_xa2.c in Sources */,
836F6FF718BDC2190095E648 /* ps2_sl3.c in Sources */,
8351F32D2212B57000A606E4 /* 208.c in Sources */,
836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */,
836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */,
836F702118BDC2190095E648 /* rs03.c in Sources */,
@ -2301,6 +2316,7 @@
8349A8E91FE6253900E26435 /* blocked_ea_1snh.c in Sources */,
8306B0E620984590000302D4 /* msb_msh.c in Sources */,
836F702918BDC2190095E648 /* sat_sap.c in Sources */,
8351F3292212B53400A606E4 /* dsa_decoder.c in Sources */,
836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */,
834FE106215C79ED000A5D3D /* utk.c in Sources */,
831BA6281EAC61CB00CF89B0 /* coding_utils.c in Sources */,

View File

@ -41,7 +41,6 @@ void decode_h4m_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
size_t ima_bytes_to_samples(size_t bytes, int channels);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
size_t xbox_ima_bytes_to_samples(size_t bytes, int channels);
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset);
size_t apple_ima4_bytes_to_samples(size_t bytes, int channels);
/* ngc_dsp_decoder */
@ -162,6 +161,9 @@ void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacin
/* asf_decoder */
void decode_asf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* dsa_decoder */
void decode_dsa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* xmd_decoder */
void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);

View File

@ -0,0 +1,52 @@
#include "coding.h"
static const int dsa_coefs[16] = {
0x0, 0x1999, 0x3333, 0x4CCC,
0x6666, 0x8000, 0x9999, 0xB333,
0xCCCC, 0xE666, 0x10000, 0x11999,
0x13333, 0x18000, 0x1CCCC, 0x21999
};
/* Decodes Ocean DSA ADPCM codec from Last Rites (PC).
* Reverse engineered from daemon1's reverse engineering. */
void decode_dsa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
off_t frame_offset;
int i, frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
uint8_t header;
int shift, filter;
int32_t hist1 = stream->adpcm_history1_32;
/* external interleave (fixed size), mono */
bytes_per_frame = 0x08;
samples_per_frame = (bytes_per_frame - 0x01) * 2;
frames_in = first_sample / samples_per_frame;
first_sample = first_sample % samples_per_frame;
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame*frames_in;
header = (uint8_t)read_8bit(frame_offset+0x00,stream->streamfile);
shift = 0x0c - ((header >> 4) & 0xf);
filter = dsa_coefs[header & 0xf];
/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
int32_t new_sample;
uint8_t nibbles = (uint8_t)read_8bit(frame_offset+0x01 + i/2,stream->streamfile);
new_sample = i&1 ? /* high nibble first */
(nibbles >> 0) & 0xf :
(nibbles >> 4) & 0xf;
new_sample = ((int16_t)(new_sample << 0xC) >> shift); /* 16b sign extend + scale */
new_sample = new_sample + ((hist1 * filter) >> 0x10);
outbuf[sample_count] = (int16_t)(new_sample << 2);
sample_count += channelspacing;
hist1 = new_sample;
}
stream->adpcm_history1_32 = hist1;
}

View File

@ -321,7 +321,7 @@ ffmpeg_codec_data * init_ffmpeg_header_offset_subsong(STREAMFILE *streamFile, ui
data->offset = start;
data->size = size;
if (data->size == 0 || data->start + data->size > get_streamfile_size(streamFile)) {
VGM_LOG("FFmpeg: wrong start+size found\n");
VGM_LOG("FFPMEG: wrong start+size found: %x + %x > %x \n", (uint32_t)start, (uint32_t)size, get_streamfile_size(streamFile));
data->size = get_streamfile_size(streamFile) - data->start;
}
data->logical_offset = 0;

View File

@ -937,16 +937,19 @@ void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
off_t offset = stream->offset;
/* header fields mostly unknown (vary a lot or look like flags),
* 0x07 0x06 = major/minor tool version?, 0x0c: stereo flag? */
/* header fields mostly unknown (vary a lot or look like flags, tool version?, 0x08: stereo flag?) */
version = read_8bit(offset + 0x00, stream->streamfile);
big_endian = version < 5; //todo and sb.big_endian?
big_endian = version < 5;
read_16bit = big_endian ? read_16bitBE : read_16bitLE;
header_samples = read_16bit(offset + 0x0E, stream->streamfile); /* always 10 (per channel) */
hist1 = read_16bit(offset + 0x10 + channel*0x04,stream->streamfile);
step_index = read_8bit(offset + 0x12 + channel*0x04,stream->streamfile);
offset += 0x10 + 0x08 + 0x04; //todo v6 has extra 0x08?
offset += 0x10 + 0x08;
if (version >= 3)
offset += 0x04;
//if (version >= 6) /* supposedly this exists, maybe in later BAOs */
// offset += 0x08;
/* write PCM samples, must be written to match header's num_samples (hist mustn't) */
max_samples_to_do = ((samples_to_do > header_samples) ? header_samples : samples_to_do);
@ -1081,19 +1084,3 @@ size_t apple_ima4_bytes_to_samples(size_t bytes, int channels) {
return (bytes / block_align) * (block_align - 0x02*channels) * 2 / channels
+ ((bytes % block_align) ? ((bytes % block_align) - 0x02*channels) * 2 / channels : 0);
}
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset) {
int version, big_endian, header_samples;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
size_t header_size = 0;
version = read_8bit(offset + 0x00, streamFile);
big_endian = version < 5; //todo and sb.big_endian?
read_16bit = big_endian ? read_16bitBE : read_16bitLE;
header_samples = read_16bit(offset + 0x0E, streamFile); /* always 10 (per channel) */
header_size += 0x10 + 0x04 * channels + 0x04; //todo v6 has extra 0x08?
header_size += header_samples * channels * sizeof(sample);
return header_samples + ima_bytes_to_samples(bytes - header_size, channels);
}

View File

@ -10,7 +10,7 @@
* Layer III MPEG1 uses two granules (data chunks) per frame, while MPEG2/2.5 ("LSF mode") only one.
* EA-frames contain one granule, so to reconstruct one MPEG-frame we need two EA-frames (MPEG1) or
* one (MPEG2). This is only for our decoder, real EALayer3 would decode EA-frames directly.
* EALayer v1 and v2 differ in part of the header, but are mostly the same.
* EALayer3 v1 and v2 differ in part of the header, but are mostly the same.
*
* Reverse engineering by Zench: https://bitbucket.org/Zenchreal/ealayer3 (ealayer3.exe decoder)
* Reference: https://www.mp3-tech.org/programmer/docs/mp3_theory.pdf
@ -73,13 +73,14 @@ typedef struct {
} ealayer3_frame_info;
static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame(mpeg_codec_data *data, int num_stream, vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b);
static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os);
static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf);
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start);
static int ealayer3_is_empty_frame(vgm_bitstream *is);
/* **************************************************************************** */
/* EXTERNAL API */
@ -100,7 +101,7 @@ int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset,
is.bufsize = read_streamfile(ibuf,start_offset,EALAYER3_EA_FRAME_BUFFER_SIZE, streamFile); /* reads less at EOF */;
is.b_off = 0;
ok = ealayer3_parse_frame(data, &is, &eaf);
ok = ealayer3_parse_frame(data, -1, &is, &eaf);
if (!ok) goto fail;
}
//;VGM_ASSERT(!eaf.mpeg1, "MPEG EAL3: mpeg2 found at 0x%lx\n", start_offset); /* rare [FIFA 08 (PS3) abk] */
@ -126,6 +127,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
vgm_bitstream is_0 = {0}, is_1 = {0}, os = {0};
uint8_t ibuf_0[EALAYER3_EA_FRAME_BUFFER_SIZE], ibuf_1[EALAYER3_EA_FRAME_BUFFER_SIZE];
/* read first frame/granule, or PCM-only frame (found alone at the end of SCHl streams) */
{
//;VGM_LOG("s%i: get granule0 at %lx\n", num_stream,stream->offset);
@ -136,7 +138,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
is_0.bufsize = read_streamfile(ibuf_0,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
is_0.b_off = 0;
ok = ealayer3_parse_frame(data, &is_0, &eaf_0);
ok = ealayer3_parse_frame(data, num_stream, &is_0, &eaf_0);
if (!ok) goto fail;
ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_0);
@ -152,10 +154,13 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
/* In EAL3 V2P sometimes there is a new SNS/SPS block between granules. Instead of trying to fix it here
* or in blocked layout (too complex/patchy), SNS/SPS uses a custom streamfile that simply removes all
* block headers, so this parser only sees raw EALayer3 data. It also discards samples, which confuses
* blocked layout calculations */
* blocked layout calculations
*
* Similarly (as V2P decodes and writes 1 granule at a time) stream can end in granule0. Since mpg123
* decodes in pairs we detect and feed it a fake end granule1, to get the last granule0's 576 samples. */
/* get second frame/granule (MPEG1 only) if first granule was found */
granule_found = 0;
/* get second frame/granule (MPEG1 only) if first granule was found */
while (eaf_0.common_size && eaf_0.mpeg1 && !granule_found) {
//;VGM_LOG("s%i: get granule1 at %lx\n", num_stream,stream->offset);
if (!ealayer3_skip_data(stream, data, num_stream, 1))
@ -165,14 +170,25 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
is_1.bufsize = read_streamfile(ibuf_1,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
is_1.b_off = 0;
ok = ealayer3_parse_frame(data, &is_1, &eaf_1);
/* detect end granule0 (which may be before stream end in multichannel) and create a usable last granule1 */
if (data->type == MPEG_EAL32P && eaf_0.mpeg1 && ealayer3_is_empty_frame(&is_1)) {
;VGM_LOG("EAL3: fake granule1 needed\n");
/* memcpy/clone for now as I'm not sure now to create a valid empty granule1, but
* probably doesn't matter since num_samples should end before its samples */
eaf_1 = eaf_0;
is_1 = is_0;
eaf_1.granule_index = 1;
break;
}
ok = ealayer3_parse_frame(data, num_stream, &is_1, &eaf_1);
if (!ok) goto fail;
ok = ealayer3_write_pcm_block(stream, data, num_stream, &eaf_1);
if (!ok) goto fail;
stream->offset += eaf_1.eaframe_size;
//;VGM_LOG("s%i: get granule0 done at %lx (eaf_size=%x, common_size=%x)\n", num_stream,stream->offset, eaf_0.eaframe_size, eaf_0.common_size);
//;VGM_LOG("s%i: get granule1 done at %lx (eaf_size=%x, common_size=%x)\n", num_stream,stream->offset, eaf_1.eaframe_size, eaf_1.common_size);
if (!ealayer3_skip_data(stream, data, num_stream, 0))
goto fail;
@ -182,7 +198,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
granule_found = 1;
}
/* rebuild EALayer frame to MPEG frame */
/* rebuild EALayer3 frame to MPEG frame */
{
os.buf = ms->buffer;
os.bufsize = ms->buffer_size;
@ -205,15 +221,22 @@ fail:
/* INTERNAL HELPERS */
/* **************************************************************************** */
static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf) {
static int ealayer3_parse_frame(mpeg_codec_data *data, int num_stream, vgm_bitstream *is, ealayer3_frame_info * eaf) {
int ok;
/* We must pass this from state, as not all EA-frames have channel info.
* (unknown in the first EA-frame but that's ok) */
int channels_per_frame = 0;
if (num_stream >= 0) {
channels_per_frame = data->streams[num_stream]->channels_per_frame;
}
/* make sure as there is re-parsing in loops */
memset(eaf, 0, sizeof(ealayer3_frame_info));
switch(data->type) {
case MPEG_EAL31: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame, 0); break;
case MPEG_EAL31b: ok = ealayer3_parse_frame_v1(is, eaf, data->channels_per_frame, 1); break;
case MPEG_EAL31: ok = ealayer3_parse_frame_v1(is, eaf, channels_per_frame, 0); break;
case MPEG_EAL31b: ok = ealayer3_parse_frame_v1(is, eaf, channels_per_frame, 1); break;
case MPEG_EAL32P:
case MPEG_EAL32S: ok = ealayer3_parse_frame_v2(is, eaf); break;
default: goto fail;
@ -241,10 +264,10 @@ static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf,
}
if (eaf->v1_pcm_flag == 0xEE && !channels_per_frame) {
VGM_LOG("MPEG EAL3 v1: PCM block in first frame\n");
goto fail; /* must know from a prev frame */
goto fail; /* must know from a prev frame (can't use eaf->channels for V1a) */
}
/* read EA-frame common header (v1a PCM blocks don't have EA-frames, while v1b do) */
/* read EA-frame common header (V1a PCM blocks don't have EA-frames, while V1b do) */
if (is_v1b || eaf->v1_pcm_flag == 0x00) {
ok = ealayer3_parse_frame_common(is, eaf);
if (!ok) goto fail;
@ -544,52 +567,89 @@ fail:
return 0;
}
static void ealayer3_copy_pcm_block(uint8_t* outbuf, off_t pcm_offset, int pcm_number, int channels_per_frame, int is_packed, STREAMFILE * streamfile) {
int i, ch;
if (pcm_number == 0)
return;
/* read + write PCM block samples (always BE) */
if (is_packed) {
/* ch0+ch1 packed together */
off_t put_offset = 0;
for (i = 0; i < pcm_number * channels_per_frame; i++) {
int16_t pcm_sample = read_16bitBE(pcm_offset,streamfile);
put_16bitLE(outbuf + put_offset, pcm_sample);
pcm_offset += sizeof(sample);
put_offset += sizeof(sample);
}
}
else {
/* all of ch0 first, then all of ch1 (EAL3 v1b only) */
for (ch = 0; ch < channels_per_frame; ch++) {
off_t put_offset = sizeof(sample)*ch;
for (i = 0; i < pcm_number; i++) {
int16_t pcm_sample = read_16bitBE(pcm_offset,streamfile);
put_16bitLE(outbuf + put_offset, pcm_sample);
pcm_offset += sizeof(sample);
put_offset += sizeof(sample)*channels_per_frame;
}
}
}
}
/* write PCM block directly to sample buffer and setup decode discard (EALayer3 seems to use this as a prefetch of sorts).
* Meant to be written inmediatedly, as those PCM are parts that can be found after 1 decoded frame.
* (ex. EA-frame_gr0, PCM-frame_0, EA-frame_gr1, PCM-frame_1 actually writes PCM-frame_0+1, decode of EA-frame_gr0+1 + discard part */
static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf) {
mpeg_custom_stream *ms = data->streams[num_stream];
int channels_per_frame = ms->channels_per_frame;
size_t bytes_filled;
int i;
bytes_filled = sizeof(sample)*ms->samples_filled*data->channels_per_frame;
bytes_filled = sizeof(sample) * ms->samples_filled * channels_per_frame;
if (bytes_filled + eaf->pcm_size > ms->output_buffer_size) {
VGM_LOG("MPEG EAL3: can't fill the sample buffer with 0x%x\n", eaf->pcm_size);
goto fail;
}
if (eaf->v1_pcm_number && !eaf->pcm_size) {
VGM_LOG("MPEG EAL3: pcm size without pcm number\n");
goto fail; //todo ??? first block?
}
if (eaf->v1_pcm_number) {
if (!eaf->pcm_size)
return 1;
uint8_t* outbuf = ms->output_buffer + bytes_filled;
off_t pcm_offset = stream->offset + eaf->pre_size + eaf->common_size;
VGM_ASSERT(eaf->v1_pcm_decode_discard > 576, "MPEG EAL3: big discard %i at 0x%x\n", eaf->v1_pcm_decode_discard, (uint32_t)stream->offset);
VGM_ASSERT(eaf->v1_pcm_number > 0x100, "MPEG EAL3: big samples %i at 0x%x\n", eaf->v1_pcm_number, (uint32_t)stream->offset);
/* read + write PCM block samples (always BE) */
for (i = 0; i < eaf->v1_pcm_number * data->channels_per_frame; i++) {
off_t pcm_offset = stream->offset + eaf->pre_size + eaf->common_size + sizeof(sample)*i;
int16_t pcm_sample = read_16bitBE(pcm_offset,stream->streamfile);
put_16bitLE(ms->output_buffer + bytes_filled + sizeof(sample)*i, pcm_sample);
}
//;VGM_LOG("EA EAL3 v1: off=%lx, discard=%x, pcm=%i, pcm_o=%lx\n",
// stream->offset, eaf->v1_pcm_decode_discard, eaf->v1_pcm_number, pcm_offset);
/* V1 usually discards + copies samples at the same time
* V1b PCM block is interleaved/'planar' format (ex. NFS:U PS3) */
ealayer3_copy_pcm_block(outbuf, pcm_offset, eaf->v1_pcm_number, channels_per_frame, (data->type == MPEG_EAL31), stream->streamfile);
ms->samples_filled += eaf->v1_pcm_number;
/* skip decoded samples as PCM block 'overwrites' them */
/* skip decoded samples as PCM block 'overwrites' them w/ special meanings */
{
size_t decode_to_discard = eaf->v1_pcm_decode_discard;
//todo should also discard v1_pcm_number, but block layout samples may be exhausted and won't move (maybe new block if offset = new offset detected)
/* special meanings */
if (data->type == MPEG_EAL31) {
//todo should also discard v1_pcm_number, but block layout samples may be exhausted
// and won't move (maybe new block if offset = new offset detected)
if (decode_to_discard == 576)
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number;
}
else {
// todo also discard
if (decode_to_discard == 0) /* seems ok? */
decode_to_discard += data->samples_per_frame;//+ eaf->v1_pcm_number;
else if (decode_to_discard == 576) /* untested */
//todo maybe should be (576 or samples_per_frame - decode_to_discard) but V1b doesn't seem to set discard
if (decode_to_discard == 0) /* seems ok (ex. comparing NFS:UC PS3 vs PC gets correct waveform this way) */
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number; /* musn't discard pcm_number */
else if (decode_to_discard == 576) //todo unsure
decode_to_discard = data->samples_per_frame;//+ eaf->v1_pcm_number;
}
ms->decode_to_discard += decode_to_discard;
@ -597,6 +657,24 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
}
if (eaf->v2_extended_flag) {
uint8_t* outbuf = ms->output_buffer + bytes_filled;
off_t pcm_offset = stream->offset + eaf->pre_size + eaf->common_size;
/* V2P usually only copies big PCM, while V2S discards then copies few samples (similar to V1b).
* Unlike V1b, both modes seem to use 'packed' PCM block */
ealayer3_copy_pcm_block(outbuf, pcm_offset, eaf->v2_pcm_number, channels_per_frame, 1, stream->streamfile);
ms->samples_filled += eaf->v2_pcm_number;
//;VGM_LOG("EA EAL3 v2: off=%lx, mode=%x, value=%i, pcm=%i, c-size=%x, pcm_o=%lx\n",
// stream->offset, eaf->v2_mode, eaf->v2_mode_value, eaf->v2_pcm_number, eaf->v2_common_size, pcm_offset);
/* modify decoded samples depending on flag (looks correct in V2P loops, ex. NFS:W) */
if (eaf->v2_mode == 0x00) {
size_t decode_to_discard = eaf->v2_mode_value; /* (usually 0 in V2P, varies in V2S) */
decode_to_discard = 576 - decode_to_discard;
ms->decode_to_discard += decode_to_discard;
}
/* todo supposed skip modes (only seen 0x00):
*
@ -612,28 +690,6 @@ static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d
* if 2: 576 if G == 0 then F * 2
* if 3: 576
*/
//;VGM_LOG("EA EAL3 v2: off=%lx, mode=%x, value=%x, pcm=%x, size=%x\n", stream->offset, eaf->v2_mode, eaf->v2_mode_value, eaf->v2_pcm_number, eaf->v2_common_size);
if (eaf->v2_pcm_number) {
/* read + write PCM block samples (always BE) */
for (i = 0; i < eaf->v2_pcm_number * data->channels_per_frame; i++) {
off_t pcm_offset = stream->offset + eaf->pre_size + eaf->common_size + sizeof(sample)*i;
int16_t pcm_sample = read_16bitBE(pcm_offset,stream->streamfile);
put_16bitLE(ms->output_buffer + bytes_filled + sizeof(sample)*i, pcm_sample);
}
ms->samples_filled += eaf->v2_pcm_number;
}
/* modify decoded samples depending on flag */
if (eaf->v2_mode == 0x00) {
size_t decode_to_discard = eaf->v2_mode_value; /* (usually 0 in V2P, varies in V2S) */
if (decode_to_discard == 0)
decode_to_discard = 576;
//todo output seems correct-ish but reaches file end and tries to parse more frames
ms->decode_to_discard += decode_to_discard;
}
}
return 1;
@ -672,11 +728,11 @@ static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, i
is.bufsize = read_streamfile(ibuf,stream->offset,EALAYER3_EA_FRAME_BUFFER_SIZE, stream->streamfile); /* reads less at EOF */
is.b_off = 0;
ok = ealayer3_parse_frame(data, &is, &eaf);
ok = ealayer3_parse_frame(data, num_stream, &is, &eaf);
if (!ok) goto fail;
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-%i: skipping %x, now at %lx\n", num_stream,i,eaf.eaframe_size,stream->offset);
}
//;VGM_LOG("s%i: skipped %i frames, now at %lx\n", num_stream,skips,stream->offset);
@ -685,4 +741,15 @@ fail:
return 0;
}
static int ealayer3_is_empty_frame(vgm_bitstream *is) {
int i;
for (i = 0; i < is->bufsize; i++) {
if (is->buf[i] != 0)
return 0;
}
return 1;
}
#endif

View File

@ -7,12 +7,6 @@
#include "mpeg_decoder.h"
/* TODO list for custom decoder
* - don't force channel param and get them from frame headers for some types (for MPEG_STANDARD)
* - in case of streams like 2ch+1ch+1ch+2ch (not seen) use one stream per channel and advance streams as channels are done
* - validate of channels between streams
*/
#define MPEG_DATA_BUFFER_SIZE 0x1000 /* at least one MPEG frame (max ~0x5A1 plus some more in case of free bitrate) */
static mpg123_handle * init_mpg123_handle();
@ -154,8 +148,14 @@ mpeg_codec_data *init_mpeg_custom(STREAMFILE *streamFile, off_t start_offset, co
/* init streams */
data->streams_size = channels / data->channels_per_frame;
/* 2ch streams + odd channels = last stream must be 1ch */
/* (known channels combos are 2ch+..+2ch, 1ch+..+1ch, or rarely 2ch+..+2ch+1ch in EALayer3) */
if (data->channels_per_frame == 2 && channels % 2)
data->streams_size += 1;
data->streams = calloc(data->streams_size, sizeof(mpeg_custom_stream*));
for (i=0; i < data->streams_size; i++) {
for (i = 0; i < data->streams_size; i++) {
data->streams[i] = calloc(1, sizeof(mpeg_custom_stream));
data->streams[i]->m = init_mpg123_handle(); /* decoder not shared as may need several frames to decode)*/
if (!data->streams[i]->m) goto fail;
@ -169,8 +169,11 @@ mpeg_codec_data *init_mpeg_custom(STREAMFILE *streamFile, off_t start_offset, co
data->streams[i]->buffer_size = data->default_buffer_size;
data->streams[i]->buffer = calloc(sizeof(uint8_t), data->streams[i]->buffer_size);
if (!data->streams[i]->buffer) goto fail;
}
data->streams[i]->channels_per_frame = data->channels_per_frame;
if (i + 1 == data->streams_size && data->channels_per_frame == 2 && channels % 2)
data->streams[i]->channels_per_frame = 1;
}
return data;
@ -314,28 +317,28 @@ static void decode_mpeg_custom(VGMSTREAM * vgmstream, mpeg_codec_data * data, sa
samples_to_copy -= samples_to_discard;
}
/* mux streams channels (1/2ch combos) to outbuf (Nch) */
if (samples_to_copy > 0) {
/* copy stream's samples to outbuf */
int ch, stream;
if (samples_to_copy > samples_to_do - samples_done)
samples_to_copy = samples_to_do - samples_done;
/* mux streams channels (1/2ch) to outbuf (Nch) (ex. 6ch: samples from 2ch+2ch+2ch) */
for (i = 0; i < data->streams_size; i++) {
mpeg_custom_stream *ms = data->streams[i];
int channels_frame = data->channels_per_frame;
int fch, s;
ch = 0;
for (stream = 0; stream < data->streams_size; stream++) {
mpeg_custom_stream *ms = data->streams[stream];
sample* inbuf = (sample*)ms->output_buffer;
int stream_channels = ms->channels_per_frame;
int stream_ch, s;
for (fch = 0; fch < channels_frame; fch++) {
for (stream_ch = 0; stream_ch < stream_channels; stream_ch++) {
for (s = 0; s < samples_to_copy; s++) {
size_t bytes_used = sizeof(sample)*ms->samples_used*channels_frame;
off_t in_offset = sizeof(sample)*s*channels_frame + sizeof(sample)*fch;
off_t out_offset = s*channels + i*channels_frame + fch;
size_t stream_sample = (ms->samples_used+s)*stream_channels + stream_ch;
size_t buffer_sample = (samples_done+s)*channels + ch;
memcpy((uint8_t*)(outbuf+samples_done*channels + out_offset),
ms->output_buffer+bytes_used + in_offset,
sizeof(sample));
outbuf[buffer_sample] = inbuf[stream_sample];
}
ch++;
}
ms->samples_used += samples_to_copy;
@ -371,6 +374,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
size_t stream_size = get_streamfile_size(stream->streamfile);
int rc, ok;
mpeg_custom_stream *ms = data->streams[num_stream];
int channels_per_frame = ms->channels_per_frame;
//;VGM_LOG("MPEG: decode stream%i @ 0x%08lx (filled=%i, used=%i, buffer_full=%i)\n", num_stream, stream->offset, ms->samples_filled, ms->samples_used, ms->buffer_full);
@ -417,7 +421,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
}
bytes_filled = sizeof(sample)*ms->samples_filled*data->channels_per_frame;
bytes_filled = sizeof(sample) * ms->samples_filled * channels_per_frame;
/* feed new raw data to the decoder if needed, copy decoded results to frame buffer output */
if (!ms->buffer_used) {
//;VGM_LOG("MPEG: feed new data and get samples\n");
@ -434,7 +438,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
(unsigned char*)ms->output_buffer + bytes_filled, ms->output_buffer_size - bytes_filled,
&bytes_done);
}
samples_filled = (bytes_done / sizeof(sample) / data->channels_per_frame);
samples_filled = (bytes_done / sizeof(sample) / channels_per_frame);
/* discard for weird features (EALayer3 and PCM blocks, AWC and repeated frames) */
if (ms->decode_to_discard) {
@ -442,7 +446,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
size_t decode_to_discard = ms->decode_to_discard;
if (decode_to_discard > samples_filled)
decode_to_discard = samples_filled;
bytes_to_discard = sizeof(sample)*decode_to_discard*data->channels_per_frame;
bytes_to_discard = sizeof(sample) * decode_to_discard * channels_per_frame;
bytes_done -= bytes_to_discard;
ms->decode_to_discard -= decode_to_discard;
@ -465,9 +469,9 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data
decode_fail:
/* 0-fill but continue with other streams */
bytes_filled = ms->samples_filled*data->channels_per_frame*sizeof(sample);
bytes_filled = ms->samples_filled * channels_per_frame * sizeof(sample);
memset(ms->output_buffer + bytes_filled, 0, ms->output_buffer_size - bytes_filled);
ms->samples_filled = (ms->output_buffer_size / data->channels_per_frame / sizeof(sample));
ms->samples_filled = (ms->output_buffer_size / channels_per_frame / sizeof(sample));
}

View File

@ -14,6 +14,7 @@ static const char* extension_list[] = {
//"", /* vgmstream can play extensionless files too, but plugins must accept them manually */
"04sw",
"208",
"2dx9",
"2pfs",
"800",
@ -107,6 +108,7 @@ static const char* extension_list[] = {
"ckd",
"cks",
"cnk",
"cpk",
"cps",
"csa", //txth/reserved [LEGO Racers 2 (PS2)]
"csmp",
@ -121,6 +123,7 @@ static const char* extension_list[] = {
"de2",
"dec",
"dmsg",
"dsf",
"dsp",
"dspw",
"dtk",
@ -351,6 +354,7 @@ static const char* extension_list[] = {
"sb6",
"sb7",
"sbr",
"sbv",
"sm0",
"sm1",
"sm2",
@ -446,6 +450,7 @@ static const char* extension_list[] = {
"vbx", //txth/reserved [THE Taxi 2 (PS2)]
"vds",
"vdm",
"vgm", //txth/reserved [Maximo (PS2)]
"vgs",
"vgv",
"vig",
@ -485,6 +490,7 @@ static const char* extension_list[] = {
"wv6",
"wve",
"wvs",
"wvx",
"x",
"xa",
@ -624,9 +630,9 @@ static const coding_info coding_info_list[] = {
{coding_MSADPCM_int, "Microsoft 4-bit ADPCM (mono/interleave)"},
{coding_MSADPCM_ck, "Microsoft 4-bit ADPCM (Cricket Audio)"},
{coding_WS, "Westwood Studios VBR ADPCM"},
{coding_AICA, "Yamaha AICA 4-bit ADPCM"},
{coding_AICA_int, "Yamaha AICA 4-bit ADPCM (mono/interleave)"},
{coding_YAMAHA, "Yamaha 4-bit ADPCM"},
{coding_AICA, "Yamaha 4-bit ADPCM"},
{coding_AICA_int, "Yamaha 4-bit ADPCM (mono/interleave)"},
{coding_YAMAHA, "Yamaha 4-bit ADPCM (framed)"},
{coding_YAMAHA_NXAP, "Yamaha NXAP 4-bit ADPCM"},
{coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"},
{coding_L5_555, "Level-5 0x555 4-bit ADPCM"},
@ -636,6 +642,7 @@ static const coding_info coding_info_list[] = {
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
{coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"},
{coding_ASF, "Argonaut ASF 4-bit ADPCM"},
{coding_DSA, "Ocean DSA 4-bit ADPCM"},
{coding_XMD, "Konami XMD 4-bit ADPCM"},
{coding_PCFX, "PC-FX 4-bit ADPCM"},
{coding_OKI16, "OKI 4-bit ADPCM (16-bit output)"},
@ -1134,10 +1141,9 @@ static const meta_info meta_info_list[] = {
{meta_A2M, "Artificial Mind & Movement A2M header"},
{meta_AHV, "Amuze AHV header"},
{meta_MSV, "Sony MultiStream MSV header"},
{meta_SDF_PS2, "Beyond Reality PS2 SDF header"},
{meta_SDF, "Beyond Reality SDF header"},
{meta_SVG, "High Voltage SVG header"},
{meta_VIS, "Konami VIS header"},
{meta_SDF_3DS, "Beyond Reality 3DS SDF header"},
{meta_VAI, "Asobo Studio .VAI header"},
{meta_AIF_ASOBO, "Asobo Studio .AIF header"},
{meta_AO, "AlphaOgg .AO header"},
@ -1162,6 +1168,8 @@ static const meta_info meta_info_list[] = {
{meta_OGG_OPUS, "Ogg Opus header"},
{meta_IMC, "iNiS .IMC header"},
{meta_GIN, "Electronic Arts Gnsu header"},
{meta_DSF, "Ocean DSF header"},
{meta_208, "Ocean .208 header"},
};

View File

@ -5,38 +5,51 @@
/* EA SNS/SPS blocks */
void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
uint32_t block_size, block_samples;
size_t file_size = get_streamfile_size(streamFile);
uint32_t block_id, block_size, block_samples;
off_t channel_start;
size_t channel_interleave;
int i;
/* always BE */
block_size = read_32bitBE(block_offset + 0x00,streamFile);
block_samples = read_32bitBE(block_offset + 0x04,streamFile);
/* EOF */
if (block_size == 0 || block_offset >= file_size) {
vgmstream->current_block_offset = file_size;
vgmstream->next_block_offset = file_size + 0x04;
vgmstream->current_block_samples = vgmstream->num_samples;
/* EOF reads: signal we have nothing and let the layout fail */
if (block_offset >= get_streamfile_size(streamFile)) {
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset;
vgmstream->current_block_samples = -1;
return;
}
/* always BE */
block_size = read_32bitBE(block_offset + 0x00,streamFile);
/* At 0x00(1): block flag
* - in SNS: 0x00=normal block, 0x80=last block (not mandatory)
* - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */
block_id = (block_size & 0x00FFFFFF) >> 24;
block_size &= 0x00FFFFFF;
switch(vgmstream->coding_type) {
if (block_id == 0x00 || block_id == 0x80 || block_id == 0x44) {
block_samples = read_32bitBE(block_offset + 0x04, streamFile);
} else {
block_samples = 0;
}
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset + block_size;
vgmstream->current_block_samples = block_samples;
/* no need to setup offsets (plus could read over filesize near EOF) */
if (block_samples == 0)
return;
switch (vgmstream->coding_type) {
case coding_NGC_DSP:
/* 0x04: unknown (0x00/02), 0x08: some size?, 0x34: null? */
channel_start = read_32bitBE(block_offset+0x08+0x00,streamFile);
channel_interleave = read_32bitBE(block_offset+0x08+0x0c,streamFile);
channel_start = read_32bitBE(block_offset + 0x08 + 0x00, streamFile);
channel_interleave = read_32bitBE(block_offset + 0x08 + 0x0c, streamFile);
/* guessed as all known EA DSP only have one block with subheader (maybe changes coefs every block?) */
if (channel_start >= 0x40) {
dsp_read_coefs_be(vgmstream,streamFile, block_offset+0x08+0x10,0x28);
dsp_read_hist_be (vgmstream,streamFile, block_offset+0x08+0x30,0x28);//todo guessed and doesn't fix clicks in full loops
dsp_read_coefs_be(vgmstream, streamFile, block_offset + 0x08 + 0x10, 0x28);
dsp_read_hist_be(vgmstream, streamFile, block_offset + 0x08 + 0x30, 0x28);//todo guessed and doesn't fix clicks in full loops
}
break;
@ -47,15 +60,11 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
}
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i*channel_interleave;
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i * channel_interleave;
/* also fix first offset (for EALayer3) */
if (block_offset == vgmstream->ch[i].channel_start_offset) {
vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset;
}
}
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset + block_size;
vgmstream->current_block_samples = block_samples;
}

View File

@ -28,10 +28,14 @@ void block_update_mul(off_t block_offset, VGMSTREAM * vgmstream) {
data_header = 0x00;
data_size = 0;
}
if (block_type == 0x00 && block_size != 0) {
else if (block_type == 0x00 && block_size != 0) {
/* read audio sub-header */
data_size = read_32bit(block_offset + block_header + 0x00,streamFile);
}
else if (block_type < 0) {
/* EOF/bad read */
data_size = -1;
}
else {
/* non-audio or empty audio block */
data_header = 0x00;
@ -44,7 +48,5 @@ void block_update_mul(off_t block_offset, VGMSTREAM * vgmstream) {
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = block_offset + block_header + data_header + vgmstream->current_block_size*i;
//VGM_LOG("ch%i of=%lx\n", i, vgmstream->ch[i].offset);
}
//getchar();
}

View File

@ -0,0 +1,48 @@
#include "meta.h"
#include "../coding/coding.h"
/* .208 - from Ocean game(s?) [Last Rites (PC)] */
VGMSTREAM * init_vgmstream_208(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, sample_rate;
size_t data_size;
/* checks */
if (!check_extensions(streamFile, "208"))
goto fail;
/* possible validation: (0x04 == 0 and 0xcc == 0x1F7D984D) or 0x04 == 0xf0 and 0xcc == 0) */
if (!((read_32bitLE(0x04,streamFile) == 0x00 && read_32bitBE(0xcc,streamFile) == 0x1F7D984D) ||
(read_32bitLE(0x04,streamFile) == 0xF0 && read_32bitBE(0xcc,streamFile) == 0x00000000)))
goto fail;
start_offset = read_32bitLE(0x00,streamFile);
data_size = read_32bitLE(0x0c,streamFile);
sample_rate = read_32bitLE(0x34,streamFile);
channel_count = read_32bitLE(0x3C,streamFile); /* assumed */
loop_flag = 0;
if (start_offset + data_size != get_streamfile_size(streamFile))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_208;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 8);
vgmstream->coding_type = coding_PCM8_U;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,51 @@
#include "meta.h"
#include "../coding/coding.h"
/* .DSF - from Ocean game(s?) [Last Rites (PC)] */
VGMSTREAM * init_vgmstream_dsf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, sample_rate;
size_t data_size;
/* checks */
if (!check_extensions(streamFile, "dsf"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4F434541 && /* "OCEA" */
read_32bitBE(0x00,streamFile) != 0x4E204453 && /* "N DS" */
read_32bitBE(0x00,streamFile) != 0x41000000) /* "A\0\0\0" */
goto fail;
/* 0x10(2): always 1? */
/* 0x12(4): total nibbles / 0x10? */
/* 0x16(4): always 0? */
start_offset = read_32bitLE(0x1a,streamFile);
sample_rate = read_32bitLE(0x1e,streamFile);
channel_count = read_32bitLE(0x22,streamFile) + 1;
data_size = get_streamfile_size(streamFile) - start_offset;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_DSF;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ((data_size / 0x08 / channel_count) * 14); /* bytes-to-samples */
vgmstream->coding_type = coding_DSA;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x08;
read_string(vgmstream->stream_name,0x20+1, 0x26,streamFile);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -272,7 +272,7 @@ static VGMSTREAM * parse_s10a_header(STREAMFILE *streamFile, off_t offset, uint1
goto fail;
num_sounds = read_32bitBE(offset + 0x08, streamFile);
if (num_sounds == 0 || target_index > num_sounds)
if (num_sounds == 0 || target_index >= num_sounds)
goto fail;
snr_offset = offset + read_32bitBE(offset + 0x0C + 0x04 * target_index, streamFile);
@ -311,9 +311,8 @@ fail:
/* EA SBR/SBS - used in older 7th gen games for storing SFX */
VGMSTREAM * init_vgmstream_ea_sbr(STREAMFILE *streamFile) {
uint32_t num_sounds, type_desc;
uint32_t i, num_sounds, type_desc;
uint16_t num_metas, meta_type;
uint32_t i;
off_t table_offset, types_offset, entry_offset, metas_offset, data_offset, snr_offset, sns_offset;
STREAMFILE *sbsFile = NULL, *streamData = NULL;
VGMSTREAM *vgmstream = NULL;
@ -343,7 +342,7 @@ VGMSTREAM * init_vgmstream_ea_sbr(STREAMFILE *streamFile) {
for (i = 0; i < num_metas; i++) {
entry_offset = metas_offset + 0x06 * i;
meta_type = read_16bitBE(entry_offset, streamFile);
meta_type = read_16bitBE(entry_offset + 0x00, streamFile);
data_offset = read_32bitBE(entry_offset + 0x02, streamFile);
type_desc = read_32bitBE(types_offset + 0x06 * meta_type, streamFile);
@ -498,7 +497,7 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_eaac(STREAMFILE *streamFile) {
uint32_t num_sounds;
uint8_t version, sub_version, block_id;
off_t table_offset, entry_offset, snr_offset, sns_offset;
size_t /*snr_size,*/ sns_size;
/* size_t snr_size sns_size; */
int32_t(*read_32bit)(off_t, STREAMFILE*);
STREAMFILE *musFile = NULL;
VGMSTREAM *vgmstream = NULL;
@ -548,8 +547,10 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_eaac(STREAMFILE *streamFile) {
entry_offset = table_offset + (target_stream - 1) * 0x1c;
snr_offset = read_32bit(entry_offset + 0x08, musFile) * 0x10;
sns_offset = read_32bit(entry_offset + 0x0c, musFile) * 0x80;
//snr_size = read_32bit(entry_offset + 0x10, musFile);
/*
snr_size = read_32bit(entry_offset + 0x10, musFile);
sns_size = read_32bit(entry_offset + 0x14, musFile);
*/
block_id = read_8bit(sns_offset, musFile);
if (block_id != EAAC_BLOCKID0_DATA && block_id != EAAC_BLOCKID0_END)
@ -560,7 +561,6 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_eaac(STREAMFILE *streamFile) {
goto fail;
vgmstream->num_streams = num_sounds;
vgmstream->stream_size = sns_size;
close_streamfile(musFile);
return vgmstream;
@ -765,7 +765,7 @@ typedef struct {
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);
static size_t calculate_eaac_size(VGMSTREAM *vgmstream, STREAMFILE *streamFile, eaac_header *eaac, off_t start_offset);
/* EA newest header from RwAudioCore (RenderWare?) / EAAudioCore library (still generated by sx.exe).
* Audio "assets" come in separate RAM headers (.SNR/SPH) and raw blocked streams (.SNS/SPS),
@ -832,7 +832,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
eaac.loop_offset = eaac.stream_offset + eaac.loop_offset;
}
else {
/* RAM assets only one block in case in case of full loops */
/* RAM assets have only one block in case of full loops */
eaac.loop_offset = eaac.stream_offset; /* implicit */
}
@ -853,16 +853,18 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
}
}
/* accepted channel configs only seem to be mono/stereo/quad/5.1/7.1, from debug strings */
/* common channel configs are mono/stereo/quad/5.1/7.1 (from debug strings) */
switch(eaac.channel_config) {
case 0x00: eaac.channels = 1; break;
case 0x01: eaac.channels = 2; break;
case 0x03: eaac.channels = 4; break;
case 0x05: eaac.channels = 6; break;
case 0x07: eaac.channels = 8; break;
case 0x0a: eaac.channels = 11; break; /* rare [Army of Two: The Devil's Cartel (PS3)-EALayer3v2P] */
default:
/* surely channels = channel_config+1 but fail just in case for now */
VGM_LOG("EA EAAC: unknown channel config 0x%02x\n", eaac.channel_config);
goto fail; /* fail with unknown values just in case */
goto fail;
}
@ -1024,9 +1026,13 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
goto fail;
}
if (!vgmstream_open_stream(vgmstream,temp_streamFile ? temp_streamFile : streamData,start_offset))
if (!vgmstream_open_stream(vgmstream, temp_streamFile ? temp_streamFile : streamData, start_offset))
goto fail;
if (eaac.loop_start == 0) {
vgmstream->stream_size = calculate_eaac_size(vgmstream, temp_streamFile ? temp_streamFile : streamData, &eaac, start_offset);
}
close_streamfile(temp_streamFile);
return vgmstream;
@ -1038,12 +1044,50 @@ fail:
static size_t get_snr_size(STREAMFILE *streamFile, off_t offset) {
switch (read_8bit(offset + 0x04, streamFile) >> 4 & 0x0F) { /* flags */
case EAAC_FLAG_LOOPED | EAAC_FLAG_STREAMED: return 0x10;
case EAAC_FLAG_LOOPED: return 0x0C;
default: return 0x08;
case EAAC_FLAG_LOOPED | EAAC_FLAG_STREAMED: return 0x10;
case EAAC_FLAG_LOOPED: return 0x0C;
default: return 0x08;
}
}
static size_t calculate_eaac_size(VGMSTREAM *vgmstream, STREAMFILE *streamFile, eaac_header *eaac, off_t start_offset) {
uint32_t total_samples;
size_t stream_size, file_size;
switch (eaac->codec) {
case EAAC_CODEC_EAXMA:
case EAAC_CODEC_EALAYER3_V1:
case EAAC_CODEC_EALAYER3_V2_PCM:
case EAAC_CODEC_EALAYER3_V2_SPIKE:
case EAAC_CODEC_EATRAX:
case EAAC_CODEC_EAMP3:
case EAAC_CODEC_EAOPUS:
stream_size = get_streamfile_size(streamFile);
break;
default:
stream_size = 0;
total_samples = 0;
file_size = get_streamfile_size(streamFile);
vgmstream->next_block_offset = start_offset;
while (vgmstream->next_block_offset < file_size && total_samples != vgmstream->num_samples) {
block_update_ea_sns(vgmstream->next_block_offset, vgmstream);
if (vgmstream->current_block_samples == 0)
continue;
/* stream size is almost never provided in bank files so we have to calc it manually */
stream_size += vgmstream->next_block_offset - vgmstream->ch[0].offset;
total_samples += vgmstream->current_block_samples;
}
/* reset once we're done */
block_update(start_offset, vgmstream);
break;
}
return stream_size;
}
/* Actual looping uses 2 block sections, separated by a block end flag *and* padded.
*
@ -1109,6 +1153,8 @@ static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *st
if (!vgmstream_open_stream(data->segments[i],temp_streamFile[i],0x00))
goto fail;
data->segments[i]->stream_size = calculate_eaac_size(data->segments[i], temp_streamFile[i], eaac, 0x00);
}
if (!setup_layout_segmented(data))

View File

@ -115,7 +115,7 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
/* check extension */
/* they don't seem enforced by EA's tools but usually:
* .asf: ~early (audio stream file?) [ex. Need for Speed (PC)]
* .asf: ~early (audio stream file?) [ex. Need for Speed II (PC)]
* .lasf: fake for plugins
* .str: ~early [ex. FIFA 2002 (PS1)]
* .eam: ~mid (fake?)
@ -161,6 +161,7 @@ fail:
/* EA BNK with variable header - from EA games SFXs; also created by sx.exe */
VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) {
off_t offset;
int target_stream = streamFile->stream_index;
/* check extension */
/* .bnk: common
@ -177,7 +178,9 @@ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) {
else
offset = 0x00;
return parse_bnk_header(streamFile, offset, streamFile->stream_index, 0);
if (target_stream == 0) target_stream = 1;
return parse_bnk_header(streamFile, offset, target_stream - 1, 0);
fail:
return NULL;
@ -587,7 +590,7 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) {
/* I can't figure it out, so let's just use a workaround for now */
if (version == 3 && sub_version == 1) { /* SSX Tricky */
/* we need to go through the first two sections to find sound table */
/* we need to go through the first two sections to find the sound table */
sec1_num = read_16bit(0x12, streamFile);
sec2_size = read_8bit(0x0d, streamFile) * read_8bit(0x0e, streamFile);
sec2_num = read_8bit(0x0f, streamFile);
@ -610,6 +613,7 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) {
total_streams = (eof_offset - section_offset) / 0x08;
off_mult = 0x04;
} else if (version == 3 && sub_version == 4) { /* Harry Potter and the Chamber of Secrets */
/* we need to go through the first two sections to find the sound table */
sec1_num = read_16bit(0x12, streamFile);
sec2_size = read_8bit(0x0d, streamFile) * read_8bit(0x0e, streamFile);
sec2_num = read_8bit(0x0f, streamFile);
@ -636,7 +640,7 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) {
total_streams = (eof_offset - section_offset) / 0x08;
off_mult = 0x04;
} else if (version == 4) { /* SSX 3, Need for Speed: Underground 2 */
/* we need to go through the first two sections to find sound table */
/* we need to go through the first two sections to find the sound table */
sec1_num = read_16bit(0x12, streamFile);
sec2_num = read_8bit(0x0f, streamFile);
@ -724,37 +728,37 @@ fail:
/* EA BNK with variable header - from EA games SFXs; also created by sx.exe */
static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int is_embedded) {
uint32_t i;
uint16_t num_sounds;
off_t header_offset, start_offset, test_offset, table_offset;
size_t header_size;
ea_header ea = {0};
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
ea_header ea = { 0 };
int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL;
int16_t(*read_16bit)(off_t, STREAMFILE*) = NULL;
VGMSTREAM *vgmstream = NULL;
int i, bnk_version;
int total_bnk_sounds, real_bnk_sounds = 0;
int bnk_version;
int real_bnk_sounds = 0;
/* check header */
/* BNK header endianness is platform-native */
if (read_32bitBE(offset + 0x00, streamFile) == EA_BNK_HEADER_BE) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
}
else if (read_32bitBE(offset + 0x00, streamFile) == EA_BNK_HEADER_LE) {
} else if (read_32bitBE(offset + 0x00, streamFile) == EA_BNK_HEADER_LE) {
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
}
else {
} else {
goto fail;
}
bnk_version = read_8bit(offset + 0x04,streamFile);
total_bnk_sounds = read_16bit(offset + 0x06,streamFile);
bnk_version = read_8bit(offset + 0x04, streamFile);
num_sounds = read_16bit(offset + 0x06, streamFile);
/* check multi-streams */
switch(bnk_version) {
switch (bnk_version) {
case 0x02: /* early [Need For Speed II (PC/PS1), FIFA 98 (PC/PS1/SAT)] */
table_offset = 0x0c;
header_size = read_32bit(offset + 0x08,streamFile); /* full size */
header_size = read_32bit(offset + 0x08, streamFile); /* full size */
break;
case 0x04: /* mid (last used in PSX banks) */
@ -769,32 +773,30 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta
goto fail;
}
if (target_stream == 0) target_stream = 1;
header_offset = 0;
for (i = 0; i < total_bnk_sounds; i++) {
/* some of these are dummies with zero offset */
test_offset = read_32bit(offset + table_offset + 0x04 * i, streamFile);
if (is_embedded) {
if (target_stream < 0 || target_stream >= num_sounds)
goto fail;
if (test_offset != 0) {
real_bnk_sounds++;
header_offset = read_32bit(offset + table_offset + 0x04 * target_stream, streamFile);
} else {
/* some of these are dummies with zero offset, skip them when opening standalone BNK */
for (i = 0; i < num_sounds; i++) {
test_offset = read_32bit(offset + table_offset + 0x04 * i, streamFile);
/* ABK points at absolute indexes, i.e. with dummies included */
if (is_embedded != 0) {
if (target_stream - 1 == i)
header_offset = offset + table_offset + 0x04 * i + test_offset;
}
else {
/* Ignore dummy streams when opening standalone BNK files */
if (test_offset != 0) {
if (target_stream == real_bnk_sounds)
header_offset = offset + table_offset + 0x04 * i + test_offset;
real_bnk_sounds++;
}
}
}
if (target_stream < 0 || header_offset == 0 || real_bnk_sounds < 1) goto fail;
if (header_offset == 0) goto fail;
if (!parse_variable_header(streamFile,&ea, header_offset, header_size - header_offset, bnk_version))
if (!parse_variable_header(streamFile, &ea, header_offset, header_size - header_offset, bnk_version))
goto fail;
/* fix absolute offsets so it works in next funcs */
@ -843,22 +845,22 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
vgmstream->layout_type = layout_none;
/* BNKs usually have absolute offsets for all channels ("full" interleave) except in some versions */
if (vgmstream->channels > 1 && ea->codec1 == EA_CODEC1_PCM) {
int interleave = (vgmstream->num_samples * (ea->bps == 8 ? 0x01 : 0x02)); /* full interleave */
for (i = 0; i < vgmstream->channels; i++) {
if (ea->channels > 1 && ea->codec1 == EA_CODEC1_PCM) {
int interleave = (ea->num_samples * (ea->bps == 8 ? 0x01 : 0x02)); /* full interleave */
for (i = 0; i < ea->channels; i++) {
ea->offsets[i] = ea->offsets[0] + interleave*i;
}
}
else if (vgmstream->channels > 1 && ea->codec1 == EA_CODEC1_VAG) {
int interleave = (vgmstream->num_samples / 28 * 16); /* full interleave */
for (i = 0; i < vgmstream->channels; i++) {
else if (ea->channels > 1 && ea->codec1 == EA_CODEC1_VAG) {
int interleave = (ea->num_samples / 28 * 16); /* full interleave */
for (i = 0; i < ea->channels; i++) {
ea->offsets[i] = ea->offsets[0] + interleave*i;
}
}
else if (vgmstream->channels > 1 && ea->codec2 == EA_CODEC2_GCADPCM && ea->offsets[0] == ea->offsets[1]) {
else if (ea->channels > 1 && ea->codec2 == EA_CODEC2_GCADPCM && ea->offsets[0] == ea->offsets[1]) {
/* pcstream+gcadpcm with sx.exe v2, this is probably a bug (even with this parts of the wave are off) */
int interleave = (vgmstream->num_samples / 14 * 8); /* full interleave */
for (i = 0; i < vgmstream->channels; i++) {
int interleave = (ea->num_samples / 14 * 8); /* full interleave */
for (i = 0; i < ea->channels; i++) {
ea->offsets[i] = ea->offsets[0] + interleave*i;
}
}
@ -893,7 +895,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
break;
case EA_CODEC2_S16LE: /* PCM16LE */
if (ea->version > 0) {
if (ea->version > EA_VERSION_V0) {
vgmstream->coding_type = coding_PCM16LE;
} else { /* Need for Speed III: Hot Pursuit (PC) */
vgmstream->coding_type = coding_PCM16_int;
@ -915,7 +917,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
{
int16_t (*read_16bit)(off_t,STREAMFILE*) = ea->big_endian ? read_16bitBE : read_16bitLE;
for (ch=0; ch < vgmstream->channels; ch++) {
for (ch=0; ch < ea->channels; ch++) {
for (i=0; i < 16; i++) { /* actual size 0x21, last byte unknown */
vgmstream->ch[ch].adpcm_coef[i] = read_16bit(ea->coefs[ch] + i*2, streamFile);
}
@ -963,7 +965,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
/* make relative loops absolute for the decoder */
if (ea->loop_flag) {
for (i = 0; i < vgmstream->channels; i++) {
for (i = 0; i < ea->channels; i++) {
ea->loops[i] += ea->offsets[0];
}
}
@ -1030,13 +1032,13 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
// vgmstream->ch[i].offset = ea->offsets[0] + vgmstream->interleave_block_size*i;
// }
//}
else if (vgmstream->coding_type == coding_PCM16_int && ea->version == 0) {
/* Need for Speed 2 (PC) bad offsets */
else if (vgmstream->coding_type == coding_PCM16_int && ea->version == EA_VERSION_V0) {
/* Need for Speed II (PC) bad offsets */
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = ea->offsets[0] + 0x02*i;
}
}
else if (vgmstream->coding_type == coding_PCM8 && ea->platform == EA_PLATFORM_PS2 && ea->version == 3) {
else if (vgmstream->coding_type == coding_PCM8 && ea->platform == EA_PLATFORM_PS2 && ea->version == EA_VERSION_V3) {
/* SSX3 (PS2) weird 0x10 mini header (codec/loop start/loop end/samples) */
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = ea->offsets[0] + 0x10;
@ -1471,7 +1473,7 @@ static void update_ea_stream_size_and_samples(STREAMFILE* streamFile, off_t star
* music (.map/lin). Subfiles always share header, except num_samples. */
num_samples += vgmstream->current_block_samples;
/* Stream size is almost never provided in bank files so we have to calc it manually */
/* stream size is almost never provided in bank files so we have to calc it manually */
stream_size += vgmstream->next_block_offset - vgmstream->ch[0].offset;
}
}

View File

@ -267,6 +267,12 @@ static const hcakey_info hcakey_list[] = {
/* Mashiro Witch (Android) */
{0x55D11D3349495204}, // 55D11D3349495204
/* Iris Mysteria! (Android) */
{62049655719861786}, // 00DC71D5479E1E1A
/* Kotodaman (Android) */
{19850716}, // 00000000012EE5DC
};
#endif/*_HCA_KEYS_H_*/

View File

@ -5,45 +5,47 @@
static const uint16_t subkeys_dgl[] = { /* Dragalia Lost (Cygames) [iOS/Android] */
0x0152,0x0165,0x0192,0x01E8,0x0240,0x026B,0x02B8,0x0348,0x055E,0x0595,0x05DC,0x0606,0x0636,0x0690,0x06A1,0x06A4,
0x06B3,0x0760,0x0767,0x076E,0x076F,0x07A6,0x07AA,0x07B4,0x07CC,0x080D,0x082B,0x084C,0x0859,0x085B,0x0861,0x0864,
0x0865,0x0873,0x088A,0x089B,0x08A5,0x08A7,0x08C3,0x08C6,0x08D5,0x08D8,0x08E0,0x08E8,0x08EF,0x08F0,0x0908,0x090B,
0x0916,0x0919,0x0923,0x0926,0x0929,0x092C,0x092D,0x092F,0x0942,0x0944,0x094C,0x094E,0x0957,0x095F,0x0963,0x0964,
0x096C,0x097B,0x097D,0x0988,0x099E,0x09AE,0x09C1,0x09C2,0x09C5,0x09C8,0x09D7,0x09FF,0x0A00,0x0A02,0x0A12,0x0A16,
0x0A19,0x0A25,0x0A2A,0x0A2F,0x0A30,0x0A31,0x0A3F,0x0A41,0x0A53,0x0A63,0x0A65,0x0A6D,0x0A73,0x0A77,0x0A99,0x0A9A,
0x0AA5,0x0AA8,0x0AB8,0x0AC2,0x0AC5,0x0ACC,0x0AE0,0x0AE3,0x0AEC,0x0B09,0x0B0C,0x0B35,0x0B5B,0x0B6F,0x0B7C,0x0B8D,
0x0BA1,0x0BB0,0x0BBE,0x0BC9,0x0BDE,0x0BEF,0x0C04,0x0C0F,0x0C30,0x0C8B,0x0C9A,0x0C9F,0x0CA9,0x0CB9,0x0D71,0x0DB0,
0x0DCF,0x0DD4,0x0DE6,0x0E1C,0x0E66,0x0E9D,0x0EAF,0x0EBB,0x0FDA,0x102F,0x103A,0x1074,0x10BF,0x10C7,0x1107,0x113A,
0x116F,0x11A6,0x11FB,0x1220,0x130E,0x1335,0x135B,0x13C0,0x1474,0x1538,0x1585,0x15AD,0x15E1,0x1748,0x1892,0x18A4,
0x1944,0x197A,0x19F3,0x1A47,0x1A5B,0x1A89,0x1AAC,0x1C31,0x1C3B,0x1C7C,0x1C7E,0x1D01,0x1D0C,0x1D5A,0x1E1E,0x1E88,
0x1F0A,0x1FC2,0x2000,0x2007,0x208C,0x20E9,0x20EE,0x2160,0x216E,0x21CA,0x221E,0x2265,0x2275,0x2277,0x22C4,0x22FA,
0x2330,0x2379,0x23C9,0x23D8,0x2415,0x243C,0x245A,0x24AD,0x24CD,0x2540,0x2632,0x264C,0x269B,0x26B5,0x26C5,0x26FC,
0x2701,0x274D,0x274E,0x2777,0x27EE,0x284B,0x288C,0x28A9,0x28B6,0x292B,0x2930,0x29B0,0x29B2,0x29D9,0x2A0A,0x2A47,
0x2A55,0x2A5D,0x2ADB,0x2AE7,0x2D08,0x2DB0,0x2DB7,0x2DC3,0x2E6E,0x2E75,0x2E9E,0x2EB6,0x2ED8,0x2F64,0x2F66,0x2F72,
0x30BB,0x30CA,0x30E6,0x3160,0x3218,0x32E8,0x333F,0x338B,0x33BE,0x355A,0x357D,0x35DD,0x3619,0x36AA,0x3738,0x3752,
0x37DE,0x3804,0x380C,0x3920,0x39DB,0x3C7B,0x3CA3,0x3D50,0x3EB2,0x3EF2,0x3F42,0x3F79,0x4000,0x403D,0x40BF,0x40DE,
0x413E,0x414F,0x41A3,0x42EA,0x434A,0x43D3,0x43E9,0x4411,0x4541,0x4751,0x4793,0x47DF,0x4840,0x487A,0x48D7,0x49B4,
0x49E3,0x4B0E,0x4B21,0x4B8D,0x4C49,0x4C72,0x4D44,0x4D86,0x4DEA,0x4DF5,0x4E40,0x4F60,0x4F92,0x4FF2,0x5220,0x5493,
0x54CE,0x552C,0x559B,0x5639,0x567C,0x56A1,0x56EE,0x5794,0x582E,0x5846,0x586A,0x58B1,0x58C3,0x59A5,0x59EF,0x5A86,
0x5B19,0x5B49,0x5B5C,0x5B90,0x5BCF,0x5C38,0x5C75,0x5C83,0x5D61,0x5DE0,0x5E47,0x5E57,0x5ED5,0x6000,0x601F,0x6071,
0x6104,0x6188,0x6191,0x61B2,0x61EB,0x6226,0x627D,0x62F9,0x63DE,0x645F,0x64D3,0x659D,0x65D3,0x65D4,0x65F2,0x6631,
0x6914,0x6990,0x6993,0x6A52,0x6A85,0x6B16,0x6BF6,0x6CD6,0x6CE3,0x6CF9,0x6CFA,0x6D0E,0x6D16,0x6D3E,0x6D80,0x6DCF,
0x6E73,0x6EC5,0x6F14,0x6FD0,0x7033,0x704C,0x7098,0x7242,0x7278,0x7319,0x7427,0x7432,0x747F,0x7484,0x749D,0x74D7,
0x74D8,0x756A,0x7576,0x7588,0x75A9,0x764D,0x773C,0x7766,0x7895,0x78B0,0x78F3,0x7976,0x798F,0x79E7,0x79F9,0x7A1D,
0x7A24,0x7A47,0x7B64,0x7BBC,0x7C2E,0x7CBA,0x7D0D,0x7D12,0x7E66,0x7EB5,0x7EBA,0x7EC5,0x7F1B,0x7F26,0x7F5F,0x7FC1,
0x7FCE,0x7FFC,0x8000,0x8075,0x80B2,0x80FF,0x81C8,0x826C,0x8274,0x82B5,0x8412,0x8458,0x8467,0x8533,0x8577,0x85FF,
0x8658,0x86E3,0x86E6,0x878E,0x885E,0x8A7E,0x8B1F,0x8B25,0x8B33,0x8B4D,0x8B80,0x8BFF,0x8C38,0x8D46,0x8D8B,0x8E10,
0x8E79,0x8F01,0x8FF1,0x9000,0x9029,0x9082,0x924A,0x92F8,0x9342,0x940C,0x94B9,0x9580,0x95ED,0x9630,0x97D1,0x97FC,
0x9810,0x9825,0x9861,0x98FB,0x990E,0x9970,0x9A37,0x9B36,0x9B67,0x9FA3,0x9FF2,0xA000,0xA0A3,0xA1C6,0xA27A,0xA2FB,
0xA3AB,0xA3C2,0xA4E1,0xA548,0xA553,0xA585,0xA6A7,0xA71C,0xA723,0xA77E,0xA7D6,0xA894,0xA8BF,0xA8E0,0xA90A,0xAA3A,
0xAA57,0xAADF,0xAAF4,0xAB0B,0xABF3,0xAC0C,0xAC23,0xAC55,0xAD00,0xADC4,0xADF1,0xAE02,0xAE16,0xAE6A,0xAEA7,0xAEB6,
0xB040,0xB073,0xB122,0xB14B,0xB175,0xB177,0xB25D,0xB262,0xB332,0xB378,0xB400,0xB52E,0xB54B,0xB592,0xB59C,0xB5AD,
0xB5CE,0xB5D3,0xB5D5,0xB613,0xB65D,0xB79F,0xB89D,0xB907,0xBC78,0xBCCC,0xBDBF,0xBE21,0xBF21,0xBF64,0xC13F,0xC2EA,
0xC303,0xC385,0xC3C9,0xC3D8,0xC452,0xC5CB,0xC5EB,0xC655,0xC67B,0xC6D9,0xC728,0xC8A8,0xCAF6,0xCDAC,0xCDF7,0xD075,
0xD163,0xD203,0xD410,0xD49E,0xD718,0xD876,0xD99C,0xDA29,0xDAA7,0xDBA0,0xDC8F,0xDCFA,0xDD3D,0xDD55,0xDE02,0xDE30,
0xE000,0xE02E,0xE073,0xE1C5,0xE1CD,0xE288,0xE3AE,0xE597,0xE5E3,0xE652,0xE775,0xE930,0xE947,0xEC15,0xEC1B,0xED0A,
0xED93,0xED95,0xEDC2,0xEF7F,0xEFA6,0xEFB6,0xF049,0xF0C7,0xF107,0xF41F,0xF558,0xF5C8,0xF7DC,0xF7ED,0xF89E,0xF8B2,
0xF9C9,0xFAAA,0xFB77,0xFCAF,0xFCCA,0xFD01,0xFD13,0xFD57,0xFD68,0xFDDB,0xFE07,0xFF43,0xFF65,0xFF85,0xFF8B,0xFF9A,
0xFFD0,
0x06B3,0x0760,0x0767,0x076E,0x076F,0x077B,0x07A6,0x07AA,0x07B4,0x07CC,0x080D,0x082B,0x084C,0x084E,0x0859,0x085B,
0x0861,0x0864,0x0865,0x0873,0x088A,0x089B,0x08A5,0x08A7,0x08C0,0x08C3,0x08C6,0x08D5,0x08D8,0x08E0,0x08E8,0x08EB,
0x08EF,0x08F0,0x0902,0x0908,0x090B,0x0916,0x0919,0x0923,0x0926,0x0929,0x092C,0x092D,0x092F,0x0942,0x0944,0x094C,
0x094E,0x0957,0x095F,0x0963,0x0964,0x096C,0x097B,0x097D,0x0988,0x099E,0x09AE,0x09C1,0x09C2,0x09C5,0x09C8,0x09D7,
0x09FF,0x0A00,0x0A02,0x0A12,0x0A16,0x0A19,0x0A25,0x0A2A,0x0A2F,0x0A30,0x0A31,0x0A3F,0x0A41,0x0A53,0x0A63,0x0A65,
0x0A6D,0x0A73,0x0A77,0x0A99,0x0A9A,0x0AA5,0x0AA8,0x0AB8,0x0AC2,0x0AC5,0x0ACC,0x0AE0,0x0AE3,0x0AEC,0x0B09,0x0B0C,
0x0B35,0x0B5B,0x0B6F,0x0B7C,0x0B8D,0x0BA1,0x0BB0,0x0BBE,0x0BC9,0x0BDE,0x0BEF,0x0C04,0x0C0F,0x0C30,0x0C8B,0x0C9A,
0x0C9F,0x0CA9,0x0CB9,0x0D71,0x0D7B,0x0DB0,0x0DCF,0x0DD4,0x0DE6,0x0E1C,0x0E66,0x0E9D,0x0EAF,0x0EBB,0x0FDA,0x102F,
0x103A,0x1074,0x10BF,0x10C7,0x1107,0x112F,0x113A,0x116F,0x11A6,0x11FB,0x1220,0x130E,0x1335,0x135B,0x13C0,0x1474,
0x1538,0x1585,0x15AD,0x15E1,0x1748,0x178C,0x1892,0x18A4,0x1944,0x197A,0x19F3,0x1A47,0x1A5B,0x1A89,0x1AAC,0x1BE2,
0x1C31,0x1C3B,0x1C7C,0x1C7E,0x1C89,0x1D01,0x1D0C,0x1D5A,0x1DA3,0x1E1E,0x1E88,0x1F0A,0x1F6D,0x1FC2,0x2000,0x2007,
0x208C,0x20E9,0x20EE,0x2120,0x2160,0x2161,0x216E,0x21CA,0x21DD,0x221E,0x2227,0x2265,0x2275,0x2277,0x22C4,0x22FA,
0x2330,0x2379,0x23C9,0x23D8,0x2415,0x243C,0x245A,0x24AD,0x24CD,0x2514,0x2540,0x2632,0x264C,0x269B,0x26B5,0x26C5,
0x26FC,0x2701,0x2709,0x274D,0x274E,0x2777,0x27EE,0x284B,0x2882,0x288C,0x28A9,0x28B6,0x292B,0x2930,0x29B0,0x29B2,
0x29D9,0x2A0A,0x2A47,0x2A55,0x2A5D,0x2ADB,0x2AE7,0x2D08,0x2DB0,0x2DB7,0x2DC3,0x2E6E,0x2E75,0x2E9E,0x2EB6,0x2ED8,
0x2F64,0x2F66,0x2F72,0x30BB,0x30CA,0x30E6,0x3160,0x3218,0x32E8,0x333F,0x338B,0x33BE,0x355A,0x357D,0x35DD,0x360C,
0x3619,0x36AA,0x3738,0x3752,0x37DE,0x3804,0x380C,0x3920,0x39DB,0x3C7B,0x3CA3,0x3D50,0x3EB2,0x3EF2,0x3F42,0x3F79,
0x4000,0x403D,0x40BF,0x40DE,0x413E,0x414F,0x41A3,0x42EA,0x434A,0x43D3,0x43E9,0x4411,0x4541,0x4663,0x4751,0x4793,
0x47DF,0x4840,0x487A,0x48D7,0x49B4,0x49E3,0x4B0E,0x4B21,0x4B8D,0x4C49,0x4C72,0x4D44,0x4D86,0x4DEA,0x4DF5,0x4E40,
0x4F60,0x4F92,0x4FF2,0x5137,0x5220,0x5493,0x54CE,0x552C,0x559B,0x5639,0x567C,0x56A1,0x56EE,0x5794,0x582E,0x5846,
0x586A,0x58B1,0x58C3,0x59A5,0x59EF,0x5A86,0x5B19,0x5B49,0x5B5C,0x5B90,0x5BCF,0x5C38,0x5C75,0x5C83,0x5D61,0x5DE0,
0x5E47,0x5E57,0x5ED5,0x5FAF,0x6000,0x601F,0x6071,0x6104,0x6188,0x6191,0x61B2,0x61EB,0x6226,0x627D,0x62F9,0x63DE,
0x645F,0x64D3,0x659D,0x65D3,0x65D4,0x65F2,0x6631,0x6914,0x6990,0x6993,0x6A52,0x6A85,0x6B16,0x6BF6,0x6CD6,0x6CE3,
0x6CF9,0x6CFA,0x6D0E,0x6D16,0x6D1E,0x6D3E,0x6D80,0x6DCF,0x6E73,0x6EC5,0x6F14,0x6FD0,0x7033,0x704C,0x7098,0x7242,
0x7278,0x72B7,0x7319,0x7427,0x7432,0x747F,0x7484,0x749D,0x74D7,0x74D8,0x756A,0x7576,0x7588,0x75A9,0x764D,0x773C,
0x7766,0x7895,0x78B0,0x78F3,0x7976,0x797F,0x798F,0x79AB,0x79E7,0x79F9,0x7A1D,0x7A24,0x7A47,0x7B64,0x7BBC,0x7C2E,
0x7CBA,0x7D0D,0x7D12,0x7E66,0x7EB5,0x7EBA,0x7EC5,0x7F1B,0x7F26,0x7F5F,0x7FC1,0x7FCE,0x7FFC,0x8000,0x8075,0x80B2,
0x80FF,0x81C8,0x826C,0x8274,0x82B5,0x8412,0x8458,0x8467,0x8533,0x8577,0x85FF,0x8658,0x86E3,0x86E6,0x878E,0x885E,
0x8A7E,0x8B1F,0x8B25,0x8B33,0x8B4D,0x8B80,0x8BFF,0x8C38,0x8D46,0x8D8B,0x8E10,0x8E79,0x8F01,0x8FF1,0x9000,0x9029,
0x9082,0x924A,0x92F8,0x9342,0x940C,0x94B9,0x9580,0x95ED,0x9630,0x97D1,0x97FC,0x9810,0x9825,0x9861,0x98FB,0x990E,
0x9970,0x9A37,0x9B36,0x9B67,0x9DBF,0x9FA3,0x9FF2,0xA000,0xA0A3,0xA0AA,0xA1C6,0xA27A,0xA2FB,0xA3AB,0xA3C2,0xA4E1,
0xA548,0xA553,0xA585,0xA6A7,0xA71C,0xA723,0xA77E,0xA7D6,0xA894,0xA8BF,0xA8E0,0xA90A,0xAA3A,0xAA57,0xAADF,0xAAF4,
0xAB0B,0xABF3,0xAC0C,0xAC23,0xAC55,0xAD00,0xADC4,0xADF1,0xAE02,0xAE16,0xAE6A,0xAEA7,0xAEB6,0xB040,0xB073,0xB122,
0xB14B,0xB175,0xB177,0xB25D,0xB262,0xB332,0xB378,0xB400,0xB52E,0xB54B,0xB592,0xB59C,0xB5AD,0xB5CE,0xB5D3,0xB5D5,
0xB613,0xB65D,0xB79F,0xB89D,0xB907,0xBC78,0xBCCC,0xBDBF,0xBE21,0xBF21,0xBF64,0xC13F,0xC2EA,0xC303,0xC385,0xC3C9,
0xC3D8,0xC452,0xC5CB,0xC5EB,0xC62D,0xC655,0xC67B,0xC6D9,0xC728,0xC8A8,0xCAF6,0xCDAC,0xCDF7,0xCE3B,0xD075,0xD163,
0xD203,0xD410,0xD49E,0xD70A,0xD718,0xD815,0xD876,0xD99C,0xDA29,0xDAA7,0xDBA0,0xDC8F,0xDCFA,0xDD3D,0xDD55,0xDE02,
0xDE30,0xE000,0xE02E,0xE073,0xE1C5,0xE1CD,0xE288,0xE3AE,0xE597,0xE5C3,0xE5E3,0xE652,0xE775,0xE930,0xE947,0xEC15,
0xEC1B,0xEC56,0xED0A,0xED93,0xED95,0xEDC2,0xEF7F,0xEFA6,0xEFB6,0xF049,0xF0C7,0xF107,0xF41F,0xF558,0xF5C8,0xF7DC,
0xF7ED,0xF89E,0xF8B2,0xF9C9,0xFAAA,0xFB77,0xFCAF,0xFCCA,0xFD01,0xFD13,0xFD57,0xFD68,0xFDDB,0xFE07,0xFF43,0xFF65,
0xFF85,0xFF8B,0xFF9A,0xFFD0,
};
#if 0

View File

@ -738,6 +738,7 @@ VGMSTREAM * init_vgmstream_ppst(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_opus_sps_n1_segmented(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ubi_bao_pk(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ubi_bao_atomic(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile);
@ -768,8 +769,7 @@ VGMSTREAM * init_vgmstream_ahv(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_msv(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sdf_ps2(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sdf_3ds(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_sdf(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_svg(STREAMFILE *streamFile);
@ -826,4 +826,8 @@ VGMSTREAM * init_vgmstream_smp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_gin(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_dsf(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_208(STREAMFILE * streamFile);
#endif /*_META_H*/

View File

@ -279,8 +279,11 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
* .xsew: Mega Man X Legacy Collections (PC)
* .adpcm: Angry Birds Transformers (Android)
* .adw: Dead Rising 2 (PC)
* .wd: Genma Onimusha (Xbox) voices */
if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd") ) {
* .wd: Genma Onimusha (Xbox) voices
* (extensionless): Myst III (Xbox)
* .sbv: Spongebob Squarepants - The Movie (PC)
* .wvx: Godzilla - Destroy All Monsters Melee (Xbox) */
if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv") ) {
;
}
else if ( check_extensions(streamFile, "mwv") ) {

View File

@ -1,90 +1,93 @@
#include "meta.h"
#include "../coding/coding.h"
/* SDF - from Beyond Reality games [Agent Hugo - Lemoon Twist (PS2)] */
VGMSTREAM * init_vgmstream_sdf_ps2(STREAMFILE *streamFile) {
/* SDF - from Beyond Reality games */
VGMSTREAM * init_vgmstream_sdf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
size_t data_size;
int loop_flag, channel_count;
int loop_flag, channel_count, sample_rate, interleave, coefs_offset;
/* checks */
if ( !check_extensions(streamFile,"sdf") )
if (!check_extensions(streamFile,"sdf"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53444600) /* "SDF\0" */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x03000000) /* version? */
goto fail;
start_offset = 0x18;
data_size = get_streamfile_size(streamFile) - start_offset;
if (read_32bitLE(0x08,streamFile) != data_size)
goto fail;
data_size = read_32bitLE(0x08,streamFile);
start_offset = get_streamfile_size(streamFile) - data_size;
channel_count = read_32bitLE(0x10,streamFile);
loop_flag = 0; /* all files have loop flags but simply fade out normally and repeat */
switch(start_offset) {
case 0x18: /* Agent Hugo - Lemoon Twist (PS2)*/
sample_rate = read_32bitLE(0x0c,streamFile);
channel_count = read_32bitLE(0x10,streamFile);
interleave = read_32bitLE(0x14,streamFile);
break;
case 0x78: /* Gummy Bears Mini Golf (3DS) */
sample_rate = read_32bitLE(0x10,streamFile);
channel_count = read_32bitLE(0x14,streamFile);
interleave = read_32bitLE(0x18,streamFile);
coefs_offset = 0x1c;
break;
case 0x84: /* Mr. Bean's Wacky World (Wii) */
sample_rate = read_32bitLE(0x10,streamFile);
channel_count = read_32bitLE(0x14,streamFile);
interleave = read_32bitLE(0x18,streamFile);
data_size = read_32bitLE(0x20,streamFile); /* usable size */
coefs_offset = 0x28;
break;
default:
goto fail;
}
loop_flag = 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SDF_PS2;
vgmstream->sample_rate = read_32bitLE(0x0c,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(data_size,channel_count);
vgmstream->meta_type = meta_SDF;
vgmstream->sample_rate = sample_rate;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile);
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* SDF - from Beyond Reality games [Gummy Bears Mini Golf (3DS)] */
VGMSTREAM * init_vgmstream_sdf_3ds(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
size_t data_size;
int loop_flag, channel_count;
/* checks */
if ( !check_extensions(streamFile,"sdf") )
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53444600) /* "SDF\0" */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x03000000) /* version? */
goto fail;
start_offset = 0x78; /* assumed */
data_size = get_streamfile_size(streamFile) - start_offset;
if (read_32bitLE(0x08,streamFile) != data_size)
goto fail;
channel_count = read_32bitLE(0x14,streamFile);
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_SDF_3DS;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = dsp_bytes_to_samples(data_size,channel_count);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = data_size / channel_count;
dsp_read_coefs_le(vgmstream,streamFile,0x1c,0x2e);
//todo: there be hist around 0x3c
switch(start_offset) {
case 0x18:
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
vgmstream->num_samples = ps_bytes_to_samples(data_size,channel_count);
break;
case 0x78:
case 0x84:
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
if (vgmstream->interleave_block_size == 0) /* Gummy Bears Mini Golf */
vgmstream->interleave_block_size = data_size / channel_count;
vgmstream->num_samples = dsp_bytes_to_samples(data_size,channel_count);
dsp_read_coefs_le(vgmstream, streamFile, coefs_offset+0x00,0x2e);
dsp_read_hist_le (vgmstream, streamFile, coefs_offset+0x24,0x2e);
break;
default:
goto fail;
}
/* most songs simply repeat; don't loop if too short (in seconds) */
if (vgmstream->num_samples > 10*sample_rate) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;

View File

@ -1,15 +1,12 @@
#include "meta.h"
static void parse_adtl(off_t adtl_offset, off_t adtl_length, STREAMFILE *streamFile, long *loop_start, long *loop_end, int *loop_flag);
/* .sfl - odd RIFF-formatted files that go along with .ogg [Hanachirasu (PC), Touhou 10.5 (PC)] */
VGMSTREAM * init_vgmstream_sfl_ogg(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamData = NULL;
int loop_flag = 0;
long loop_start_ms = -1;
long loop_end_ms = -1;
int loop_start = 0, loop_end = 0;
/* checks */
@ -26,7 +23,7 @@ VGMSTREAM * init_vgmstream_sfl_ogg(STREAMFILE *streamFile) {
get_streamfile_basename(streamFile,basename,PATH_LIMIT);
streamData = open_streamfile_by_filename(streamFile, basename);
if (!streamData) {
/* try again with file.sfl=header + file.ogg=daba */
/* try again with file.sfl=header + file.ogg=data */
streamData = open_streamfile_by_ext(streamFile,"ogg");
if (!streamData) goto fail;
}
@ -47,51 +44,82 @@ VGMSTREAM * init_vgmstream_sfl_ogg(STREAMFILE *streamFile) {
/* read through chunks to verify format and find metadata */
{
size_t riff_size, file_size;
off_t current_chunk = 0x0c; /* start with first chunk */
off_t current_chunk = 0x0c;
size_t riff_size = read_32bitLE(0x04,streamFile);
size_t file_size = get_streamfile_size(streamFile);
riff_size = read_32bitLE(0x04,streamFile);
file_size = get_streamfile_size(streamFile);
if (file_size < riff_size+0x08)
goto fail;
/* sfl loops come in two varieties:
* - "cue " (start) + "LIST" with "rgn" (length) [Touhou]
* - "cue " (start+end) [Hanachirasu]
* Both may have "LIST" with optional "labl" markers (start+end or start+length in seconds),
* that can be parsed to get loops, but aren't sample-accurate nor always exist.
*/
while (current_chunk < file_size) {
uint32_t chunk_type = read_32bitBE(current_chunk+0x00,streamFile);
off_t chunk_size = read_32bitLE(current_chunk+0x04,streamFile);
size_t chunk_size = read_32bitLE(current_chunk+0x04,streamFile);
/* There seem to be a few bytes left over, included in the
* RIFF but not enough to make a new chunk. */
if (current_chunk+0x08 > file_size) break;
if (current_chunk+0x08+chunk_size > file_size)
if (current_chunk + 0x08 + chunk_size > file_size)
goto fail;
switch(chunk_type) {
case 0x4C495354: /* "LIST" */
switch (read_32bitBE(current_chunk+0x08, streamFile)) {
case 0x6164746C: /* "adtl" */
/* yay, atdl is its own little world */
parse_adtl(current_chunk + 0x08, chunk_size, streamFile,
&loop_start_ms,&loop_end_ms,&loop_flag);
case 0x63756520: /* "cue " */
switch (read_32bitLE(current_chunk+0x08+0x00, streamFile)) { /* cue count */
case 1:
loop_start = read_32bitLE(current_chunk+0x08+0x04+0x04, streamFile);
break;
case 2:
loop_start = read_32bitLE(current_chunk+0x08+0x04+0x04, streamFile);
loop_end = read_32bitLE(current_chunk+0x08+0x1c+0x04, streamFile);
/* cues can be unordered */
if (loop_start > loop_end) {
long temp = loop_start;
loop_start = loop_end;
loop_end = temp;
}
break;
default:
goto fail;
}
break;
case 0x4C495354: /* "LIST" */
/* "LIST" is chunk-based too but in practice sfl always follows the same order */
switch (read_32bitBE(current_chunk+0x08+0x00, streamFile)) {
case 0x6164746C: /* "adtl" */
if (read_32bitBE(current_chunk+0x08+0x04, streamFile) == 0x6C747874 && /* "ltxt" */
read_32bitBE(current_chunk+0x08+0x14, streamFile) == 0x72676E20) { /* "rgn " */
loop_end = read_32bitLE(current_chunk+0x08+0x10, streamFile) + loop_start;
}
break;
case 0x6c61626c: /* "labl" */
default:
break;
}
break;
case 0x53465049: /* "SFPI": filename info */
default:
break;
}
current_chunk += 0x08+chunk_size;
/* there may be padding bytes, included in riff_size but not enough to make a new chunk */
if (current_chunk + 0x08 > file_size)
break;
}
}
/* install loops */
loop_flag = (loop_end > 0);
/* install loops (sfl .ogg often has song endings too, use the base .ogg for those) */
if (loop_flag) {
int loop_start = (long long)loop_start_ms * vgmstream->sample_rate / 1000;
int loop_end = (long long)loop_end_ms * vgmstream->sample_rate / 1000;
vgmstream_force_loop(vgmstream,loop_flag,loop_start, loop_end);
}
/* sfl .ogg often has song endings (use the base .ogg for those) */
close_streamfile(streamData);
return vgmstream;
@ -101,94 +129,3 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
/* return milliseconds */
static long parse_adtl_marker(unsigned char * marker) {
long hh,mm,ss,ms;
if (memcmp("Marker ",marker,7)) return -1;
if (4 != sscanf((char*)marker+7,"%ld:%ld:%ld.%ld",&hh,&mm,&ss,&ms))
return -1;
return ((hh*60+mm)*60+ss)*1000+ms;
}
/* return milliseconds */
static int parse_region(unsigned char * region, long *start, long *end) {
long start_hh,start_mm,start_ss,start_ms;
long end_hh,end_mm,end_ss,end_ms;
if (memcmp("Region ",region,7)) return -1;
if (8 != sscanf((char*)region+7,"%ld:%ld:%ld.%ld to %ld:%ld:%ld.%ld",
&start_hh,&start_mm,&start_ss,&start_ms,
&end_hh,&end_mm,&end_ss,&end_ms))
return -1;
*start = ((start_hh*60+start_mm)*60+start_ss)*1000+start_ms;
*end = ((end_hh*60+end_mm)*60+end_ss)*1000+end_ms;
return 0;
}
/* loop points have been found hiding here */
static void parse_adtl(off_t adtl_offset, off_t adtl_length, STREAMFILE *streamFile, long *loop_start, long *loop_end, int *loop_flag) {
int loop_start_found = 0;
int loop_end_found = 0;
off_t current_chunk = adtl_offset+0x04;
while (current_chunk < adtl_offset + adtl_length) {
uint32_t chunk_type = read_32bitBE(current_chunk+0x00,streamFile);
off_t chunk_size = read_32bitLE(current_chunk+0x04,streamFile);
if (current_chunk+0x08+chunk_size > adtl_offset+adtl_length)
return;
switch(chunk_type) {
case 0x6c61626c: { /* "labl" */
unsigned char *labelcontent = malloc(chunk_size-0x04);
if (!labelcontent) return;
if (read_streamfile(labelcontent,current_chunk+0x0c, chunk_size-0x04,streamFile) != chunk_size-0x04) {
free(labelcontent);
return;
}
switch (read_32bitLE(current_chunk+8,streamFile)) {
case 1:
if (!loop_start_found && (*loop_start = parse_adtl_marker(labelcontent)) >= 0)
loop_start_found = 1;
if (!loop_start_found && !loop_end_found && parse_region(labelcontent,loop_start,loop_end) >= 0) {
loop_start_found = 1;
loop_end_found = 1;
}
break;
case 2:
if (!loop_end_found && (*loop_end = parse_adtl_marker(labelcontent)) >= 0)
loop_end_found = 1;
break;
default:
break;
}
free(labelcontent);
break;
}
default:
break;
}
current_chunk += 0x08 + chunk_size;
}
if (loop_start_found && loop_end_found)
*loop_flag = 1;
/* labels don't seem to be consistently ordered */
if (*loop_start > *loop_end) {
long temp = *loop_start;
*loop_start = *loop_end;
*loop_end = temp;
}
}

View File

@ -28,12 +28,15 @@ typedef struct {
uint32_t loop_start_segment;
uint32_t loop_end_segment;
txtp_entry default_entry;
int default_entry_set;
size_t is_layered;
} txtp_header;
static txtp_header* parse_txtp(STREAMFILE* streamFile);
static void clean_txtp(txtp_header* txtp);
static void set_config(VGMSTREAM *vgmstream, txtp_entry *current);
static void apply_config(VGMSTREAM *vgmstream, txtp_entry *current);
/* TXTP - an artificial playlist-like format to play files with segments/layers/config */
@ -68,20 +71,12 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
close_streamfile(temp_streamFile);
if (!vgmstream) goto fail;
vgmstream->channel_mask = txtp->entry[0].channel_mask;
vgmstream->channel_mappings_on = txtp->entry[0].channel_mappings_on;
if(vgmstream->channel_mappings_on) {
for (i = 0; i < 32; i++) {
vgmstream->channel_mappings[i] = txtp->entry[0].channel_mappings[i];
}
}
apply_config(vgmstream, &txtp->entry[0]);
}
else if (txtp->is_layered) {
/* layered multi file */
int channel_count = 0, loop_flag;
/* init layout */
data_l = init_layout_layered(txtp->entry_count);
if (!data_l) goto fail;
@ -96,6 +91,9 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
close_streamfile(temp_streamFile);
if (!data_l->layers[i]) goto fail;
apply_config(data_l->layers[i], &txtp->entry[i]);
/* get actual channel count after config */
channel_count += data_l->layers[i]->channels;
}
@ -118,15 +116,6 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
vgmstream->coding_type = data_l->layers[0]->coding_type;
vgmstream->layout_type = layout_layered;
vgmstream->channel_mask = txtp->entry[0].channel_mask;
vgmstream->channel_mappings_on = txtp->entry[0].channel_mappings_on;
if (vgmstream->channel_mappings_on) {
for (i = 0; i < 32; i++) {
vgmstream->channel_mappings[i] = txtp->entry[0].channel_mappings[i];
}
}
vgmstream->layout_data = data_l;
}
else {
@ -134,7 +123,6 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
int num_samples, loop_start_sample = 0, loop_end_sample = 0;
int loop_flag, channel_count;
/* init layout */
data_s = init_layout_segmented(txtp->entry_count);
if (!data_s) goto fail;
@ -149,7 +137,7 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
close_streamfile(temp_streamFile);
if (!data_s->segments[i]) goto fail;
data_s->segments[i]->channel_mask = txtp->entry[0].channel_mask;
apply_config(data_s->segments[i], &txtp->entry[i]);
}
/* setup segmented VGMSTREAMs */
@ -192,8 +180,11 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
}
/* loop settings apply to the resulting vgmstream, so config based on first entry */
set_config(vgmstream, &txtp->entry[0]);
/* apply default config to the resulting file */
if (txtp->default_entry_set) {
apply_config(vgmstream, &txtp->default_entry);
}
clean_txtp(txtp);
return vgmstream;
@ -206,7 +197,17 @@ fail:
return NULL;
}
static void set_config(VGMSTREAM *vgmstream, txtp_entry *current) {
static void apply_config(VGMSTREAM *vgmstream, txtp_entry *current) {
vgmstream->channel_mask = current->channel_mask;
vgmstream->channel_mappings_on = current->channel_mappings_on;
if (vgmstream->channel_mappings_on) {
int ch;
for (ch = 0; ch < 32; ch++) {
vgmstream->channel_mappings[ch] = current->channel_mappings[ch];
}
}
vgmstream->config_loop_count = current->config_loop_count;
vgmstream->config_fade_time = current->config_fade_time;
vgmstream->config_fade_delay = current->config_fade_delay;
@ -217,6 +218,26 @@ static void set_config(VGMSTREAM *vgmstream, txtp_entry *current) {
/* ********************************** */
static void clean_filename(char * filename) {
int i;
size_t len;
if (filename[0] == '\0')
return;
/* normalize paths */
fix_dir_separators(filename);
/* remove trailing spaces */
len = strlen(filename);
for (i = len-1; i > 0; i--) {
if (filename[i] != ' ')
break;
filename[i] = '\0';
}
}
static void get_double(const char * config, double *value) {
int n;
if (sscanf(config, "%lf%n", value,&n) != 1) {
@ -224,7 +245,30 @@ static void get_double(const char * config, double *value) {
}
}
static int add_filename(txtp_header * txtp, char *filename) {
static void add_config(txtp_entry* current, txtp_entry* cfg, const char* filename) {
strcpy(current->filename, filename);
current->subsong = cfg->subsong;
current->channel_mask = cfg->channel_mask;
if (cfg->channel_mappings_on) {
int ch;
current->channel_mappings_on = cfg->channel_mappings_on;
for (ch = 0; ch < 32; ch++) {
current->channel_mappings[ch] = cfg->channel_mappings[ch];
}
}
current->config_loop_count = cfg->config_loop_count;
current->config_fade_time = cfg->config_fade_time;
current->config_fade_delay = cfg->config_fade_delay;
current->config_ignore_loop = cfg->config_ignore_loop;
current->config_force_loop = cfg->config_force_loop;
current->config_ignore_fade = cfg->config_ignore_fade;
}
static int add_filename(txtp_header * txtp, char *filename, int is_default) {
int i, n;
txtp_entry cfg = {0};
size_t range_start, range_end;
@ -365,7 +409,15 @@ static int add_filename(txtp_header * txtp, char *filename) {
}
fix_dir_separators(filename); /* clean paths */
clean_filename(filename);
//;VGM_LOG("TXTP: clean filename='%s'\n", filename);
/* config that applies to all files */
if (is_default) {
txtp->default_entry_set = 1;
add_config(&txtp->default_entry, &cfg, filename);
return 1;
}
/* add filenames */
for (i = range_start; i < range_end; i++){
@ -384,26 +436,9 @@ static int add_filename(txtp_header * txtp, char *filename) {
/* new entry */
current = &txtp->entry[txtp->entry_count];
memset(current,0, sizeof(txtp_entry));
strcpy(current->filename, filename);
cfg.subsong = (i+1);
current->subsong = (i+1);
current->channel_mask = cfg.channel_mask;
if (cfg.channel_mappings_on) {
int ch;
current->channel_mappings_on = cfg.channel_mappings_on;
for (ch = 0; ch < 32; ch++) {
current->channel_mappings[ch] = cfg.channel_mappings[ch];
}
}
current->config_loop_count = cfg.config_loop_count;
current->config_fade_time = cfg.config_fade_time;
current->config_fade_delay = cfg.config_fade_delay;
current->config_ignore_loop = cfg.config_ignore_loop;
current->config_force_loop = cfg.config_force_loop;
current->config_ignore_fade = cfg.config_ignore_fade;
add_config(current, &cfg, filename);
txtp->entry_count++;
}
@ -424,7 +459,7 @@ fail:
}
static int parse_keyval(txtp_header * txtp, const char * key, const char * val) {
//;VGM_LOG("TXTP: key %s = val %s\n", key,val);
//;VGM_LOG("TXTP: key=val '%s'='%s'\n", key,val);
if (0==strcmp(key,"loop_start_segment")) {
if (!parse_num(val, &txtp->loop_start_segment)) goto fail;
@ -440,13 +475,18 @@ static int parse_keyval(txtp_header * txtp, const char * key, const char * val)
goto fail;
}
}
else if (0==strcmp(key,"commands")) {
char val2[TXT_LINE_MAX];
strcpy(val2, val); /* copy since val is modified here but probably not important */
if (!add_filename(txtp, val2, 1)) goto fail;
}
else {
VGM_LOG("TXTP: unknown key=%s, val=%s\n", key,val);
goto fail;
}
return 1;
fail:
VGM_LOG("TXTP: error while parsing key=val '%s'='%s'\n", key,val);
return 0;
}
@ -471,7 +511,7 @@ static txtp_header* parse_txtp(STREAMFILE* streamFile) {
if (!ext) goto fail; /* ??? */
ext[0] = '\0';
if (!add_filename(txtp, filename))
if (!add_filename(txtp, filename, 0))
goto fail;
return txtp;
@ -494,8 +534,8 @@ static txtp_header* parse_txtp(STREAMFILE* streamFile) {
txt_offset += bytes_read;
/* get key/val (ignores lead/trail spaces, stops at space/comment/separator) */
ok = sscanf(line, " %[^ \t#=] = %[^ \t#\r\n] ", key,val);
/* get key/val (ignores lead/trail spaces, stops at space/separator) */
ok = sscanf(line, " %[^ \t#=] = %[^ \t\r\n] ", key,val);
if (ok == 2) { /* no key=val */
if (!parse_keyval(txtp, key, val)) /* read key/val */
goto fail;
@ -510,7 +550,7 @@ static txtp_header* parse_txtp(STREAMFILE* streamFile) {
continue; /* simple comment */
/* filename with config */
if (!add_filename(txtp, filename))
if (!add_filename(txtp, filename, 0))
goto fail;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
#ifndef _UBI_BAO_STREAMFILE_H_
#define _UBI_BAO_STREAMFILE_H_
//todo fix dupe code, but would be nice to keep it all in separate compilation units
#include "ubi_sb_streamfile.h"
static STREAMFILE* setup_ubi_bao_streamfile(STREAMFILE *streamFile, off_t stream_offset, size_t stream_size, int layer_number, int layer_count, int big_endian) {
return setup_ubi_sb_streamfile(streamFile, stream_offset, stream_size, layer_number, layer_count, big_endian);
}
#endif /* _UBI_BAO_STREAMFILE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -345,7 +345,7 @@ static STREAMFILE* setup_ubi_sb_streamfile(STREAMFILE *streamFile, off_t stream_
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;
new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, ubi_sb_io_read,ubi_sb_io_size);
new_streamFile = open_io_streamfile(new_streamFile, &io_data,io_data_size, ubi_sb_io_read,ubi_sb_io_size);
if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile;

View File

@ -184,7 +184,6 @@ static inline int64_t read_64bitBE(off_t offset, STREAMFILE * streamfile) {
if (read_streamfile(buf,offset,8,streamfile)!=8) return -1;
return get_64bitBE(buf);
}
static inline int8_t read_8bit(off_t offset, STREAMFILE * streamfile) {
uint8_t buf[1];
@ -193,13 +192,15 @@ static inline int8_t read_8bit(off_t offset, STREAMFILE * streamfile) {
}
/* guess byte endianness from a given value, return true if big endian and false if little endian */
/* TODO: possibly improve */
static inline int guess_endianness16bit(off_t offset, STREAMFILE * streamfile) {
return ((uint16_t)read_16bitLE(offset,streamfile) > (uint16_t)read_16bitBE(offset,streamfile)) ? 1 : 0;
uint8_t buf[0x02];
if (read_streamfile(buf,offset,0x02,streamfile) != 0x02) return -1; /* ? */
return (uint16_t)get_16bitLE(buf) > (uint16_t)get_16bitBE(buf) ? 1 : 0;
}
static inline int guess_endianness32bit(off_t offset, STREAMFILE * streamfile) {
return ((uint32_t)read_32bitLE(offset,streamfile) > (uint32_t)read_32bitBE(offset,streamfile)) ? 1 : 0;
uint8_t buf[0x04];
if (read_streamfile(buf,offset,0x04,streamfile) != 0x04) return -1; /* ? */
return (uint32_t)get_32bitLE(buf) > (uint32_t)get_32bitBE(buf) ? 1 : 0;
}
static inline size_t align_size_to_block(size_t value, size_t block_align) {

View File

@ -410,6 +410,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ppst,
init_vgmstream_opus_sps_n1_segmented,
init_vgmstream_ubi_bao_pk,
init_vgmstream_ubi_bao_atomic,
init_vgmstream_dsp_switch_audio,
init_vgmstream_sadf,
init_vgmstream_h4m,
@ -430,10 +431,9 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_a2m,
init_vgmstream_ahv,
init_vgmstream_msv,
init_vgmstream_sdf_ps2,
init_vgmstream_sdf,
init_vgmstream_svg,
init_vgmstream_vis,
init_vgmstream_sdf_3ds,
init_vgmstream_vai,
init_vgmstream_aif_asobo,
init_vgmstream_ao,
@ -463,6 +463,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_imc_container,
init_vgmstream_smp,
init_vgmstream_gin,
init_vgmstream_dsf,
init_vgmstream_208,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
@ -1248,6 +1250,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return 256; /* (0x8c - 0xc) * 2 */
case coding_ASF:
return 32; /* (0x11 - 0x1) * 2 */
case coding_DSA:
return 14; /* (0x08 - 0x1) * 2 */
case coding_XMD:
return (vgmstream->interleave_block_size - 0x06)*2 + 2;
case coding_EA_MT:
@ -1424,6 +1428,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 0x8c;
case coding_ASF:
return 0x11;
case coding_DSA:
return 0x08;
case coding_XMD:
return vgmstream->interleave_block_size;
case coding_EA_MT:
@ -2047,6 +2053,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
}
break;
case coding_DSA:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_dsa(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
}
break;
case coding_XMD:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_xmd(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
@ -2280,14 +2292,25 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
"encoding: ");
concatn(length,desc,temp);
switch (vgmstream->coding_type) {
//todo codec bugs with layout inside layouts (ex. TXTP)
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg: {
ffmpeg_codec_data *data = (ffmpeg_codec_data *)vgmstream->codec_data;
if (!data && vgmstream->layout_data) {
ffmpeg_codec_data *data = NULL;
if (vgmstream->layout_type == layout_layered) {
layered_layout_data* layout_data = vgmstream->layout_data;
if (layout_data->layers[0]->coding_type == coding_FFmpeg)
data = layout_data->layers[0]->codec_data;
}
else if (vgmstream->layout_type == layout_segmented) {
segmented_layout_data* layout_data = vgmstream->layout_data;
if (layout_data->segments[0]->coding_type == coding_FFmpeg)
data = layout_data->segments[0]->codec_data;
}
else {
data = vgmstream->codec_data;
}
if (data) {
if (data->codec && data->codec->long_name) {
@ -2637,7 +2660,7 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) {
return get_vgmstream_average_bitrate_from_size(vgmstream->stream_size, sample_rate, length_samples);
}
//todo bitrate bugs with layout inside layouts (ex. TXTP)
/* make a list of used streamfiles (repeats will be filtered below) */
if (vgmstream->layout_type==layout_segmented) {
segmented_layout_data *data = (segmented_layout_data *) vgmstream->layout_data;
@ -2786,7 +2809,6 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
if (!file) goto fail;
}
VGM_LOG("ch%i offset=%lx\n", ch,offset);
vgmstream->ch[ch].streamfile = file;
vgmstream->ch[ch].channel_start_offset =
vgmstream->ch[ch].offset = offset;

View File

@ -159,6 +159,7 @@ typedef enum {
coding_MC3, /* Paradigm MC3 3-bit ADPCM */
coding_FADPCM, /* FMOD FADPCM 4-bit ADPCM */
coding_ASF, /* Argonaut ASF 4-bit ADPCM */
coding_DSA, /* Ocean DSA 4-bit ADPCM */
coding_XMD, /* Konami XMD 4-bit ADPCM */
coding_PCFX, /* PC-FX 4-bit ADPCM */
coding_OKI16, /* OKI 4-bit ADPCM with 16-bit output */
@ -694,11 +695,10 @@ typedef enum {
meta_A2M, /* Scooby-Doo! Unmasked (PS2) */
meta_AHV, /* Headhunter (PS2) */
meta_MSV, /* Fight Club (PS2) */
meta_SDF_PS2, /* Agent Hugo - Lemoon Twist (PS2) */
meta_SDF,
meta_SVG, /* Hunter - The Reckoning - Wayward (PS2) */
meta_VIS, /* AirForce Delta Strike (PS2) */
meta_VAI, /* Ratatouille (GC) */
meta_SDF_3DS, /* Gummy Bears Mini Golf (3DS) */
meta_AIF_ASOBO, /* Ratatouille (PC) */
meta_AO, /* Cloudphobia (PC) */
meta_APC, /* MegaRace 3 (PC) */
@ -722,6 +722,8 @@ typedef enum {
meta_OGG_OPUS,
meta_IMC,
meta_GIN,
meta_DSF,
meta_208,
} meta_t;
@ -1003,6 +1005,7 @@ typedef struct {
size_t current_size_target; /* max data, until something happens */
size_t decode_to_discard; /* discard from this stream only (for EALayer3 or AWC) */
int channels_per_frame; /* for rare cases that streams don't share this */
} mpeg_custom_stream;
typedef struct {
@ -1015,7 +1018,7 @@ typedef struct {
mpg123_handle *m; /* MPEG decoder */
struct mpg123_frameinfo mi; /* start info, so it's available even when resetting */
/* for internal use, assumed to be constant for all frames */
/* for internal use */
int channels_per_frame;
int samples_per_frame;
/* for some calcs */