Merge pull request #869 from bnnm/mpc-aac

- Fix .mpc/mp+ total samples and encoder delay
- Fix .vxn encoder delay / gapless [Asphalt 9 (Android)]
- Fix EA SWVR .stream sample rate in some cases [Nascar Rumble (PS1)]
- Fix .wem with fully truncated PCM [Metal Gear Solid V (PC)]
- Fix some .aac encoder delay/sample issues
- Remove unneeded .hca subkeys (use .acb/awb)
This commit is contained in:
bnnm 2021-06-01 00:42:56 +02:00 committed by GitHub
commit 7cfa1f2960
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 4344 additions and 4267 deletions

View File

@ -570,6 +570,7 @@ STREAMFILE* ffmpeg_get_streamfile(ffmpeg_codec_data* data);
/* ffmpeg_decoder_utils.c (helper-things) */
ffmpeg_codec_data* init_ffmpeg_atrac3_raw(STREAMFILE* sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay);
ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* out_samples);
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size);
/* ffmpeg_decoder_custom_opus.c (helper-things) */
@ -655,6 +656,7 @@ size_t ac3_bytes_to_samples(size_t bytes, int full_block_align, int channels);
size_t aac_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes);
size_t mpeg_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes);
int32_t mpeg_get_samples_clean(STREAMFILE* sf, off_t start, size_t size, size_t* p_loop_start, size_t* p_loop_end, int is_vbr);
int mpc_get_samples(STREAMFILE* sf, off_t offset, int32_t* p_samples, int32_t* p_delay);
/* helper to pass a wrapped, clamped, fake extension-ed, SF to another meta */

View File

@ -1006,6 +1006,7 @@ size_t aac_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes) {
if (frame_size <= 0x08)
break;
//;VGM_LOG("AAC: %lx, %x\n", offset, frame_size);
frames++;
offset += frame_size;
}
@ -1013,6 +1014,82 @@ size_t aac_get_samples(STREAMFILE* sf, off_t start_offset, size_t bytes) {
return frames * samples_per_frame;
}
/* variable-sized var reader */
static int mpc_get_size(uint8_t* header, int header_size, int pos, int32_t* p_size) {
uint8_t tmp;
int32_t size = 0;
do {
if (pos >= header_size)
return pos;
tmp = header[pos];
size = (size << 7) | (tmp & 0x7F);
pos++;
}
while((tmp & 0x80));
*p_size = size;
return pos;
}
int mpc_get_samples(STREAMFILE* sf, off_t offset, int32_t* p_samples, int32_t* p_delay) {
uint8_t header[0x20];
int pos, size;
int32_t samples = 0, delay = 0;
if (read_streamfile(header, offset, sizeof(header), sf) != sizeof(header))
goto fail;;
if ((get_u32be(header) & 0xFFFFFF0F) == get_id32be("MP+\x07")) {
samples = get_u32le(header + 0x04) * 1152; /* total frames */
delay = 481; /* MPC_DECODER_SYNTH_DELAY */
samples -= delay;
/* in theory one header field can contain actual delay, not observed */
}
else if (get_u32be(header) == get_id32be("MPCK")) {
/* V8 header is made if mini chunks (16b type, 8b size including type+size):
* - SH: stream header
* - RG: replay gain
* - EI: encoder info
* - SO: seek?
* - ST: stream?
* - AP: audio part start */
if (get_u16be(header + 0x04) != 0x5348)
goto fail;
size = get_u8(header + 0x06);
if (0x04 + size > sizeof(header))
goto fail;
if (get_u8(header + 0x0b) != 0x08)
goto fail;
/* SH chunk: */
/* 0x00: CRC */
/* 0x04: header version (8) */
/* 0x05: samples (variable sized) */
/* 0xNN: "beginning silence" (variable sized) */
/* 0xNN: bitpacked channels/rate/etc */
pos = mpc_get_size(header, sizeof(header), 0x0C, &samples);
pos = mpc_get_size(header, sizeof(header), pos, &delay);
samples -= delay; /* original delay, not SYNTH_DELAY */
delay += 481; /* MPC_DECODER_SYNTH_DELAY */
/* SYNTH_DELAY seems to be forced, but official code isn't very clear (known samples set delay to 0 but need SYNTH DELAY) */
}
else {
goto fail;
}
if (p_samples) *p_samples = samples;
if (p_delay) *p_delay = delay;
return 1;
fail:
return 0;
}
/* ******************************************** */
/* CUSTOM STREAMFILES */
/* ******************************************** */

View File

@ -187,4 +187,24 @@ fail:
return NULL;
}
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size) {
ffmpeg_codec_data* data = NULL;
data = init_ffmpeg_offset(sf, offset, size);
if (!data) goto fail;
/* seeks to 0 eats first frame for whatever reason */
ffmpeg_set_force_seek(data);
/* raw AAC doesn't set this, while some decoders like FAAD remove 1024,
* but should be handled in container as each encoder uses its own value
* (Apple: 2112, FAAD: probably 1024, etc) */
//ffmpeg_set_skip_samples(data, 1024);
return data;
fail:
free_ffmpeg(data);
return NULL;
}
#endif

View File

