Updated VGMStream to r1745-22-gf696beb0
Signed-off-by: Christopher Snowhill <kode54@gmail.com>swiftingly
parent
bea896cca5
commit
94057cf467
|
@ -434,7 +434,7 @@
|
|||
836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; };
|
||||
836F703518BDC2190095E648 /* svs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF918BDC2190095E648 /* svs.c */; };
|
||||
836F703618BDC2190095E648 /* thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFA18BDC2190095E648 /* thp.c */; };
|
||||
836F703718BDC2190095E648 /* tun.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFB18BDC2190095E648 /* tun.c */; };
|
||||
836F703718BDC2190095E648 /* alp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFB18BDC2190095E648 /* alp.c */; };
|
||||
836F703818BDC2190095E648 /* ubi_ckd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFC18BDC2190095E648 /* ubi_ckd.c */; };
|
||||
836F703918BDC2190095E648 /* vgs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFD18BDC2190095E648 /* vgs.c */; };
|
||||
836F703A18BDC2190095E648 /* vs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFE18BDC2190095E648 /* vs.c */; };
|
||||
|
@ -610,6 +610,7 @@
|
|||
83AFABBE23795202002F3947 /* isb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83AFABBB23795202002F3947 /* isb.c */; };
|
||||
83B46FD12707FB2100847FC9 /* at3plus_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B46FCD2707FB2100847FC9 /* at3plus_decoder.h */; };
|
||||
83B46FD52707FB9A00847FC9 /* endianness.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B46FD42707FB9A00847FC9 /* endianness.h */; };
|
||||
83B69B222845A26600D2435A /* bw_mp3_riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 83B69B212845A26600D2435A /* bw_mp3_riff.c */; };
|
||||
83B72E3A27904589006007A3 /* libfdk-aac.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83B72E342790452C006007A3 /* libfdk-aac.2.dylib */; };
|
||||
83BAFB6C19F45EB3005DAB60 /* bfstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BAFB6B19F45EB3005DAB60 /* bfstm.c */; };
|
||||
83C7280F22BC893D00678B4A /* xwb_xsb.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C727FB22BC893800678B4A /* xwb_xsb.h */; };
|
||||
|
@ -1231,7 +1232,7 @@
|
|||
836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = "<group>"; };
|
||||
836F6EF918BDC2190095E648 /* svs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = svs.c; sourceTree = "<group>"; };
|
||||
836F6EFA18BDC2190095E648 /* thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp.c; sourceTree = "<group>"; };
|
||||
836F6EFB18BDC2190095E648 /* tun.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tun.c; sourceTree = "<group>"; };
|
||||
836F6EFB18BDC2190095E648 /* alp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alp.c; sourceTree = "<group>"; };
|
||||
836F6EFC18BDC2190095E648 /* ubi_ckd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_ckd.c; sourceTree = "<group>"; };
|
||||
836F6EFD18BDC2190095E648 /* vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vgs.c; sourceTree = "<group>"; };
|
||||
836F6EFE18BDC2190095E648 /* vs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vs.c; sourceTree = "<group>"; };
|
||||
|
@ -1406,6 +1407,7 @@
|
|||
83AFABBB23795202002F3947 /* isb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = isb.c; sourceTree = "<group>"; };
|
||||
83B46FCD2707FB2100847FC9 /* at3plus_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = at3plus_decoder.h; sourceTree = "<group>"; };
|
||||
83B46FD42707FB9A00847FC9 /* endianness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = endianness.h; sourceTree = "<group>"; };
|
||||
83B69B212845A26600D2435A /* bw_mp3_riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bw_mp3_riff.c; sourceTree = "<group>"; };
|
||||
83B72E342790452C006007A3 /* libfdk-aac.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libfdk-aac.2.dylib"; path = "../../ThirdParty/fdk-aac/lib/libfdk-aac.2.dylib"; sourceTree = "<group>"; };
|
||||
83BAFB6B19F45EB3005DAB60 /* bfstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfstm.c; sourceTree = "<group>"; };
|
||||
83C727FB22BC893800678B4A /* xwb_xsb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xwb_xsb.h; sourceTree = "<group>"; };
|
||||
|
@ -1836,6 +1838,7 @@
|
|||
8349A8F61FE6257E00E26435 /* aix_streamfile.h */,
|
||||
836F6E3218BDC2180095E648 /* aix.c */,
|
||||
836F6E3318BDC2180095E648 /* akb.c */,
|
||||
836F6EFB18BDC2190095E648 /* alp.c */,
|
||||
834FE0C0215C79E5000A5D3D /* ao.c */,
|
||||
834FE0C7215C79E7000A5D3D /* apc.c */,
|
||||
836F6E3418BDC2180095E648 /* apple_caff.c */,
|
||||
|
@ -1867,6 +1870,7 @@
|
|||
836F6E3A18BDC2180095E648 /* brstm.c */,
|
||||
83AA7F762519C042004C5298 /* bsf.c */,
|
||||
83EDE5D71A70951A005F5D84 /* btsnd.c */,
|
||||
83B69B212845A26600D2435A /* bw_mp3_riff.c */,
|
||||
835C883122CC17BD001B4B3F /* bwav.c */,
|
||||
8306B0CF2098458F000302D4 /* caf.c */,
|
||||
836F6E3B18BDC2180095E648 /* capdsp.c */,
|
||||
|
@ -2179,7 +2183,6 @@
|
|||
8373342E23F60D4100DE14DC /* tgc.c */,
|
||||
836F6EFA18BDC2190095E648 /* thp.c */,
|
||||
836F46AF2820874D005B9B87 /* tt_ad.c */,
|
||||
836F6EFB18BDC2190095E648 /* tun.c */,
|
||||
83C7280122BC893A00678B4A /* txth_streamfile.h */,
|
||||
830165971F256BD000CA0941 /* txth.c */,
|
||||
8306B0D22098458F000302D4 /* txtp.c */,
|
||||
|
@ -2970,7 +2973,7 @@
|
|||
836F703318BDC2190095E648 /* str_snds.c in Sources */,
|
||||
832BF82221E0514B006F50F1 /* vs_str.c in Sources */,
|
||||
8349A9191FE6258200E26435 /* afc.c in Sources */,
|
||||
836F703718BDC2190095E648 /* tun.c in Sources */,
|
||||
836F703718BDC2190095E648 /* alp.c in Sources */,
|
||||
83031ECD243C50CC00C3F3E0 /* blocked_vid1.c in Sources */,
|
||||
836F700B18BDC2190095E648 /* ps2_wad.c in Sources */,
|
||||
8349A9161FE6258200E26435 /* flx.c in Sources */,
|
||||
|
@ -3066,6 +3069,7 @@
|
|||
836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */,
|
||||
836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */,
|
||||
83C7282122BC893D00678B4A /* msf_konami.c in Sources */,
|
||||
83B69B222845A26600D2435A /* bw_mp3_riff.c in Sources */,
|
||||
8315958920FEC83F007002F0 /* asf.c in Sources */,
|
||||
83C7281222BC893D00678B4A /* 9tav.c in Sources */,
|
||||
836F6F3818BDC2190095E648 /* psx_decoder.c in Sources */,
|
||||
|
|
|
@ -21,7 +21,7 @@ void decode_3ds_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspaci
|
|||
void decode_snds_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_otns_ima(VGMSTREAM* vgmstream, VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_wv6_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_alp_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_hv_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_ffta2_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_blitz_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_mtf_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo);
|
||||
|
|
|
@ -190,8 +190,8 @@ static void wv6_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset,
|
|||
if (*step_index > 88) *step_index=88;
|
||||
}
|
||||
|
||||
/* Lego Racers (PC) .TUN variation, reverse engineered from the .exe */
|
||||
static void alp_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
/* High Voltage variation, reverse engineered from .exes [Lego Racers (PC), NBA Hangtime (PC)] */
|
||||
static void hv_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
|
||||
int sample_nibble, sample_decoded, step, delta;
|
||||
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
|
@ -489,8 +489,8 @@ void decode_wv6_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspa
|
|||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
/* ALT IMA, DVI IMA with custom nibble expand */
|
||||
void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
/* High Voltage's DVI IMA with simplified nibble expand */
|
||||
void decode_hv_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
@ -503,7 +503,7 @@ void decode_alp_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspa
|
|||
off_t byte_offset = stream->offset + i/2;
|
||||
int nibble_shift = (i&1?0:4); //high nibble first
|
||||
|
||||
alp_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
hv_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
}
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
|
|||
case coding_DVI_IMA_int:
|
||||
case coding_3DS_IMA:
|
||||
case coding_WV6_IMA:
|
||||
case coding_ALP_IMA:
|
||||
case coding_HV_IMA:
|
||||
case coding_FFTA2_IMA:
|
||||
case coding_BLITZ_IMA:
|
||||
case coding_PCFX:
|
||||
|
@ -622,7 +622,7 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
|
|||
case coding_DVI_IMA_int:
|
||||
case coding_3DS_IMA:
|
||||
case coding_WV6_IMA:
|
||||
case coding_ALP_IMA:
|
||||
case coding_HV_IMA:
|
||||
case coding_FFTA2_IMA:
|
||||
case coding_BLITZ_IMA:
|
||||
case coding_PCFX:
|
||||
|
@ -1163,9 +1163,9 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
|
|||
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
|
||||
}
|
||||
break;
|
||||
case coding_ALP_IMA:
|
||||
case coding_HV_IMA:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
decode_alp_ima(&vgmstream->ch[ch], buffer+ch,
|
||||
decode_hv_ima(&vgmstream->ch[ch], buffer+ch,
|
||||
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -79,6 +79,7 @@ static const char* extension_list[] = {
|
|||
"atsl",
|
||||
"atsl3",
|
||||
"atsl4",
|
||||
"atslx",
|
||||
"atx",
|
||||
"aud",
|
||||
"audio", //txth/reserved [Grimm Echoes (Android)]
|
||||
|
@ -118,6 +119,8 @@ static const char* extension_list[] = {
|
|||
"bo2",
|
||||
"brstm",
|
||||
"brstmspm",
|
||||
"brwav",
|
||||
"brwsd", //fake extension for RWSD (non-format)
|
||||
"bsnd",
|
||||
"btsnd",
|
||||
"bvg",
|
||||
|
@ -776,7 +779,7 @@ static const coding_info coding_info_list[] = {
|
|||
{coding_SNDS_IMA, "Heavy Iron .snds 4-bit IMA ADPCM"},
|
||||
{coding_QD_IMA, "Quantic Dream 4-bit IMA ADPCM"},
|
||||
{coding_WV6_IMA, "Gorilla Systems WV6 4-bit IMA ADPCM"},
|
||||
{coding_ALP_IMA, "High Voltage ALP 4-bit IMA ADPCM"},
|
||||
{coding_HV_IMA, "High Voltage 4-bit IMA ADPCM"},
|
||||
{coding_FFTA2_IMA, "Final Fantasy Tactics A2 4-bit IMA ADPCM"},
|
||||
{coding_BLITZ_IMA, "Blitz Games 4-bit IMA ADPCM"},
|
||||
{coding_MTF_IMA, "MT Framework 4-bit IMA ADPCM"},
|
||||
|
@ -1202,7 +1205,7 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_MTAF, "Konami MTAF header"},
|
||||
{meta_PS2_VAG1, "Konami VAG1 header"},
|
||||
{meta_PS2_VAG2, "Konami VAG2 header"},
|
||||
{meta_TUN, "Lego Racers ALP header"},
|
||||
{meta_ALP, "High Voltage ALP header"},
|
||||
{meta_WPD, "WPD 'DPW' header"},
|
||||
{meta_MN_STR, "Mini Ninjas 'STR' header"},
|
||||
{meta_MSS, "Guerilla MCSS header"},
|
||||
|
@ -1223,7 +1226,8 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_HCA, "CRI HCA header"},
|
||||
{meta_SVAG_SNK, "SNK SVAG header"},
|
||||
{meta_PS2_VDS_VDM, "Procyon Studio VDS/VDM header"},
|
||||
{meta_FFMPEG, "FFmpeg supported file format"},
|
||||
{meta_FFMPEG, "FFmpeg supported format"},
|
||||
{meta_FFMPEG_faulty, "FFmpeg supported format (check log)"},
|
||||
{meta_X360_CXS, "tri-Crescendo CXS header"},
|
||||
{meta_AKB, "Square-Enix AKB header"},
|
||||
{meta_X360_PASX, "Premium Agency PASX header"},
|
||||
|
|
|
@ -7,28 +7,35 @@
|
|||
* as pseudo dynamic/multi-song container [Sega Ages 2500 Vol 28 Tetris Collection (PS2)] */
|
||||
#define MAX_SEGMENTS 120
|
||||
|
||||
static VGMSTREAM* build_segmented_vgmstream(STREAMFILE* sf, off_t* segment_offsets, size_t* segment_sizes, int32_t* segment_samples, int segment_count, int layer_count);
|
||||
typedef struct {
|
||||
uint32_t segment_offsets[MAX_SEGMENTS];
|
||||
uint32_t segment_sizes[MAX_SEGMENTS];
|
||||
int32_t segment_samples[MAX_SEGMENTS];
|
||||
int segment_rates[MAX_SEGMENTS];
|
||||
|
||||
int segment_count;
|
||||
int layer_count;
|
||||
|
||||
int force_disable_loop;
|
||||
} aix_header_t;
|
||||
|
||||
static VGMSTREAM* build_segmented_vgmstream(STREAMFILE* sf, aix_header_t* aix);
|
||||
|
||||
/* AIX - N segments with M layers (2ch ADX) inside [SoulCalibur IV (PS3), Dragon Ball Z: Burst Limit (PS3)] */
|
||||
VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
|
||||
off_t segment_offsets[MAX_SEGMENTS] = {0};
|
||||
size_t segment_sizes[MAX_SEGMENTS] = {0};
|
||||
int32_t segment_samples[MAX_SEGMENTS] = {0};
|
||||
int segment_rates[MAX_SEGMENTS] = {0};
|
||||
|
||||
aix_header_t aix = {0};
|
||||
off_t data_offset, subtable_offset;
|
||||
int segment_count, layer_count;
|
||||
int i;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00, sf, "AIXF"))
|
||||
goto fail;
|
||||
if (!check_extensions(sf, "aix"))
|
||||
goto fail;
|
||||
if (read_u32be(0x00,sf) != 0x41495846 || /* "AIXF" */
|
||||
read_u32be(0x08,sf) != 0x01000014 || /* version? */
|
||||
read_u32be(0x0c,sf) != 0x00000800)
|
||||
if (read_u32be(0x08,sf) != 0x01000014 || /* version? */
|
||||
read_u32be(0x0c,sf) != 0x00000800) /* header size? */
|
||||
goto fail;
|
||||
|
||||
/* AIX combine layers for multichannel and segments for looping, all very hacky.
|
||||
|
@ -42,30 +49,42 @@ VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) {
|
|||
const off_t segment_list_offset = 0x20;
|
||||
const size_t segment_list_entry_size = 0x10;
|
||||
|
||||
segment_count = read_u16be(0x18,sf);
|
||||
if (segment_count < 1 || segment_count > MAX_SEGMENTS) goto fail;
|
||||
aix.segment_count = read_u16be(0x18,sf);
|
||||
if (aix.segment_count < 1 || aix.segment_count > MAX_SEGMENTS) goto fail;
|
||||
|
||||
subtable_offset = segment_list_offset + segment_count*segment_list_entry_size;
|
||||
subtable_offset = segment_list_offset + aix.segment_count * segment_list_entry_size;
|
||||
if (subtable_offset >= data_offset) goto fail;
|
||||
|
||||
for (i = 0; i < segment_count; i++) {
|
||||
segment_offsets[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x00,sf);
|
||||
segment_sizes[i] = read_u32be(segment_list_offset + segment_list_entry_size*i + 0x04,sf);
|
||||
segment_samples[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x08,sf);
|
||||
segment_rates[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x0c,sf);
|
||||
for (i = 0; i < aix.segment_count; i++) {
|
||||
aix.segment_offsets[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x00,sf);
|
||||
aix.segment_sizes[i] = read_u32be(segment_list_offset + segment_list_entry_size*i + 0x04,sf);
|
||||
aix.segment_samples[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x08,sf);
|
||||
aix.segment_rates[i] = read_s32be(segment_list_offset + segment_list_entry_size*i + 0x0c,sf);
|
||||
|
||||
/* segments > 0 can have 0 sample rate, seems to indicate same as first
|
||||
* [Ryu ga Gotoku: Kenzan! (PS3) tenkei_sng1.aix] */
|
||||
if (i > 0 && segment_rates[i] == 0)
|
||||
segment_rates[i] = segment_rates[0];
|
||||
if (i > 0 && aix.segment_rates[i] == 0)
|
||||
aix.segment_rates[i] = aix.segment_rates[0];
|
||||
|
||||
/* all segments must have equal sample rate */
|
||||
if (segment_rates[i] != segment_rates[0])
|
||||
if (aix.segment_rates[i] != aix.segment_rates[0])
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (segment_offsets[0] != data_offset)
|
||||
if (aix.segment_offsets[0] != data_offset)
|
||||
goto fail;
|
||||
|
||||
/* Metroid: Other M (Wii)'s bgm_m_stage_06_02 is truncated on disc, seemingly not an extraction error.
|
||||
* Playing expected samples aligns to bgm_m_stage_06, but from tests seems the song stops once reaching
|
||||
* the missing audio (doesn't loop). */
|
||||
if (aix.segment_count == 3 && aix.segment_offsets[1] + aix.segment_sizes[1] > get_streamfile_size(sf)) {
|
||||
aix.segment_count = 2;
|
||||
|
||||
aix.segment_sizes[1] = get_streamfile_size(sf) - aix.segment_offsets[1];
|
||||
//aix.segment_samples[1] = 0;
|
||||
aix.force_disable_loop = 1; /* force */
|
||||
vgm_logi("AIX: missing data, parts will be silent\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* between the segment and layer table some kind of 0x10 subtable? */
|
||||
|
@ -80,15 +99,15 @@ VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) {
|
|||
layer_list_offset = subtable_offset + 0x10;
|
||||
if (layer_list_offset >= data_offset) goto fail;
|
||||
|
||||
layer_count = read_u8(layer_list_offset,sf);
|
||||
if (layer_count < 1) goto fail;
|
||||
aix.layer_count = read_u8(layer_list_offset,sf);
|
||||
if (aix.layer_count < 1) goto fail;
|
||||
|
||||
layer_list_end = layer_list_offset + 0x08 + layer_count*layer_list_entry_size;
|
||||
layer_list_end = layer_list_offset + 0x08 + aix.layer_count * layer_list_entry_size;
|
||||
if (layer_list_end >= data_offset) goto fail;
|
||||
|
||||
for (i = 0; i < layer_count; i++) {
|
||||
for (i = 0; i < aix.layer_count; i++) {
|
||||
/* all layers must have same sample rate as segments */
|
||||
if (read_s32be(layer_list_offset + 0x08 + i*layer_list_entry_size + 0x00,sf) != segment_rates[0])
|
||||
if (read_s32be(layer_list_offset + 0x08 + i * layer_list_entry_size + 0x00,sf) != aix.segment_rates[0])
|
||||
goto fail;
|
||||
/* 0x04: layer channels */
|
||||
}
|
||||
|
@ -96,7 +115,7 @@ VGMSTREAM* init_vgmstream_aix(STREAMFILE* sf) {
|
|||
|
||||
|
||||
/* build combo layers + segments VGMSTREAM */
|
||||
vgmstream = build_segmented_vgmstream(sf, segment_offsets, segment_sizes, segment_samples, segment_count, layer_count);
|
||||
vgmstream = build_segmented_vgmstream(sf, &aix);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_AIX;
|
||||
|
@ -108,7 +127,7 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static VGMSTREAM *build_layered_vgmstream(STREAMFILE* sf, off_t segment_offset, size_t segment_size, int layer_count) {
|
||||
static VGMSTREAM* build_layered_vgmstream(STREAMFILE* sf, aix_header_t* aix, int segment) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
layered_layout_data* data = NULL;
|
||||
int i;
|
||||
|
@ -116,12 +135,12 @@ static VGMSTREAM *build_layered_vgmstream(STREAMFILE* sf, off_t segment_offset,
|
|||
|
||||
|
||||
/* build layers */
|
||||
data = init_layout_layered(layer_count);
|
||||
data = init_layout_layered(aix->layer_count);
|
||||
if (!data) goto fail;
|
||||
|
||||
for (i = 0; i < layer_count; i++) {
|
||||
for (i = 0; i < aix->layer_count; i++) {
|
||||
/* build the layer STREAMFILE */
|
||||
temp_sf = setup_aix_streamfile(sf, segment_offset, segment_size, i, "adx");
|
||||
temp_sf = setup_aix_streamfile(sf, aix->segment_offsets[segment], aix->segment_sizes[segment], i, "adx");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
/* build the sub-VGMSTREAM */
|
||||
|
@ -130,6 +149,18 @@ static VGMSTREAM *build_layered_vgmstream(STREAMFILE* sf, off_t segment_offset,
|
|||
|
||||
data->layers[i]->stream_size = get_streamfile_size(temp_sf);
|
||||
|
||||
#if 0
|
||||
/* for rare truncated AIX */
|
||||
if (aix->segment_samples[segment] == 0) {
|
||||
VGMSTREAM* vl = data->layers[i];
|
||||
uint32_t offset = read_u16be(0x02, temp_sf) + 0x04;
|
||||
uint32_t size = vl->stream_size - offset;
|
||||
uint32_t frames = size / vl->interleave_block_size / vl->channels;
|
||||
|
||||
vl->num_samples = frames * ((vl->interleave_block_size - 2) * 2) + 0x100;
|
||||
}
|
||||
#endif
|
||||
|
||||
close_streamfile(temp_sf);
|
||||
temp_sf = NULL;
|
||||
}
|
||||
|
@ -151,38 +182,46 @@ fail:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static VGMSTREAM *build_segmented_vgmstream(STREAMFILE* sf, off_t* segment_offsets, size_t* segment_sizes, int32_t* segment_samples, int segment_count, int layer_count) {
|
||||
static VGMSTREAM* build_segmented_vgmstream(STREAMFILE* sf, aix_header_t* aix) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
segmented_layout_data* data = NULL;
|
||||
int i, loop_flag, loop_start_segment, loop_end_segment;
|
||||
|
||||
|
||||
/* build segments */
|
||||
data = init_layout_segmented(segment_count);
|
||||
data = init_layout_segmented(aix->segment_count);
|
||||
if (!data) goto fail;
|
||||
|
||||
for (i = 0; i < segment_count; i++) {
|
||||
for (i = 0; i < aix->segment_count; i++) {
|
||||
/* build the layered sub-VGMSTREAM */
|
||||
data->segments[i] = build_layered_vgmstream(sf, segment_offsets[i], segment_sizes[i], layer_count);
|
||||
data->segments[i] = build_layered_vgmstream(sf, aix, i);
|
||||
if (!data->segments[i]) goto fail;
|
||||
|
||||
data->segments[i]->num_samples = segment_samples[i]; /* just in case */
|
||||
data->segments[i]->stream_size = aix->segment_sizes[i];
|
||||
|
||||
data->segments[i]->stream_size = segment_sizes[i];
|
||||
data->segments[i]->num_samples = aix->segment_samples[i];
|
||||
#if 0
|
||||
/* should be the same as layer's */
|
||||
if (aix->segment_samples[i] != 0) {
|
||||
data->segments[i]->num_samples = aix->segment_samples[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!setup_layout_segmented(data))
|
||||
goto fail;
|
||||
|
||||
/* known loop cases:
|
||||
/* known loop cases (no info on header, controlled by game?):
|
||||
* - 1 segment: main/no loop [Hatsune Miku: Project Diva (PSP)]
|
||||
* - 2 segments: intro + loop [SoulCalibur IV (PS3)]
|
||||
* - 3 segments: intro + loop + end [Dragon Ball Z: Burst Limit (PS3), Metroid: Other M (Wii)]
|
||||
* - 4/5 segments: intros + loop + ends [Danball Senki (PSP)]
|
||||
* - +39 segments: no loops but multiple segments for dynamic parts? [Tetris Collection (PS2)] */
|
||||
loop_flag = (segment_count > 0 && segment_count <= 5);
|
||||
loop_start_segment = (segment_count > 3) ? 2 : 1;
|
||||
loop_end_segment = (segment_count > 3) ? (segment_count - 2) : 1;
|
||||
loop_flag = (aix->segment_count > 0 && aix->segment_count <= 5);
|
||||
loop_start_segment = (aix->segment_count > 3) ? 2 : 1;
|
||||
loop_end_segment = (aix->segment_count > 3) ? (aix->segment_count - 2) : 1;
|
||||
if (aix->force_disable_loop)
|
||||
loop_flag = 0;
|
||||
|
||||
/* build the segmented VGMSTREAM */
|
||||
vgmstream = allocate_segmented_vgmstream(data, loop_flag, loop_start_segment, loop_end_segment);
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* ALP - from High Voltage games [LEGO Racers (PC), NBA Inside Drive 2000 (PC)] */
|
||||
VGMSTREAM* init_vgmstream_alp(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channels, sample_rate;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "ALP "))
|
||||
goto fail;
|
||||
/* .tun: stereo
|
||||
* .pcm: mono */
|
||||
if (!check_extensions(sf,"tun,pcm"))
|
||||
goto fail;
|
||||
|
||||
start_offset = read_u32le(0x04, sf) + 0x08;
|
||||
if (!is_id32be(0x08,sf, "ADPC")) /* codec, probably */
|
||||
goto fail;
|
||||
/* 0x0c: "M\0\0" */
|
||||
channels = read_u8(0x0f, sf);
|
||||
|
||||
/* NBA Inside Drive 2000 (PC) */
|
||||
if (start_offset >= 0x14)
|
||||
sample_rate = read_s32le(0x10, sf); /* still 22050 though */
|
||||
else
|
||||
sample_rate = 22050;
|
||||
|
||||
loop_flag = 0;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_ALP;
|
||||
vgmstream->channels = channels;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(sf) - start_offset, channels);
|
||||
|
||||
vgmstream->coding_type = coding_HV_IMA;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x01;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
|
@ -7,18 +7,22 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) {
|
|||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
int type, big_endian = 0, entries;
|
||||
int big_endian = 0, entries, version, platform, format;
|
||||
uint32_t subfile_offset = 0, subfile_size = 0, header_size, entry_size;
|
||||
|
||||
init_vgmstream_t init_vgmstream = NULL;
|
||||
const char* fake_ext;
|
||||
const char* fake_ext = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "ATSL"))
|
||||
goto fail;
|
||||
/* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
|
||||
if (!check_extensions(sf,"atsl,atsl3,atsl4"))
|
||||
|
||||
/* .atsl: common extension (PC/PS4/etc)
|
||||
* .atsl3: PS3 games
|
||||
* .atsl4: some PS4 games
|
||||
* .atslx: X360 games */
|
||||
if (!check_extensions(sf,"atsl,atsl3,atsl4,atslx"))
|
||||
goto fail;
|
||||
|
||||
/* main header (LE) */
|
||||
|
@ -31,58 +35,44 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) {
|
|||
/* 0x20: subheader size */
|
||||
/* 0x24/28: null */
|
||||
|
||||
/* Type byte may be wrong (could need header id tests instead). Example flags at 0x08/0x0c:
|
||||
/* 0x08: unknown, varies */
|
||||
|
||||
/* 0x0c(1): 0/1 (version? seen both in even in the same game) */
|
||||
version = read_u8(0x0c, sf); /* <~2017 = v0, both seen in Nioh (PC) */
|
||||
platform = read_u8(0x0d, sf);
|
||||
/* 0x0e: header version? (00~04: size 0x28, 05~06: size 0x30), 03~05 seen in Nioh (PS4) */
|
||||
/* 0x0f: always 1? */
|
||||
|
||||
big_endian = (platform == 0x02 || platform == 0x03); /* PS3/X360 */
|
||||
|
||||
/* Example flags at 0x08/0x0c for reference:
|
||||
* - 00010101 00020001 .atsl3 from One Piece Pirate Warriors (PS3)[ATRAC3]
|
||||
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]
|
||||
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]-bgm007
|
||||
* - 01010301 00030201 .atsl3 from Fist of North Star: Ken's Rage 2 (X360)[ATRAC3]-bgm007
|
||||
* 00000301 00020101 (same)
|
||||
* - 01040301 00060301 .atsl4 from Nobunaga's Ambition: Sphere of Influence (PS4)[ATRAC9]
|
||||
* - 00060301 00040301 .atsl in G1L from One Piece Pirate Warriors 3 (Vita)[ATRAC9]
|
||||
* - 00060301 00010301 .atsl in G1L from One Piece Pirate Warriors 3 (PC)[KOVS]
|
||||
* - 000A0301 00010501 .atsl in G1L from Warriors All-Stars (PC)[KOVS] 2017-09
|
||||
* - 01000000 01010501 .atsl from Nioh (PC)[KOVS] 2017-11
|
||||
* - 01000000 00010501 .atsl from Nioh (PC)[KOVS] 2017-11
|
||||
* - 000B0301 00080601 .atsl in G1l from Sengoku Musou Sanada Maru (Switch)[KTSS] 2017-09
|
||||
* - 01000000 00010501 .atsl from Nioh (PC)[KOVS] 2017-11
|
||||
* - 01000000 01010501 .atsl from Nioh (PC)[KOVS] 2017-11
|
||||
* - 03070301 01060301 .atsl from Nioh (PS4)[ATRAC9]
|
||||
* - 00080301 01060401 .atsl from Nioh (PS4)[ATRAC9]
|
||||
* - 00090301 01060501 .atsl from Nioh (PS4)[ATRAC9] (bigger header)
|
||||
* - 010C0301 01060601 .atsl from Dynasty Warriors 9 (PS4)[KTAC]
|
||||
* - 010D0301 01010601 .atsl from Dynasty Warriors 9 DLC (PC)[KOVS]
|
||||
*/
|
||||
|
||||
type = read_u16le(0x0c, sf);
|
||||
//version = read_u16le(0x0e, sf);
|
||||
switch(type) {
|
||||
case 0x0100: /* KOVS */
|
||||
init_vgmstream = init_vgmstream_ogg_vorbis;
|
||||
fake_ext = "kvs";
|
||||
switch(version) {
|
||||
case 0x00:
|
||||
entry_size = 0x28;
|
||||
break;
|
||||
case 0x0101:
|
||||
init_vgmstream = init_vgmstream_ogg_vorbis;
|
||||
fake_ext = "kvs";
|
||||
case 0x01:
|
||||
entry_size = 0x3c;
|
||||
break;
|
||||
case 0x0200: /* ATRAC3 */
|
||||
init_vgmstream = init_vgmstream_riff;
|
||||
fake_ext = "at3";
|
||||
entry_size = 0x28;
|
||||
big_endian = 1;
|
||||
break;
|
||||
case 0x0400:
|
||||
case 0x0600: /* ATRAC9 */
|
||||
init_vgmstream = init_vgmstream_riff;
|
||||
fake_ext = "at9";
|
||||
entry_size = 0x28;
|
||||
break;
|
||||
case 0x0601: /* KTAC */
|
||||
init_vgmstream = init_vgmstream_ktac;
|
||||
fake_ext = "ktac";
|
||||
entry_size = 0x3c;
|
||||
break;
|
||||
case 0x0800: /* KTSS */
|
||||
init_vgmstream = init_vgmstream_ktss;
|
||||
fake_ext = "ktss";
|
||||
entry_size = 0x28;
|
||||
break;
|
||||
default:
|
||||
vgm_logi("ATSL: unknown type %x (report)\n", type);
|
||||
vgm_logi("ATSL: unknown version %x (report)\n", version);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -99,11 +89,36 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) {
|
|||
int is_unique = 1;
|
||||
uint32_t entry_subfile_offset, entry_subfile_size;
|
||||
|
||||
/* 0x00: id */
|
||||
/* entry header (values match subfile header) */
|
||||
/* 0x00: id (0..N, usually) */
|
||||
entry_subfile_offset = read_u32(header_size + i*entry_size + 0x04,sf);
|
||||
entry_subfile_size = read_u32(header_size + i*entry_size + 0x08,sf);
|
||||
/* 0x10+: config, channels/sample rate/num_samples/loop_start/channel layout/etc (matches subfile header) */
|
||||
if (version == 0x00) {
|
||||
format = 0x00;
|
||||
/* 0x0c: sample rate */
|
||||
/* 0x10: samples */
|
||||
/* 0x14: loop start */
|
||||
/* 0x18: loop end */
|
||||
/* 0x1c: null? */
|
||||
/* 0x28: offset to unknown extra table (after entries) */
|
||||
/* 0x0c: unknown table entries (0x2C each) */
|
||||
}
|
||||
else {
|
||||
/* 0x0c: null? */
|
||||
/* 0x10: offset to unknown extra table (after entries) */
|
||||
/* 0x14: unknown table entries (0x2C each) */
|
||||
/* 0x18: channels */
|
||||
/* 0x1c: some hash/id? (same for all entries) */
|
||||
format = read_u32(header_size + i*entry_size + 0x20, sf);
|
||||
/* 0x24: sample rate */
|
||||
/* 0x28: samples */
|
||||
/* 0x2c: encoder delay */
|
||||
/* 0x30: loop start (includes delay) */
|
||||
/* 0x34: channel layout */
|
||||
/* 0x38: null? */
|
||||
}
|
||||
|
||||
//TODO use silence subsong?
|
||||
/* dummy entry, seen in DW9 DLC (has unique config though) */
|
||||
if (!entry_subfile_offset && !entry_subfile_size)
|
||||
continue;
|
||||
|
@ -127,11 +142,64 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) {
|
|||
subfile_size = entry_subfile_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||||
if (!subfile_offset || !subfile_size) goto fail;
|
||||
|
||||
/* some kind of seek/switch table may follow (optional, found in .atsl3) */
|
||||
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||||
if (!subfile_offset || !subfile_size) goto fail;
|
||||
|
||||
/* some kind of switch table may follow (referenced in entries) */
|
||||
}
|
||||
|
||||
/* similar codec values also seen in KTSR */
|
||||
switch(platform) {
|
||||
case 0x01: /* PC */
|
||||
if (format == 0x0000 || format == 0x0005) {
|
||||
init_vgmstream = init_vgmstream_ogg_vorbis;
|
||||
fake_ext = "kvs";
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x02: /* PS3 */
|
||||
if (format == 0x0000) {
|
||||
init_vgmstream = init_vgmstream_riff;
|
||||
fake_ext = "at3";
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: /* X360 */
|
||||
if (format == 0x0000) {
|
||||
init_vgmstream = init_vgmstream_xma;
|
||||
fake_ext = "xma";
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04: /* Vita */
|
||||
case 0x06: /* PS4 */
|
||||
if (format == 0x0000 || format == 0x1001) { /* Nioh (PS4)-1001 */
|
||||
init_vgmstream = init_vgmstream_riff;
|
||||
fake_ext = "at9";
|
||||
}
|
||||
else if (format == 0x1000) { /* Dynasty Warriors 9 (PS4) patch BGM */
|
||||
init_vgmstream = init_vgmstream_ktac;
|
||||
fake_ext = "ktac";
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x08: /* Switch */
|
||||
if (format == 0x0000 || format == 0x0005) {/* Dynasty Warriors 9 (Switch)-0005 w/ Opus */
|
||||
init_vgmstream = init_vgmstream_ktss;
|
||||
fake_ext = "ktss";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (init_vgmstream == NULL || fake_ext == NULL) {
|
||||
vgm_logi("ATSL: unknown platform %x + format %x (report)\n", platform, format);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, fake_ext);
|
||||
if (!temp_sf) goto fail;
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
|
||||
/* Bioware pseudo-format (for sfx) [Star Wars: Knights of the Old Republic 1/2 (PC/Switch/iOS)] */
|
||||
VGMSTREAM* init_vgmstream_bw_mp3_riff(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
uint32_t subfile_offset = 0, subfile_size = 0;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (read_u32be(0x00, sf) != 0xFFF360C4)
|
||||
goto fail;
|
||||
//if ((read_u32be(0x00, sf) & 0xFFF00000) != 0xFFF00000) /* no point to check other mp3s */
|
||||
// goto fail;
|
||||
if (!is_id32be(0x0d, sf, "LAME") && !is_id32be(0x1d6, sf, "RIFF"))
|
||||
goto fail;
|
||||
|
||||
/* strange mix of micro empty MP3 (LAME3.93, common header) + standard RIFF */
|
||||
|
||||
subfile_offset = 0x1d6;
|
||||
subfile_size = read_u32le(subfile_offset + 0x04, sf) + 0x08;
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "wav");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
/* init the VGMSTREAM */
|
||||
vgmstream = init_vgmstream_riff(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
close_streamfile(temp_sf);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_sf);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Bioware pseudo-format (for music) [Star Wars: Knights of the Old Republic 1/2 (PC/Switch/iOS)] */
|
||||
VGMSTREAM* init_vgmstream_bw_riff_mp3(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
uint32_t subfile_offset = 0, subfile_size = 0;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00, sf, "RIFF"))
|
||||
goto fail;
|
||||
if (read_u32le(0x04, sf) != 0x32)
|
||||
goto fail;
|
||||
if (get_streamfile_size(sf) <= 0x32 + 0x08) /* ? */
|
||||
goto fail;
|
||||
|
||||
/* strange mix of micro RIFF (with codec 0x01, "fact" and "data" size 0)) + standard MP3 (sometimes with ID3) */
|
||||
|
||||
subfile_offset = 0x3A;
|
||||
subfile_size = get_streamfile_size(sf) - subfile_offset;
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "mp3");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
/* init the VGMSTREAM */
|
||||
vgmstream = init_vgmstream_mpeg(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
close_streamfile(temp_sf);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_sf);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
|
@ -7,7 +7,6 @@ static int read_pos_file(uint8_t* buf, size_t bufsize, STREAMFILE* sf);
|
|||
static int find_meta_loops(ffmpeg_codec_data* data, int32_t* p_loop_start, int32_t* p_loop_end);
|
||||
|
||||
/* parses any format supported by FFmpeg and not handled elsewhere:
|
||||
* - MP3 (.mp3, .mus): Marc Ecko's Getting Up (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)
|
||||
|
@ -26,6 +25,7 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
|
|||
int loop_flag = 0, channels, sample_rate;
|
||||
int32_t loop_start = 0, loop_end = 0, num_samples = 0, encoder_delay = 0;
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
int faulty = 0; /* mark wonky rips in hopes people may fix them */
|
||||
|
||||
/* no checks */
|
||||
//if (!check_extensions(sf, "..."))
|
||||
|
@ -102,6 +102,21 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
|
|||
ffmpeg_set_skip_samples(data, encoder_delay);
|
||||
}
|
||||
|
||||
/* detect broken RIFFs */
|
||||
if (is_id32be(0x00, sf, "RIFF")) {
|
||||
uint32_t size = read_u32le(0x04, sf);
|
||||
/* There is a log in RIFF too but to be extra sure and sometimes FFmpeg don't handle it (this is mainly for wrong AT3).
|
||||
* Some proper RIFF can be parsed here too (like DUCK). */
|
||||
if (size + 0x08 > get_streamfile_size(sf)) {
|
||||
vgm_logi("RIFF/FFmpeg: incorrect size, file may have missing data\n");
|
||||
faulty = 1;
|
||||
}
|
||||
else if (size + 0x08 < get_streamfile_size(sf)) {
|
||||
vgm_logi("RIFF/FFmpeg: incorrect size, file may have padded data\n");
|
||||
faulty = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* default but often inaccurate when calculated using bitrate (wrong for VBR) */
|
||||
if (!num_samples) {
|
||||
num_samples = ffmpeg_get_samples(data); /* may be 0 if FFmpeg can't precalculate it */
|
||||
|
@ -115,7 +130,7 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) {
|
|||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_FFMPEG;
|
||||
vgmstream->meta_type = faulty ? meta_FFMPEG_faulty : meta_FFMPEG;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
|
||||
vgmstream->codec_data = data;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
|
||||
typedef enum { NONE, MSADPCM, DSP, GCADPCM, ATRAC9, KVS, /*KNS*/ } ktsr_codec;
|
||||
typedef enum { NONE, MSADPCM, DSP, GCADPCM, ATRAC9, RIFF_ATRAC9, KOVS, /*KNS*/ } ktsr_codec;
|
||||
|
||||
#define MAX_CHANNELS 8
|
||||
|
||||
|
@ -126,8 +126,28 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
|
|||
}
|
||||
#endif
|
||||
|
||||
case RIFF_ATRAC9: {
|
||||
VGMSTREAM* riff_vgmstream = NULL; //TODO: meh
|
||||
STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "at9");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
riff_vgmstream = init_vgmstream_riff(temp_sf);
|
||||
close_streamfile(temp_sf);
|
||||
if (!riff_vgmstream) goto fail;
|
||||
|
||||
riff_vgmstream->stream_size = vgmstream->stream_size;
|
||||
riff_vgmstream->num_streams = vgmstream->num_streams;
|
||||
riff_vgmstream->channel_layout = vgmstream->channel_layout;
|
||||
|
||||
strcpy(riff_vgmstream->stream_name, vgmstream->stream_name);
|
||||
|
||||
close_vgmstream(vgmstream);
|
||||
if (sf_b != sf) close_streamfile(sf_b);
|
||||
return riff_vgmstream;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case KVS: {
|
||||
case KOVS: {
|
||||
VGMSTREAM* ogg_vgmstream = NULL; //TODO: meh
|
||||
STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "kvs");
|
||||
if (!temp_sf) goto fail;
|
||||
|
@ -234,18 +254,28 @@ static int parse_codec(ktsr_header* ktsr) {
|
|||
/* platform + format to codec, simplified until more codec combos are found */
|
||||
switch(ktsr->platform) {
|
||||
case 0x01: /* PC */
|
||||
if (ktsr->is_external)
|
||||
ktsr->codec = KVS;
|
||||
else if (ktsr->format == 0x00)
|
||||
if (ktsr->is_external) {
|
||||
if (ktsr->format == 0x0005)
|
||||
ktsr->codec = KOVS;
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
else if (ktsr->format == 0x0000) {
|
||||
ktsr->codec = MSADPCM;
|
||||
else
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: /* VITA */
|
||||
if (ktsr->is_external)
|
||||
goto fail;
|
||||
else if (ktsr->format == 0x01)
|
||||
case 0x03: /* PS4/VITA */
|
||||
if (ktsr->is_external) {
|
||||
if (ktsr->format == 0x1001)
|
||||
ktsr->codec = RIFF_ATRAC9;
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
else if (ktsr->format == 0x0001)
|
||||
ktsr->codec = ATRAC9;
|
||||
else
|
||||
goto fail;
|
||||
|
@ -254,7 +284,7 @@ static int parse_codec(ktsr_header* ktsr) {
|
|||
case 0x04: /* Switch */
|
||||
if (ktsr->is_external)
|
||||
goto fail; /* KTSS? */
|
||||
else if (ktsr->format == 0x00)
|
||||
else if (ktsr->format == 0x0000)
|
||||
ktsr->codec = DSP;
|
||||
else
|
||||
goto fail;
|
||||
|
@ -281,14 +311,14 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, uint32_t offset
|
|||
/* probably could check the flag in sound header, but the format is kinda messy */
|
||||
switch(type) {
|
||||
|
||||
case 0x38D0437D: /* external [Nioh (PC), Atelier Ryza (PC)] */
|
||||
case 0x3DEA478D: /* external [Nioh (PC)] */
|
||||
case 0x38D0437D: /* external [Nioh (PC/PS4), Atelier Ryza (PC)] */
|
||||
case 0x3DEA478D: /* external [Nioh (PC)] (smaller) */
|
||||
case 0xDF92529F: /* external [Atelier Ryza (PC)] */
|
||||
case 0x6422007C: /* external [Atelier Ryza (PC)] */
|
||||
/* 08 subtype? (ex. 0x522B86B9)
|
||||
* 0c channels
|
||||
* 10 ? (always 0x002706B8)
|
||||
* 14 codec? (05=KVS)
|
||||
* 14 external codec
|
||||
* 18 sample rate
|
||||
* 1c num samples
|
||||
* 20 null?
|
||||
|
@ -317,11 +347,6 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, uint32_t offset
|
|||
}
|
||||
ktsr->is_external = 1;
|
||||
|
||||
if (ktsr->format != 0x05) {
|
||||
VGM_LOG("ktsr: unknown subcodec at %x\n", offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x41FDBD4E: /* internal [Attack on Titan: Wings of Freedom (Vita)] */
|
||||
|
|
|
@ -541,7 +541,7 @@ VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_mtaf(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_tun(STREAMFILE* streamFile);
|
||||
VGMSTREAM* init_vgmstream_alp(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM * init_vgmstream_wpd(STREAMFILE* streamFile);
|
||||
|
||||
|
@ -988,4 +988,7 @@ VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf);
|
|||
|
||||
VGMSTREAM* init_vgmstream_tt_ad(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_bw_mp3_riff(STREAMFILE* sf);
|
||||
VGMSTREAM* init_vgmstream_bw_riff_mp3(STREAMFILE* sf);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
|
|
@ -11,13 +11,13 @@ VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) {
|
|||
size_t wave_length;
|
||||
int codec, channels, loop_flag;
|
||||
size_t stream_size;
|
||||
off_t start_offset, wave_offset = 0;
|
||||
off_t start_offset, wave_offset = 0, labl_offset;
|
||||
|
||||
|
||||
if (!is_id32be(0x00, sf, "RWSD"))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "rwsd"))
|
||||
if (!check_extensions(sf, "brwsd,rwsd"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
|
@ -98,6 +98,11 @@ VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) {
|
|||
|
||||
/* this is just data size and following data may or may not be from this RWSD */
|
||||
start_offset = read_32bitBE(0x08, sf);
|
||||
if (is_id32be(start_offset, sf, "LABL")) {
|
||||
labl_offset = start_offset;
|
||||
start_offset += read_32bitBE(start_offset + 0x04, sf);
|
||||
read_string(vgmstream->stream_name, 0x28, labl_offset + 0x18, sf);
|
||||
}
|
||||
|
||||
stream_size = read_32bitBE(wave_offset + 0x50,sf);
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* ALP - from LEGO Racers (PC) */
|
||||
VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* checks */
|
||||
if ( !check_extensions(streamFile,"tun") )
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x414C5020) /* "ALP " */
|
||||
goto fail;
|
||||
|
||||
channel_count = 2; /* probably at 0x0F */
|
||||
loop_flag = 0;
|
||||
start_offset = 0x10;
|
||||
/* also "ADPCM" at 0x08 */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = 22050;
|
||||
vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(streamFile) - 0x10, channel_count);
|
||||
|
||||
vgmstream->coding_type = coding_ALP_IMA;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x01;
|
||||
vgmstream->meta_type = meta_TUN;
|
||||
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
|
@ -47,6 +47,7 @@ typedef enum {
|
|||
XA_EA,
|
||||
CP_YM,
|
||||
PCM_FLOAT_LE,
|
||||
IMA_HV,
|
||||
|
||||
UNKNOWN = 99,
|
||||
} txth_codec_t;
|
||||
|
@ -240,6 +241,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
|
|||
case PCM_FLOAT_LE: coding = coding_PCMFLOAT; break;
|
||||
case SDX2: coding = coding_SDX2; break;
|
||||
case DVI_IMA: coding = coding_DVI_IMA; break;
|
||||
case IMA_HV: coding = coding_HV_IMA; break;
|
||||
#ifdef VGM_USE_MPEG
|
||||
case MPEG: coding = coding_MPEG_layer3; break; /* we later find out exactly which */
|
||||
#endif
|
||||
|
@ -316,6 +318,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
|
|||
case coding_PSX_badflags:
|
||||
case coding_DVI_IMA:
|
||||
case coding_IMA:
|
||||
case coding_HV_IMA:
|
||||
case coding_AICA:
|
||||
case coding_APPLE_IMA4:
|
||||
case coding_TGC:
|
||||
|
@ -968,6 +971,7 @@ static txth_codec_t parse_codec(txth_header* txth, const char* val) {
|
|||
else if (is_string(val,"XA_EA")) return XA_EA;
|
||||
else if (is_string(val,"CP_YM")) return CP_YM;
|
||||
else if (is_string(val,"PCM_FLOAT_LE")) return PCM_FLOAT_LE;
|
||||
else if (is_string(val,"IMA_HV")) return IMA_HV;
|
||||
/* special handling */
|
||||
else if (is_string(val,"name_value")) return txth->name_values[0];
|
||||
else if (is_string(val,"name_value1")) return txth->name_values[0];
|
||||
|
@ -2079,6 +2083,7 @@ static int get_bytes_to_samples(txth_header* txth, uint32_t bytes) {
|
|||
|
||||
case IMA:
|
||||
case DVI_IMA:
|
||||
case IMA_HV:
|
||||
return ima_bytes_to_samples(bytes, txth->channels);
|
||||
case AICA:
|
||||
case CP_YM:
|
||||
|
|
|
@ -257,7 +257,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
|||
init_vgmstream_eb_sfx,
|
||||
init_vgmstream_eb_sf0,
|
||||
init_vgmstream_mtaf,
|
||||
init_vgmstream_tun,
|
||||
init_vgmstream_alp,
|
||||
init_vgmstream_wpd,
|
||||
init_vgmstream_mn_str,
|
||||
init_vgmstream_mss,
|
||||
|
@ -524,6 +524,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
|||
init_vgmstream_esf,
|
||||
init_vgmstream_adm3,
|
||||
init_vgmstream_tt_ad,
|
||||
init_vgmstream_bw_mp3_riff,
|
||||
init_vgmstream_bw_riff_mp3,
|
||||
|
||||
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
||||
init_vgmstream_mpeg,
|
||||
|
|
|
@ -118,7 +118,7 @@ typedef enum {
|
|||
coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */
|
||||
coding_QD_IMA,
|
||||
coding_WV6_IMA, /* Gorilla Systems WV6 4-bit IMA ADPCM */
|
||||
coding_ALP_IMA, /* High Voltage ALP 4-bit IMA ADPCM */
|
||||
coding_HV_IMA, /* High Voltage 4-bit IMA ADPCM */
|
||||
coding_FFTA2_IMA, /* Final Fantasy Tactics A2 4-bit IMA ADPCM */
|
||||
coding_BLITZ_IMA, /* Blitz Games 4-bit IMA ADPCM */
|
||||
|
||||
|
@ -577,7 +577,7 @@ typedef enum {
|
|||
meta_MTAF,
|
||||
meta_PS2_VAG1, /* Metal Gear Solid 3 VAG1 */
|
||||
meta_PS2_VAG2, /* Metal Gear Solid 3 VAG2 */
|
||||
meta_TUN, /* LEGO Racers (PC) */
|
||||
meta_ALP,
|
||||
meta_WPD, /* Shuffle! (PC) */
|
||||
meta_MN_STR, /* Mini Ninjas (PC/PS3/WII) */
|
||||
meta_MSS, /* Guerilla: ShellShock Nam '67 (PS2/Xbox), Killzone (PS2) */
|
||||
|
@ -596,7 +596,8 @@ typedef enum {
|
|||
meta_HCA, /* CRI HCA */
|
||||
meta_SVAG_SNK,
|
||||
meta_PS2_VDS_VDM, /* Graffiti Kingdom */
|
||||
meta_FFMPEG, /* any file supported by FFmpeg */
|
||||
meta_FFMPEG,
|
||||
meta_FFMPEG_faulty,
|
||||
meta_X360_CXS, /* Eternal Sonata (Xbox 360) */
|
||||
meta_AKB, /* SQEX iOS */
|
||||
meta_X360_PASX, /* Namco PASX (Soul Calibur II HD X360) */
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
<string>atsl</string>
|
||||
<string>atsl3</string>
|
||||
<string>atsl4</string>
|
||||
<string>atslx</string>
|
||||
<string>atx</string>
|
||||
<string>aud</string>
|
||||
<string>audio</string>
|
||||
|
@ -192,6 +193,8 @@
|
|||
<string>bo2</string>
|
||||
<string>brstm</string>
|
||||
<string>brstmspm</string>
|
||||
<string>brwav</string>
|
||||
<string>brwsd</string>
|
||||
<string>bsnd</string>
|
||||
<string>btsnd</string>
|
||||
<string>bvg</string>
|
||||
|
|
Loading…
Reference in New Issue