Updated VGMStream to r1745-22-gf696beb0

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
swiftingly
Christopher Snowhill 2022-05-30 18:26:34 -07:00
parent bea896cca5
commit 94057cf467
18 changed files with 437 additions and 175 deletions

View File

@ -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 */,

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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"},

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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)] */

View File

@ -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*/

View File

@ -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);

View File

@ -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;
}

View File

@ -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:

View File

@ -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,

View File

@ -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) */

View File

@ -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>