@ -4,43 +4,46 @@
/* SWVR - from EA games, demuxed from .av/trk/mis/etc [Future Cop L.A.P.D. (PS/PC), Freekstyle (PS2/GC), EA Sports Supercross (PS)] */
VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) {
VGMSTREAM* init_vgmstream_ea_swvr(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count, sample_rate, big_endian;
int loop_flag = 0, channels, sample_rate, big_endian;
coding_t coding;
uint32_t block_id;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
int total_subsongs, target_subsong = streamFile->stream_index;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
/* .stream: common (found inside files)
* .str: shortened, probably unnecessary */
if (!check_extensions(streamFile,"stream,str"))
if (!check_extensions(sf,"stream,str"))
goto fail;
/* Files have no actual audio headers, so we inspect the first block for known values.
* Freekstyle uses multiblocks/subsongs (though some subsongs may be clones?) */
/* blocks ids are in machine endianness */
if (read_32bitBE(0x00,streamFile) == 0x52565753) { /* "RVWS" (PS1/PS2/PC) */
if (read_u32be(0x00,sf) == get_id32be("RVWS")) { /* PS1/PS2/PC */
big_endian = 0;
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
start_offset = read_32bit(0x04, streamFile);
start_offset = read_32bit(0x04, sf);
}
else if (read_32bitBE(0x00,streamFile) == 0x53575652) { /* "SWVR" (GC) */
else if (read_u32be(0x00,sf) == get_id32be("SWVR")) { /* GC */
big_endian = 1;
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
start_offset = read_32bit(0x04, streamFile);
start_offset = read_32bit(0x04, sf);
}
else if (read_32bitBE(0x00,streamFile) == 0x4D474156) { /* "MGAV", Freekstyle (PS2) raw movies */
else if (read_u32be(0x00,sf) == get_id32be("MGAV")) { /* Freekstyle (PS2) raw movies */
big_endian = 0;
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
start_offset = 0x00;
}
else if (read_32bitBE(0x00,streamFile) == 0x4453504D) { /* "DSPM", Freekstyle (GC) raw movies */
else if (read_u32be(0x00,sf) == get_id32be("DSPM")) { /* Freekstyle (GC) raw movies */
big_endian = 1;
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
@ -50,64 +53,81 @@ VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) {
goto fail;
}
if (read_32bit(start_offset+0x00, streamFile) == 0x50414444) /* "PADD" (Freekstyle) */
start_offset += read_32bit(start_offset+0x04, streamFile);
else if (read_32bit(start_offset+0x10, streamFile) == 0x53484452) /* "SHDR" (Future Cop PC) */
start_offset += read_32bit(start_offset+0x04, streamFile);
if (read_32bit(start_offset+0x00, sf) == get_id32be("PADD")) /* Freekstyle */
start_offset += read_32bit(start_offset+0x04, sf);
if (read_32bit(start_offset+0x00, streamFile) == 0x46494C4C) /* "FILL" (Freekstyle) */
start_offset += read_32bit(start_offset+0x04, streamFile);
if (read_32bit(start_offset+0x00, sf) == get_id32be("FILL")) /* Freekstyle */
start_offset += read_32bit(start_offset+0x04, sf);
total_subsongs = 1;
block_id = read_32bit(start_offset, streamFile);
block_id = read_32bit(start_offset, sf);
/* value after block id (usually at 0x38) is number of blocks of 0x6000 (results in file size, including FILLs) */
/* files are basically headerless so we inspect the first block
* Freekstyle uses multiblocks/subsongs (though some subsongs may be clones?) */
/* intended sample rate for PSX music (verified in emus) should be 14260, but is found in ELF as pitch value
* (ex. Nascar Rumble 0x052C in SLUS_010.68 at 0x000143BC): 0x052C * 44100 / 4096 ~= 14254.98046875hz
* Future Cop PSX pitch looks similar (comparing vs recordings). */
switch(block_id) {
case 0x5641474D: /* "VAGM" */
case 0x5641474D: /* "VAGM" (stereo music) */
coding = coding_PSX;
if (read_16bit(start_offset+0x1a, streamFile) == 0x0024) {
total_subsongs = read_32bit(start_offset+0x0c, streamFile)+1;
sample_rate = 22050;
if (read_16bit(start_offset+0x1a, sf) == 0x0024) {
total_subsongs = read_32bit(start_offset+0x0c, sf)+1;
sample_rate = 22050; /* Freekstyle (PS2) */
}
else {
sample_rate = 14008;
sample_rate = 1324 * 44100 / 4096; /* ~14254 [Future Cop (PS1), Nascar Rumble (PS1), EA Sports Motocross (PS1)] */
}
channel_count = 2;
channels = 2;
break;
case 0x56414742: /* "VAGB" */
case 0x56414742: /* "VAGB" (mono sfx/voices)*/
coding = coding_PSX;
if (read_16bit(start_offset+0x1a, streamFile) == 0x6400) {
sample_rate = 22050;
if (read_16bit(start_offset+0x1a, sf) == 0x6400) {
sample_rate = 22050; /* Freekstyle (PS2) */
}
else {
sample_rate = 14008;
/* approximate as pitches vary per file (ex. Nascar Rumble: engine=3779, heli=22050, commentary=11050) */
sample_rate = 1080 * 44100 / 4096; /* ~11627 [EA Sports Motocross (PS1)] */
}
channel_count = 1;
channels = 1;
break;
case 0x4453504D: /* "DSPM" */
case 0x4453504D: /* "DSPM" (stereo music) */
coding = coding_NGC_DSP;
total_subsongs = read_32bit(start_offset+0x0c, streamFile)+1;
sample_rate = 22050;
channel_count = 2;
total_subsongs = read_32bit(start_offset+0x0c, sf)+1;
sample_rate = 22050; /* Freekstyle (GC) */
channels = 2;
break;
case 0x44535042: /* "DSPB" */
case 0x44535042: /* "DSPB" (mono voices/sfx) */
coding = coding_NGC_DSP;
channel_count = 1;
sample_rate = 22050;
channels = 1;
sample_rate = 22050; /* Freekstyle (GC) */
break;
case 0x4D534943: /* "MSIC" */
case 0x4D534943: /* "MSIC" (stereo music) */
coding = coding_PCM8_U_int;
channel_count = 2;
sample_rate = 14008;
channels = 2;
sample_rate = 14291; /* assumed, by comparing vs PSX output [Future Cop (PC)] */
break;
case 0x53484F43: /* "SHOC" (a generic block but hopefully has PC sounds) */
if (read_32bit(start_offset+0x10, streamFile) == 0x53484F43) { /* SHDR */
coding = coding_PCM8_U_int; //todo there are other codecs
channel_count = 1;
sample_rate = 14008;
if (read_32bit(start_offset+0x10, sf) == get_id32be("SHDR")) { /* Future Cop (PC) */
/* there is a mini header? after SHDR
* 0x00: 5
* 0x04: "snds"
* 0x08: channels?
* 0x0c: data size without blocks/padding
* 0x10: null
* 0x14: null
* 0x18: null
* 0x1c: 1
* 0x20: 1
* 0x24: 0x4F430000 */
if (read_32bit(start_offset+0x18, sf) != get_id32be("snds"))
goto fail;
coding = coding_PCM8_U_int;
channels = 1;
sample_rate = 16000; /* assumed */
}
else {
//todo
/* The Lord of the Rings - The Return of the King (PC) uses IMA for sfx (in non-RVWS chunks)
* and some unknown codec for streams (mixed with strings and cutscene(?) commands) */
goto fail;
}
break;
@ -119,25 +139,25 @@ VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) {
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
loop_flag = 0;//(channel_count > 1); /* some Future Cop LAPD tracks repeat but other games have fadeouts */
loop_flag = 0;//(channels > 1); /* some Future Cop LAPD tracks repeat but other games have fadeouts */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_EA_SWVR;
vgmstream->sample_rate = sample_rate;
vgmstream->codec_endian = big_endian;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = get_streamfile_size(streamFile) / total_subsongs; /* approx... */
vgmstream->stream_size = get_streamfile_size(sf) / total_subsongs; /* approx... */
vgmstream->coding_type = coding;
vgmstream->layout_type = layout_blocked_ea_swvr;
/* DSP coefs are loaded per block */
/* some files (voices etc) decode with pops but seems a mastering problem */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
/* calc num_samples manually */
@ -155,7 +175,7 @@ VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) {
}
vgmstream->num_samples += num_samples;
}
while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
while (vgmstream->next_block_offset < get_streamfile_size(sf));
block_update(start_offset, vgmstream);
}

View File

@ -8,7 +8,7 @@ static int find_meta_loops(ffmpeg_codec_data* data, int32_t* p_loop_start, int32
/* parses any format supported by FFmpeg and not handled elsewhere:
* - MP3 (.mp3, .mus): Marc Ecko's Getting Up (PC)
* - MPC (.mpc): Moonshine Runners (PC), Asphalt 7 (PC)
* - MPC (.mpc, mp+): Moonshine Runners (PC), Asphalt 7 (PC)
* - FLAC (.flac): Warcraft 3 Reforged (PC), Call of Duty: Ghosts (PC)
* - DUCK (.wav): Sonic Jam (SAT), Virtua Fighter 2 (SAT)
* - ALAC/AAC (.caf): Chrono Trigger (iOS)
@ -24,7 +24,7 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
ffmpeg_codec_data* data = NULL;
int loop_flag = 0;
int32_t loop_start = 0, loop_end = 0, num_samples = 0;
int32_t loop_start = 0, loop_end = 0, num_samples = 0, encoder_delay = 0;
int total_subsongs, target_subsong = sf->stream_index;
/* no checks */
@ -66,6 +66,11 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
/* hack for AAC files (will return 0 samples if not an actual file) */
if (!num_samples && check_extensions(sf, "aac,laac")) {
num_samples = aac_get_samples(sf, 0x00, get_streamfile_size(sf));
if (num_samples > 0) {
/* FFmpeg seeks to 0 eats first frame for whatever reason */
ffmpeg_set_force_seek(data);
}
}
#ifdef VGM_USE_MPEG
@ -76,10 +81,17 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
}
#endif
/* hack for MPC, that seeks/resets incorrectly due to seek table shenanigans */
if (read_u32be(0x00, sf) == 0x4D502B07 || /* "MP+\7" (Musepack V7) */
read_u32be(0x00, sf) == 0x4D50434B) { /* "MPCK" (Musepack V8) */
/* hack for MPC */
if (is_id32be(0x00, sf, "MP+\x07") || /* Musepack V7 */
is_id32be(0x00, sf, "MP+\x17") || /* Musepack V7 with flag (seen in FFmpeg) */
is_id32be(0x00, sf, "MPCK")) { /* Musepack V8 */
/* FFmpeg seeks/resets incorrectly due to MPC seek table shenanigans */
ffmpeg_set_force_seek(data);
/* FFmpeg gets this wrong as usual (specially V8 samples) */
mpc_get_samples(sf, 0x00, &num_samples, &encoder_delay);
ffmpeg_set_skip_samples(data, encoder_delay);
}
/* default but often inaccurate when calculated using bitrate (wrong for VBR) */
@ -111,7 +123,6 @@ fail:
vgmstream->codec_data = NULL;
close_vgmstream(vgmstream);
}
return NULL;
}

View File

@ -11,7 +11,7 @@ typedef struct {
/**
* List of known keys, extracted from the game files (mostly found in 2ch.net).
* List of known keys, extracted from the game files (several found in 2ch.net, others from data analisys).
* CRI's tools expect an unsigned 64 bit number string, but keys are commonly found online in hex form.
* Keys only use 56 bits though, so the upper 8 bits can be ignored.
*
@ -401,6 +401,9 @@ static const hcakey_info hcakey_list[] = {
/* Mushoku Tensei: Game ni Nattemo Honki Dasu (Android) */
{12281329554827291428u}, // AA700C292CFCAB24
/* Dragalia Lost (iOS/Android) */
{2967411924141}, // 000002B2E7889CAD
/* D4DJ Groovy Mix (Android) [base files] */
{393410674916959300}, // 0575ACECA945A444
/* D4DJ Groovy Mix (Android) [music_* files, per-song later mixed with subkey] */
@ -627,9 +630,6 @@ static const hcakey_info hcakey_list[] = {
{0xb96786621e27daf3},
{0x1111d6c10e509824},
/* Dragalia Lost (iOS/Android) */
{2967411924141, subkeys_dgl, sizeof(subkeys_dgl) / sizeof(subkeys_dgl[0]) }, // 000002B2E7889CAD
};
#endif/*_HCA_KEYS_H_*/

View File

@ -3,87 +3,6 @@
/* AWB subkey tables */
static const uint16_t subkeys_dgl[] = { /* Dragalia Lost (Cygames) [iOS/Android] */
0x0152,0x0165,0x0192,0x01A1,0x020C,0x0234,0x0240,0x024F,0x026B,0x026F,0x02B8,0x0348,0x037D,0x03C9,0x03DA,0x0440,
0x0468,0x0480,0x0526,0x0552,0x055E,0x058C,0x0597,0x05DC,0x05F6,0x05FE,0x0606,0x064D,0x0661,0x0687,0x06CC,0x0752,
0x07A1,0x07B9,0x07CD,0x07F7,0x0823,0x08A5,0x08D8,0x08E1,0x08EF,0x09AC,0x09D7,0x0A9A,0x0AA8,0x0B0C,0x0B51,0x0BBA,
0x0BBE,0x0C9A,0x0D71,0x0D7B,0x0DCF,0x0DD4,0x0DF7,0x0E1C,0x0E1F,0x0E4F,0x0E6A,0x0E9D,0x0EAF,0x0F2B,0x0F85,0x0FDA,
0x1011,0x102F,0x103A,0x1041,0x1074,0x107E,0x10BF,0x10C7,0x10E5,0x1102,0x1107,0x112F,0x113A,0x116A,0x116F,0x1182,
0x11A6,0x11FA,0x1220,0x126A,0x1280,0x12B8,0x12D7,0x130E,0x1335,0x135B,0x13C0,0x13C6,0x13EC,0x142C,0x1469,0x1474,
0x14E4,0x1518,0x1536,0x1538,0x1585,0x15AD,0x15CB,0x15E1,0x16F3,0x1706,0x1748,0x1756,0x178C,0x179A,0x17F4,0x1802,
0x184F,0x1892,0x1903,0x1944,0x198E,0x19A1,0x19F3,0x1A0C,0x1A5B,0x1A89,0x1AAC,0x1AC7,0x1B11,0x1B92,0x1C31,0x1C7C,
0x1C7E,0x1D01,0x1D0C,0x1D5A,0x1DAE,0x1DC1,0x1DCF,0x1E3B,0x1E64,0x1E72,0x1E88,0x1F90,0x1FAE,0x1FC2,0x208C,0x20E9,
0x2106,0x2117,0x2122,0x2160,0x2161,0x216E,0x21BE,0x21FE,0x2277,0x22D9,0x22FA,0x230C,0x23C9,0x23D8,0x2402,0x2415,
0x243C,0x245A,0x24AD,0x2600,0x2632,0x266E,0x2692,0x269B,0x26D4,0x26FC,0x2701,0x2723,0x274D,0x2777,0x27C2,0x27E7,
0x27EE,0x2865,0x2882,0x28B2,0x28B6,0x2973,0x29B0,0x29B1,0x2A04,0x2A33,0x2A55,0x2ADB,0x2AE7,0x2B48,0x2B7D,0x2BAA,
0x2C09,0x2C2E,0x2C5C,0x2C77,0x2D08,0x2D1F,0x2D9C,0x2DAE,0x2DB0,0x2DB7,0x2DE5,0x2DF5,0x2E6E,0x2E75,0x2E9E,0x2EB6,
0x2EBF,0x2ED8,0x2EE7,0x2F54,0x2F66,0x2F72,0x2F83,0x2FCB,0x3046,0x30BB,0x30BE,0x30CA,0x30E6,0x312C,0x3160,0x3180,
0x3184,0x31C7,0x31ED,0x31F8,0x3218,0x324D,0x32A9,0x32E8,0x32E9,0x32F9,0x3319,0x331C,0x333F,0x334E,0x336C,0x3373,
0x338B,0x33AE,0x33BE,0x33FB,0x3459,0x3486,0x34A5,0x34A8,0x34C3,0x34C6,0x34EB,0x3527,0x355A,0x357D,0x35DC,0x35F1,
0x3619,0x362A,0x3645,0x365C,0x36AA,0x36BC,0x3738,0x3745,0x3749,0x3752,0x3791,0x37C3,0x37DE,0x3804,0x380A,0x380C,
0x3818,0x381F,0x3920,0x3946,0x3952,0x395C,0x3999,0x39D0,0x39DB,0x3AB7,0x3B79,0x3BBD,0x3BCE,0x3C7B,0x3CA3,0x3D2C,
0x3D50,0x3DA7,0x3DBC,0x3DEF,0x3E7B,0x3E89,0x3EB2,0x3ED0,0x3EF2,0x3F18,0x3F42,0x3F79,0x4004,0x4069,0x406A,0x40BF,
0x40DE,0x410B,0x410F,0x413E,0x414F,0x416B,0x41A3,0x41B3,0x41BC,0x41E3,0x426E,0x4284,0x42EA,0x42EB,0x434A,0x43D3,
0x43E6,0x43E9,0x4411,0x444F,0x4457,0x449E,0x44B9,0x4541,0x458B,0x463E,0x4751,0x4768,0x476E,0x477D,0x4793,0x47B2,
0x47D1,0x47DF,0x4840,0x487A,0x4894,0x48C5,0x48D7,0x49B4,0x49E3,0x4A52,0x4B03,0x4B0E,0x4B21,0x4B52,0x4B70,0x4B8D,
0x4B94,0x4BA7,0x4BF2,0x4C14,0x4C49,0x4C52,0x4C72,0x4CBF,0x4D1F,0x4D35,0x4D44,0x4D86,0x4D9F,0x4DDC,0x4DF5,0x4E29,
0x4E40,0x4E48,0x4E5A,0x4E7C,0x4E93,0x4EE3,0x4EE5,0x4F26,0x4F36,0x4F60,0x4F6C,0x4F92,0x4FAB,0x4FBB,0x4FE5,0x4FF2,
0x5137,0x514C,0x51A9,0x51B3,0x51F8,0x5220,0x5406,0x543B,0x5487,0x5493,0x5496,0x54B1,0x54CE,0x552C,0x558B,0x559B,
0x55F4,0x561F,0x5639,0x567C,0x56A1,0x56EE,0x5757,0x577B,0x5794,0x581E,0x582E,0x5846,0x586A,0x58B1,0x58C3,0x58C9,
0x596A,0x59A5,0x59CD,0x59EF,0x59F7,0x5A3C,0x5A81,0x5A86,0x5ABB,0x5AE5,0x5B0B,0x5B19,0x5B1C,0x5B49,0x5B5C,0x5B90,
0x5BC1,0x5BC2,0x5BCF,0x5BD8,0x5BFE,0x5C38,0x5C75,0x5C83,0x5C9C,0x5CFC,0x5D4D,0x5D54,0x5D61,0x5D70,0x5DE0,0x5DEF,
0x5DFA,0x5E30,0x5E47,0x5E57,0x5E63,0x5E74,0x5EB0,0x5EB3,0x5ED5,0x5F1B,0x5F5C,0x5F8F,0x5F9D,0x5FAF,0x5FD1,0x601F,
0x6054,0x6062,0x6071,0x6073,0x60AA,0x60CE,0x6104,0x6124,0x6149,0x617F,0x6188,0x618B,0x6191,0x61B2,0x61EB,0x61F3,
0x621C,0x6226,0x623A,0x627D,0x627F,0x62F9,0x6319,0x6364,0x63DE,0x63F3,0x63FD,0x6452,0x645F,0x64A5,0x64AE,0x64D3,
0x64E6,0x651A,0x6574,0x659D,0x65D3,0x65D4,0x65F2,0x6631,0x66F1,0x6739,0x68E0,0x6914,0x6955,0x697B,0x6990,0x6993,
0x6A01,0x6A45,0x6A52,0x6A64,0x6A85,0x6AFA,0x6B08,0x6B16,0x6B75,0x6B79,0x6BF6,0x6BF8,0x6C2F,0x6C3C,0x6CA5,0x6CBD,
0x6CD6,0x6CE3,0x6CF9,0x6CFA,0x6D0E,0x6D16,0x6D1E,0x6D3E,0x6D6F,0x6D80,0x6D8B,0x6DCF,0x6DFD,0x6E73,0x6EC5,0x6ECF,
0x6F14,0x6F6F,0x6FD0,0x7033,0x704C,0x7098,0x7106,0x71A3,0x721B,0x7235,0x7242,0x7278,0x72B7,0x7319,0x7359,0x73B9,
0x73F5,0x7427,0x742F,0x7432,0x7452,0x745F,0x747F,0x7484,0x749D,0x74C8,0x74D7,0x74D8,0x74FB,0x74FE,0x756A,0x7575,
0x7576,0x7588,0x75A9,0x75DE,0x7604,0x7640,0x764D,0x773C,0x7742,0x7751,0x7766,0x77C3,0x77D7,0x77E6,0x782E,0x7860,
0x786B,0x7895,0x78B0,0x78F1,0x78F3,0x7976,0x797F,0x798A,0x798F,0x79AB,0x79E7,0x79F9,0x7A1D,0x7A24,0x7A47,0x7A6B,
0x7AB5,0x7AE2,0x7B64,0x7B68,0x7BBC,0x7C2E,0x7C77,0x7C7D,0x7C8A,0x7CBA,0x7D0D,0x7D12,0x7D2C,0x7E0E,0x7E4B,0x7E66,
0x7E9D,0x7EB5,0x7EBA,0x7EC5,0x7F10,0x7F17,0x7F1B,0x7F26,0x7F5F,0x7FB8,0x7FC1,0x7FCE,0x7FFC,0x8075,0x80A2,0x80A5,
0x80B2,0x80CB,0x80E7,0x80FF,0x8116,0x8126,0x8183,0x81C8,0x8205,0x826C,0x8274,0x82B5,0x82FD,0x830D,0x8330,0x833C,
0x8346,0x8349,0x8412,0x8413,0x8458,0x8467,0x8486,0x849D,0x8533,0x8540,0x8577,0x8586,0x858E,0x85AD,0x85FF,0x862D,
0x863D,0x863E,0x8658,0x86E3,0x86E6,0x86E9,0x8739,0x873C,0x878E,0x8797,0x879F,0x87EB,0x87FD,0x8801,0x8812,0x8828,
0x885E,0x88C3,0x890D,0x891F,0x899E,0x89BA,0x89D9,0x8A0F,0x8A7E,0x8A87,0x8AC1,0x8B1F,0x8B25,0x8B33,0x8B4D,0x8B76,
0x8B80,0x8BFF,0x8C38,0x8C4A,0x8CF2,0x8D46,0x8D86,0x8D8B,0x8DAE,0x8DEF,0x8E10,0x8E44,0x8E79,0x8EAB,0x8F01,0x8F29,
0x8F7C,0x8FCF,0x8FF1,0x9000,0x9029,0x9082,0x9130,0x9166,0x91D6,0x924A,0x9277,0x92F8,0x9342,0x9375,0x940C,0x942A,
0x9496,0x94B9,0x94D3,0x9512,0x9521,0x953A,0x9551,0x9580,0x95ED,0x9625,0x962D,0x9630,0x963A,0x9664,0x96D2,0x96EF,
0x971B,0x97D1,0x97FC,0x9810,0x981A,0x9825,0x9828,0x9861,0x98E3,0x98FB,0x990E,0x9970,0x998A,0x999E,0x99A2,0x99DA,
0x99F8,0x9A37,0x9A6F,0x9A8A,0x9AFE,0x9B06,0x9B36,0x9B54,0x9B67,0x9B81,0x9B91,0x9CA4,0x9CBC,0x9CC5,0x9D17,0x9D41,
0x9D99,0x9DBF,0x9DEA,0x9E16,0x9E1D,0x9E5A,0x9EAC,0x9F39,0x9FA3,0x9FED,0x9FF2,0xA020,0xA03C,0xA081,0xA0A3,0xA0AA,
0xA145,0xA1C6,0xA221,0xA27A,0xA2FB,0xA3AB,0xA3C2,0xA3CF,0xA457,0xA458,0xA49E,0xA4E1,0xA548,0xA553,0xA585,0xA597,
0xA5EA,0xA655,0xA6A7,0xA6D9,0xA6F6,0xA71C,0xA723,0xA75F,0xA77E,0xA7D6,0xA88B,0xA894,0xA8BF,0xA8C8,0xA8E0,0xA90A,
0xA933,0xA988,0xA9B4,0xAA21,0xAA3A,0xAA57,0xAA5E,0xAADF,0xAAF4,0xAB0B,0xAB52,0xAB8F,0xABC3,0xABD3,0xABF3,0xAC0C,
0xAC23,0xAC55,0xACCF,0xACD5,0xACDF,0xAD00,0xAD12,0xADC4,0xADF1,0xAE02,0xAE16,0xAE45,0xAE6A,0xAE9A,0xAEA7,0xAEB6,
0xAFFA,0xB015,0xB040,0xB05B,0xB073,0xB099,0xB10A,0xB122,0xB13C,0xB14B,0xB155,0xB160,0xB175,0xB177,0xB221,0xB238,
0xB25D,0xB262,0xB271,0xB30B,0xB332,0xB378,0xB3FF,0xB400,0xB437,0xB473,0xB4A9,0xB4DD,0xB4F1,0xB52E,0xB54B,0xB556,
0xB57D,0xB592,0xB59C,0xB5AD,0xB5CE,0xB5D3,0xB5D5,0xB603,0xB613,0xB65D,0xB75E,0xB761,0xB79F,0xB7A0,0xB7BC,0xB7C3,
0xB7F8,0xB893,0xB89D,0xB8F5,0xB907,0xB989,0xB9B8,0xBAE5,0xBB0D,0xBB0F,0xBBA3,0xBBBC,0xBBD3,0xBBE4,0xBC3D,0xBC78,
0xBC98,0xBCCC,0xBD2C,0xBD5D,0xBD67,0xBDBF,0xBE10,0xBE21,0xBE57,0xBEA2,0xBEBF,0xBF21,0xBF22,0xBF3F,0xBF64,0xBF8B,
0xC01B,0xC022,0xC036,0xC041,0xC04D,0xC055,0xC075,0xC095,0xC0B4,0xC0DC,0xC0E4,0xC133,0xC13F,0xC156,0xC1DB,0xC2EA,
0xC303,0xC350,0xC352,0xC36C,0xC385,0xC394,0xC3C9,0xC3D8,0xC3DB,0xC434,0xC452,0xC4AD,0xC592,0xC5CB,0xC5E0,0xC5EB,
0xC5F2,0xC625,0xC62D,0xC655,0xC67B,0xC68E,0xC6B3,0xC6D9,0xC709,0xC728,0xC78E,0xC7A4,0xC838,0xC873,0xC887,0xC8A1,
0xC8A8,0xC8E6,0xC8F6,0xC952,0xC98B,0xC9AD,0xCA13,0xCA4D,0xCA99,0xCAB9,0xCAF6,0xCB1B,0xCBC1,0xCBE6,0xCBEA,0xCC3F,
0xCC77,0xCD13,0xCDAC,0xCDC5,0xCDF7,0xCE16,0xCE32,0xCE3B,0xCEB8,0xCF0F,0xCF80,0xCFF7,0xD062,0xD075,0xD0B2,0xD0D5,
0xD159,0xD163,0xD19D,0xD1DD,0xD1E2,0xD1E9,0xD203,0xD23D,0xD2AB,0xD2B1,0xD2E0,0xD305,0xD410,0xD416,0xD422,0xD446,
0xD47B,0xD47F,0xD493,0xD49E,0xD591,0xD59C,0xD5A0,0xD70A,0xD710,0xD718,0xD771,0xD815,0xD876,0xD91D,0xD921,0xD96B,
0xD99C,0xDA29,0xDA77,0xDAA7,0xDAFF,0xDB38,0xDBA0,0xDC31,0xDC33,0xDC5A,0xDC8F,0xDCFA,0xDD0B,0xDD3D,0xDD55,0xDE02,
0xDE30,0xDE57,0xDE8A,0xDED3,0xDED7,0xDF38,0xDF9A,0xE02E,0xE073,0xE0E3,0xE114,0xE125,0xE15E,0xE164,0xE195,0xE1A6,
0xE1C5,0xE1CD,0xE1D5,0xE1D6,0xE1F1,0xE222,0xE22C,0xE25F,0xE288,0xE297,0xE3A0,0xE3AE,0xE3D3,0xE405,0xE434,0xE437,
0xE49D,0xE4AC,0xE4BE,0xE50E,0xE51F,0xE52F,0xE53B,0xE597,0xE5A9,0xE5C3,0xE5E3,0xE5F1,0xE652,0xE659,0xE6AA,0xE6D7,
0xE6DF,0xE6EE,0xE76D,0xE775,0xE795,0xE7A2,0xE7B5,0xE7CE,0xE840,0xE8DD,0xE8EB,0xE930,0xE944,0xE947,0xE99F,0xEA1C,
0xEACB,0xEBBA,0xEC15,0xEC1B,0xEC36,0xEC56,0xED0A,0xED17,0xED24,0xED5A,0xED87,0xED93,0xED95,0xED99,0xEDC2,0xEDEB,
0xEE1F,0xEEC6,0xEF04,0xEF63,0xEF7F,0xEFA6,0xEFAF,0xEFB5,0xEFB6,0xEFCC,0xEFD1,0xEFD8,0xF00A,0xF049,0xF055,0xF0C7,
0xF107,0xF108,0xF132,0xF144,0xF16D,0xF1E7,0xF202,0xF221,0xF24B,0xF2E3,0xF2F6,0xF32A,0xF3FE,0xF412,0xF41F,0xF429,
0xF4F7,0xF52B,0xF558,0xF585,0xF5C8,0xF66E,0xF675,0xF685,0xF6A3,0xF6D7,0xF78A,0xF7A6,0xF7D7,0xF7DC,0xF7ED,0xF82D,
0xF82E,0xF84C,0xF89E,0xF8B2,0xF982,0xF9A9,0xF9C9,0xFA0B,0xFA6B,0xFAAA,0xFB77,0xFBD0,0xFCAF,0xFCB8,0xFCCA,0xFD01,
0xFD0B,0xFD13,0xFD38,0xFD57,0xFD5D,0xFD68,0xFD6D,0xFD86,0xFDDB,0xFDDC,0xFE07,0xFE33,0xFEA6,0xFF43,0xFF48,0xFF65,
0xFF85,0xFF8B,0xFF8C,0xFF9A,0xFFD0
};
#if 0
static const uint16_t subkeys_all[] = { /* all values for testing purposes (slow) */
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,

View File

@ -42,15 +42,16 @@ VGMSTREAM* init_vgmstream_naac(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
{
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, data_size);
vgmstream->codec_data = init_ffmpeg_aac(sf, start_offset, data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* observed default, some files start without silence though seems correct when loop_start=0 */
ffmpeg_set_skip_samples(vgmstream->codec_data, 1024); /* raw AAC doesn't set this */
vgmstream->num_samples -= 1024; /* may end with 1024 of silence? */
vgmstream->num_samples -= 1024;
vgmstream->loop_end_sample -= 1024;
/* for some reason last frame is ignored/bugged in various decoders (gives EOF errors) */
}
#else
goto fail;

View File

@ -42,14 +42,14 @@ VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG
{
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, data_size);
vgmstream->codec_data = init_ffmpeg_aac(sf, start_offset, data_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* apparently none, or maybe ~600 */
//ffmpeg_set_skip_samples(ffmpeg_data, 1024);
//vgmstream->num_samples -= 1024;
/* assumed, maybe a bit more */
ffmpeg_set_skip_samples(vgmstream->codec_data, 1024);
vgmstream->num_samples -= 1024;
}
#else
goto fail;

View File

@ -468,14 +468,18 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
case coding_FFmpeg: {
ffmpeg_codec_data *ffmpeg_data = NULL;
if (txth.codec == FFMPEG || txth.codec == AC3 || txth.codec == AAC) {
if (txth.codec == FFMPEG || txth.codec == AC3) {
/* default FFmpeg */
ffmpeg_data = init_ffmpeg_offset(txth.sf_body, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail;
ffmpeg_data = init_ffmpeg_offset(txth.sf_body, txth.start_offset, txth.data_size);
if (!ffmpeg_data) goto fail;
if (vgmstream->num_samples == 0)
vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */
}
else if (txth.codec == AAC) {
ffmpeg_data = init_ffmpeg_aac(txth.sf_body, txth.start_offset, txth.data_size);
if (!ffmpeg_data) goto fail;
}
else {
/* fake header FFmpeg */
uint8_t buf[0x100];

View File

@ -1,10 +1,11 @@
#include "meta.h"
#include "../coding/coding.h"
/* VXN - from Gameloft mobile games */
VGMSTREAM* init_vgmstream_vxn(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
int loop_flag = 0, channel_count, codec, sample_rate, block_align, bits, num_samples;
int loop_flag = 0, channels, codec, sample_rate, block_align, bits, num_samples, encoder_delay;
off_t start_offset, stream_offset, chunk_offset, first_offset = 0x00;
size_t stream_size;
int total_subsongs, target_subsong = sf->stream_index;
@ -13,22 +14,32 @@ VGMSTREAM* init_vgmstream_vxn(STREAMFILE* sf) {
if (!check_extensions(sf,"vxn"))
goto fail;
if (read_u32be(0x00,sf) != 0x566F784E) /* "VoxN" */
if (!is_id32be(0x00,sf, "VoxN"))
goto fail;
/* 0x04: chunk size */
/* 0x08: ASCII version? ("0.0.1") */
if (read_u32le(0x10,sf) != get_streamfile_size(sf))
goto fail;
/* 0x14: first MPC data start */
/* header is RIFF-like with many custom chunks */
if (!find_chunk_le(sf, 0x41666D74,first_offset,0, &chunk_offset,NULL)) /* "Afmt" */
goto fail;
codec = read_u16le(chunk_offset+0x00, sf);
channel_count = read_u16le(chunk_offset+0x02, sf);
channels = read_u16le(chunk_offset+0x02, sf);
sample_rate = read_u32le(chunk_offset+0x04, sf);
block_align = read_u16le(chunk_offset+0x08, sf);
bits = read_16bitLE(chunk_offset+0x0a, sf);
bits = read_s16le(chunk_offset+0x0a, sf);
/* files are divided into segment subsongs, often a leadout and loop in that order
* (the "Plst" and "Rule" chunks may have order info) */
/* files are divided into segment subsongs, often a leadout and loop in that order,
* but may also have +15 [Asphalt 9]. Various chunks seem to define how they are used:
* - Rule: optional, not related to number of playlists
* - Plst: sets N playlists + some flags?
* - Stat: N entries (1 per playlist), start? + name (null-terminated, size 0x0C) + sample values?
* - Trsn: optional, transitions for playlists?
* - Grps: N entries (1 per playlist), 0x18 per entry, unknown
* - Gprs: playlist segments, 0x20 per entry, playlist id + segment + null + segment? + flags (0/1/-1)
*/
if (!find_chunk_le(sf, 0x5365676D,first_offset,0, &chunk_offset,NULL)) /* "Segm" */
goto fail;
total_subsongs = read_u32le(chunk_offset+0x00, sf);
@ -45,7 +56,7 @@ VGMSTREAM* init_vgmstream_vxn(STREAMFILE* sf) {
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
@ -85,16 +96,24 @@ VGMSTREAM* init_vgmstream_vxn(STREAMFILE* sf) {
break;
#ifdef VGM_USE_FFMPEG
case 0x0800: /* Musepack (ex. Asphalt Xtreme) */
case 0x0800: /* Musepack (ex. Asphalt Xtreme, Asphalt 9) */
if (bits != -1) goto fail;
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset,stream_size);
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* unlike standard .mpc, .vxn has no seek table so no need to fix */
//ffmpeg_set_force_seek(vgmstream->codec_data);
encoder_delay = 0;
mpc_get_samples(sf, start_offset, NULL, &encoder_delay);
/* num_samples matches MPC samples */
/* FFmpeg doesn't set encoder delay */
ffmpeg_set_skip_samples(vgmstream->codec_data, encoder_delay);
break;
#endif

View File

@ -109,6 +109,10 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) {
}
vgmstream->num_samples = pcm_bytes_to_samples(ww.data_size, ww.channels, ww.bits_per_sample);
/* truncated .bnk RIFFs that only have header and no data is possible [Metal Gear Solid V (PC)] */
if (ww.truncated && !vgmstream->num_samples)
vgmstream->num_samples = 1; /* force something to avoid broken subsongs */
break;
case IMA: /* common */