If you have an issue with any of our projects. feel free to register.

Commit da72f8bb authored by Christopher Snowhill's avatar Christopher Snowhill

Updated VGMStream to r1050-2946-g1e583645

parent 05386bce
......@@ -592,6 +592,9 @@
83F0AA5F21E2028C004BBC04 /* smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F0AA5C21E2028B004BBC04 /* smp.c */; };
83F0AA6021E2028C004BBC04 /* vsv_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F0AA5D21E2028B004BBC04 /* vsv_streamfile.h */; };
83F0AA6121E2028C004BBC04 /* vsv.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F0AA5E21E2028C004BBC04 /* vsv.c */; };
83F1EE2D245D4FB20076E182 /* imuse_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F1EE28245D4FB10076E182 /* imuse_decoder.c */; };
83F1EE2E245D4FB20076E182 /* vadpcm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F1EE2C245D4FB20076E182 /* vadpcm_decoder.c */; };
83F1EE30245D4FC10076E182 /* imuse.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F1EE2F245D4FC10076E182 /* imuse.c */; };
83F5F8831908D0A400C8E65F /* fsb5.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F5F8821908D0A400C8E65F /* fsb5.c */; };
83FBD506235D31F800D35BCD /* riff_ogg_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FBD502235D31F700D35BCD /* riff_ogg_streamfile.h */; };
83FC176D23AC58D100E1025F /* xma_ue3.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FC176A23AC58D100E1025F /* xma_ue3.c */; };
......@@ -1294,6 +1297,9 @@
83F0AA5C21E2028B004BBC04 /* smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = smp.c; sourceTree = "<group>"; };
83F0AA5D21E2028B004BBC04 /* vsv_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vsv_streamfile.h; sourceTree = "<group>"; };
83F0AA5E21E2028C004BBC04 /* vsv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vsv.c; sourceTree = "<group>"; };
83F1EE28245D4FB10076E182 /* imuse_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = imuse_decoder.c; sourceTree = "<group>"; };
83F1EE2C245D4FB20076E182 /* vadpcm_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vadpcm_decoder.c; sourceTree = "<group>"; };
83F1EE2F245D4FC10076E182 /* imuse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = imuse.c; sourceTree = "<group>"; };
83F412871E932F9A002E37D0 /* Vorbis.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Vorbis.xcodeproj; path = ../Vorbis/macosx/Vorbis.xcodeproj; sourceTree = "<group>"; };
83F5F8821908D0A400C8E65F /* fsb5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fsb5.c; sourceTree = "<group>"; };
83FBD502235D31F700D35BCD /* riff_ogg_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = riff_ogg_streamfile.h; sourceTree = "<group>"; };
......@@ -1495,6 +1501,7 @@
836F6DE818BDC2180095E648 /* g7221_decoder.c */,
832389511D224C0800482226 /* hca_decoder.c */,
836F6DEA18BDC2180095E648 /* ima_decoder.c */,
83F1EE28245D4FB10076E182 /* imuse_decoder.c */,
836F6DEB18BDC2180095E648 /* l5_555_decoder.c */,
836F6DEC18BDC2180095E648 /* lsf_decoder.c */,
83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */,
......@@ -1527,6 +1534,7 @@
836F6DFC18BDC2180095E648 /* sdx2_decoder.c */,
8373341023F60C7A00DE14DC /* tgcadpcm_decoder.c */,
837CEA7623487E2400E62A4A /* ubi_adpcm_decoder.c */,
83F1EE2C245D4FB20076E182 /* vadpcm_decoder.c */,
839E21D61F2EDAF000EE54D7 /* vorbis_custom_data_fsb.h */,
839E21DC1F2EDAF000EE54D7 /* vorbis_custom_data_wwise.h */,
839E21D71F2EDAF000EE54D7 /* vorbis_custom_decoder.c */,
......@@ -1717,6 +1725,7 @@
83C7280922BC893C00678B4A /* ikm.c */,
837CEAE623487F2B00E62A4A /* ima.c */,
832BF81121E05149006F50F1 /* imc.c */,
83F1EE2F245D4FC10076E182 /* imuse.c */,
836F6E5518BDC2180095E648 /* ios_psnd.c */,
83AFABBB23795202002F3947 /* isb.c */,
836F6E5618BDC2180095E648 /* ish_isd.c */,
......@@ -2304,6 +2313,7 @@
8373341B23F60C7B00DE14DC /* g7221_decoder_lib.c in Sources */,
836F705318BDC2190095E648 /* streamfile.c in Sources */,
836F6F7418BDC2190095E648 /* bgw.c in Sources */,
83F1EE2D245D4FB20076E182 /* imuse_decoder.c in Sources */,
836F6F7218BDC2190095E648 /* baf.c in Sources */,
83F5F8831908D0A400C8E65F /* fsb5.c in Sources */,
836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */,
......@@ -2399,6 +2409,7 @@
834FE107215C79ED000A5D3D /* mib_mih.c in Sources */,
836F703618BDC2190095E648 /* thp.c in Sources */,
836F6F7818BDC2190095E648 /* Cstr.c in Sources */,
83F1EE30245D4FC10076E182 /* imuse.c in Sources */,
836F6F1E18BDC2190095E648 /* acm_decoder.c in Sources */,
836F6FD818BDC2190095E648 /* ps2_gbts.c in Sources */,
831BA61A1EAC61A500CF89B0 /* ps2_vds_vdm.c in Sources */,
......@@ -2759,6 +2770,7 @@
8306B0B920984552000302D4 /* blocked_matx.c in Sources */,
83A21F7B201D895B000F04B9 /* blocked_xvag.c in Sources */,
836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */,
83F1EE2E245D4FB20076E182 /* vadpcm_decoder.c in Sources */,
836F705018BDC2190095E648 /* ydsp.c in Sources */,
8306B0B720984552000302D4 /* blocked_str_snds.c in Sources */,
836F702718BDC2190095E648 /* sat_baka.c in Sources */,
......
......@@ -61,6 +61,11 @@ void decode_ngc_dtk(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspaci
/* ngc_afc_decoder */
void decode_ngc_afc(VGMSTREAMCHANNEL *stream, sample_t *outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* vadpcm_decoder */
void decode_vadpcm(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int order);
//int32_t vadpcm_bytes_to_samples(size_t bytes, int channels);
void vadpcm_read_coefs_be(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, int order, int entries, int ch);
/* pcm_decoder */
void decode_pcm16le(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16be(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
......@@ -205,6 +210,14 @@ void seek_ubi_adpcm(ubi_adpcm_codec_data *data, int32_t num_sample);
void free_ubi_adpcm(ubi_adpcm_codec_data *data);
int ubi_adpcm_get_samples(ubi_adpcm_codec_data *data);
/* imuse_decoder */
typedef struct imuse_codec_data imuse_codec_data;
imuse_codec_data *init_imuse(STREAMFILE* sf, int channels);
void decode_imuse(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do);
void reset_imuse(imuse_codec_data* data);
void seek_imuse(imuse_codec_data* data, int32_t num_sample);
void free_imuse(imuse_codec_data* data);
/* ea_mt_decoder*/
ea_mt_codec_data *init_ea_mt(int channels, int type);
ea_mt_codec_data *init_ea_mt_loops(int channels, int pcm_blocks, int loop_sample, off_t *loop_offsets);
......
This diff is collapsed.
#include "coding.h"
#include "../util.h"
/* Decodes Silicon Graphics' N64 VADPCM, big brother of GC ADPCM.
* Has external coefs like DSP, but allows tables up to 8 groups of 8 coefs (code book) and also
* up to 8 history samples (order). In practice order must be 2, while files use 2~4 tables, so it
* ends up being an overcomplex XA. Code respects this quirky configurable hist for doc purposes though.
*
* This code is based on N64SoundListTool decoding (by Ice Mario), with bits of the official SDK vadpcm tool
* decompilation. I can't get proper sound from the later though, so not too sure about accuracy of this
* implementation. Output sounds correct though.
*/
void decode_vadpcm(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int order) {
uint8_t frame[0x09] = {0};
off_t frame_offset;
int frames_in, sample_count = 0;
size_t bytes_per_frame, samples_per_frame;
int i, j, k, o;
int scale, index;
int codes[16]; /* AKA ix */
int16_t hist[8] = {0};
int16_t out[16];
int16_t* coefs;
VGM_ASSERT_ONCE(order != 2, "VADPCM: wrong order=%i\n", order);
if (order != 2) /* only 2 allowed "in the current implementation" */
order = 2;
/* up to 8 (hist[0]=oldest) but only uses latest 2 (order=2), so we don't save the whole thing ATM */
hist[6] = stream->adpcm_history2_16;
hist[7] = stream->adpcm_history1_16;
/* external interleave (fixed size), mono */
bytes_per_frame = 0x09;
samples_per_frame = (bytes_per_frame - 0x01) * 2; /* always 16 */
frames_in = first_sample / samples_per_frame;
first_sample = first_sample % samples_per_frame;
/* parse frame header */
frame_offset = stream->offset + bytes_per_frame * frames_in;
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
scale = (frame[0] >> 4) & 0xF;
index = (frame[0] >> 0) & 0xF;
scale = 1 << scale;
VGM_ASSERT_ONCE(index > 8, "DSP: incorrect index at %x\n", (uint32_t)frame_offset);
if (index > 8) /* assumed */
index = 8;
coefs = &stream->vadpcm_coefs[index * (order*8) + 0];
/* read and pre-scale all nibbles, since groups of 8 are needed */
for (i = 0, j = 0; i < 16; i += 2, j++) {
int n0 = (frame[j+1] >> 4) & 0xF;
int n1 = (frame[j+1] >> 0) & 0xF;
/* sign extend */
if (n0 & 8)
n0 = n0 - 16;
if (n1 & 8)
n1 = n1 - 16;
codes[i+0] = n0 * scale;
codes[i+1] = n1 * scale;
}
/* decode 2 sub-frames of 8 samples (maybe like this since N64 MIPS has registers to spare?) */
for (j = 0; j < 2; j++) {
/* SDK dec code and N64ST copy 8 codes to a tmp buf and has some complex logic to move out buf
* around, but since that's useless N64 asm would be much more optimized... hopefully */
int* sf_codes = &codes[j*8];
int16_t* sf_out = &out[j*8];
/* works with 8 samples at a time, related in twisted ways */
for( i = 0; i < 8; i++) {
int sample, delta = 0;
/* in practice: delta = coefs[0][i] * hist[6] + coefs[1][i] * hist[7],
* much like XA's coef1*hist1 + coef2*hist2 but with multi coefs */
for (o = 0; o < order; o++) {
delta += coefs[o*8 + i] * hist[(8 - order) + o];
}
/* adds all previous samples */
for (k = i-1; k > -1; k--) {
for (o = 1; o < order; o++) { /* assumed, since only goes coefs[1][k] */
delta += sf_codes[(i-1) - k] * coefs[(o*8) + k];
}
}
/* scale-filter thing (also seen in DSP) */
sample = (sf_codes[i] << 11);
sample = (sample + delta) >> 11;
if (sample > 32767)
sample = 32767;
else if (sample < -32768)
sample = -32768;
sf_out[i] = sample;
}
/* save subframe hist */
for (i = 8 - order; i < 8; i++) {
hist[i] = sf_out[i];
}
}
/* copy samples last, since the whole thing is kinda complex to worry about half copying and stuff */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
outbuf[sample_count] = out[i];
sample_count += channelspacing;
}
/* update hist once all frame is actually copied */
if (first_sample + sample_count == samples_per_frame) {
stream->adpcm_history2_16 = hist[6];
stream->adpcm_history1_16 = hist[7];
}
}
/*
int32_t vadpcm_bytes_to_samples(size_t bytes, int channels) {
if (channels <= 0) return 0;
return bytes / channels / 0x09 * 16;
}
*/
/* Reads code book, linearly unlike original SDK, that does some strange reordering and pre-scaling
* to reduce some loops. Format is 8 coefs per 'order' per 'entries' (max 8, but order is always 2). So:
* - i: table index (selectable filter tables on every decoded frame)
* - j: order index (coefs for prev N hist samples)
* - k: coef index (multiplication coefficient for 8 samples in a sub-frame)
* coefs[i * (order*8) + j * 8 + k * order] = coefs[i][j][k] */
void vadpcm_read_coefs_be(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t offset, int order, int entries, int ch) {
int i;
if (entries > 8)
entries = 8;
VGM_ASSERT(order != 2, "VADPCM: wrong order %i found\n", order);
if (order != 2)
order = 2;
/* assumes all channels use same coefs, never seen non-mono files */
for (i = 0; i < entries * order * 8; i++) {
vgmstream->ch[ch].vadpcm_coefs[i] = read_s16be(offset + i*2, sf);
}
vgmstream->codec_config = order;
}
......@@ -222,6 +222,7 @@ static const char* extension_list[] = {
"ilv", //txth/reserved [Star Wars Episode III (PS2)]
"ima",
"imc",
"imx",
"int",
"is14",
"isb",
......@@ -329,6 +330,7 @@ static const char* extension_list[] = {
"mxst",
"myspd",
"n64",
"naac",
"ndp",
"ngca",
......@@ -684,6 +686,7 @@ static const coding_info coding_info_list[] = {
{coding_NGC_DSP_subint, "Nintendo DSP 4-bit ADPCM (subinterleave)"},
{coding_NGC_DTK, "Nintendo DTK 4-bit ADPCM"},
{coding_NGC_AFC, "Nintendo AFC 4-bit ADPCM"},
{coding_VADPCM, "Silicon Graphics VADPCM 4-bit ADPCM"},
{coding_G721, "CCITT G.721 4-bit ADPCM"},
......@@ -764,6 +767,7 @@ static const coding_info coding_info_list[] = {
{coding_NWA, "VisualArt's NWA DPCM"},
{coding_CIRCUS_ADPCM, "Circus 8-bit ADPCM"},
{coding_UBI_ADPCM, "Ubisoft 4/6-bit ADPCM"},
{coding_IMUSE, "LucasArts iMUSE VIMA ADPCM"},
{coding_EA_MT, "Electronic Arts MicroTalk"},
{coding_CIRCUS_VQ, "Circus VQ"},
......@@ -1287,6 +1291,7 @@ static const meta_info meta_info_list[] = {
{meta_LRMD, "Sony LRMD header"},
{meta_WWISE_FX, "Audiokinetic Wwise FX header"},
{meta_DIVA, "DIVA header"},
{meta_IMUSE, "LucasArts iMUSE header"},
};
......
......@@ -168,7 +168,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
is_small = 1; //fsb5.num_samples < 20 * fsb5.sample_rate;
/* wrong values in some files [Pac-Man CE2 Plus (Switch) pce2p_bgm_ajurika_*.fsb] */
ajurika_loops = fsb5.loop_start == 0x3c && fsb5.loop_end == 0x007F007F &&
ajurika_loops = fsb5.loop_start == 0x3c && fsb5.loop_end == (0x007F007F + 1) &&
fsb5.num_samples > fsb5.loop_end + 10000; /* arbitrary test in case some game does have those */
fsb5.loop_flag = 1;
......
......@@ -24,7 +24,11 @@ VGMSTREAM * init_vgmstream_imc(STREAMFILE *streamFile) {
start_offset = 0x10;
/* extra checks since the header is so simple */
if (channel_count < 1 || channel_count > 8 || sample_rate < 22000 || sample_rate > 48000)
if (channel_count < 1 || channel_count > 8)
goto fail;
if (sample_rate < 11025 || sample_rate > 48000)
/* game can play 11025, 16000, 22050, 32000, 44100, 48000. Anything else will be
silent in-game. ST10.IMC subsongs 42-47 use 22000, those are unused silent audio */
goto fail;
if (interleave*blocks + start_offset != file_size)
goto fail;
......
#include "meta.h"
#include "../coding/coding.h"
static int is_id4(const char* test, off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return 0;
return memcmp(buf, test, sizeof(buf)) == 0; /* memcmp to allow "AB\0\0" */
}
/* LucasArts iMUSE (Interactive Music Streaming Engine) formats */
VGMSTREAM* init_vgmstream_imuse(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, name_offset = 0;
off_t head_offset, map_offset, offset;
size_t map_size, data_bytes;
int loop_flag, channels, sample_rate, num_samples;
/* checks */
/* .imx: The Curse of Monkey Island (PC)
* .imc: Grim Fandango (multi)
* .wav: Grim Fandango (multi) RIFF sfx */
if (!check_extensions(sf, "imx,imc,wav,lwav"))
goto fail;
/* base decoder block table */
if (is_id4("COMP", 0x00, sf)) { /* The Curse of Monkey Island (PC), The Dig (PC) */
int entries = read_u32be(0x04,sf);
head_offset = 0x10 + entries * 0x10 + 0x02; /* base header + table + header size */
}
else if (is_id4("MCMP", 0x00, sf)) { /* Grim Fandango (multi), Star Wars: X-Wing Alliance (PC) */
int entries = read_u16be(0x04,sf);
head_offset = 0x06 + entries * 0x09; /* base header + table */
head_offset += 0x02 + read_u16be(head_offset, sf); /* + mini text header */
}
else {
goto fail;
}
/* "offsets" below seem to count decoded data. Data is divided into variable-sized blocks that usually
* return 0x2000 bytes (starting from and including header). File starts with a block table to make
* this manageable. Most offsets don't seem to match block or data boundaries so not really sure. */
/* main header after table */
if (is_id4("iMUS", head_offset, sf)) { /* COMP/MCMP */
int header_found = 0;
/* 0x04: decompressed size (header size + pcm bytes) */
if (!is_id4("MAP ", head_offset + 0x08, sf))
goto fail;
map_size = read_u32be(head_offset + 0x0c, sf);
map_offset = head_offset + 0x10;
/* MAP table (commands for interactive use) */
offset = map_offset;
while (offset < map_offset + map_size) {
uint32_t type = read_u32be(offset + 0x00, sf);
uint32_t size = read_u32be(offset + 0x04, sf);
offset += 0x08;
switch(type) {
case 0x46524D54: /* "FRMT" (header, always first) */
if (header_found)
goto fail;
header_found = 1;
/* 00: data offset */
/* 04: 0? */
/* 08: sample size (16b) */
sample_rate = read_u32be(offset + 0x0c,sf);
channels = read_u32be(offset + 0x10,sf);
break;
case 0x54455854: /* "TEXT" (info) */
/* optional info usually before some REGN: "****"=start, "loop"=loop,
* use first TEXT as name, usually filename for music */
/* 00: offset */
if (!name_offset) /* */
name_offset = offset + 0x04; /* null terminated */
break;
/* - SYNC: 'lip' sync info
* 00 offset
* 04 sync commands until end?
* - REGN: section config (at least one?)
* 00 offset
* 04 size
* - JUMP: usually defines a loop, sometimes after a REGN
* 00 offset (from iMUS)
* 04 size?
* 08 number?
* 0c size?
* - STOP: last command (always?)
* 00 offset
*/
default: /* maybe set REGN as subsongs? + imuse_set_region(vgmstream->data, offset, size) */
break;
}
offset += size;
}
if (!header_found)
goto fail;
if (!is_id4("DATA", head_offset + 0x10 + map_size + 0x00, sf))
goto fail;
data_bytes = read_u32be(head_offset + 0x10 + map_size + 0x04, sf);
num_samples = data_bytes / channels / sizeof(int16_t);
//num_samples = (read_u32be(head_offset + 0x04,sf) - head_size) / channels / sizeof(int16_t); /* equivalent */
}
else if (is_id4("RIFF", head_offset, sf)) { /* MCMP voices */
/* standard (LE), with fake codec 1 and sizes also in decoded bytes (see above) */
if (!is_id4("fmt ", head_offset + 0x0c, sf))
goto fail;
offset = head_offset + 0x14;
channels = read_u16le(offset + 0x02,sf);
sample_rate = read_u32le(offset + 0x04,sf);
if (!is_id4("data", head_offset + 0x24, sf))
goto fail;
data_bytes = read_u32le(head_offset + 0x28, sf);
num_samples = data_bytes / channels / sizeof(int16_t);
}
else {
goto fail; /* The Dig (PC) has no header, detect? */
}
loop_flag = 0;
start_offset = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_IMUSE;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->coding_type = coding_IMUSE;
vgmstream->layout_type = layout_none;
vgmstream->codec_data = init_imuse(sf, channels);
if (!vgmstream->codec_data) goto fail;
if (name_offset > 0)
read_string(vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf);
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
......@@ -895,4 +895,6 @@ VGMSTREAM* init_vgmstream_encrypted(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_diva(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_imuse(STREAMFILE* sf);
#endif /*_META_H*/
......@@ -493,6 +493,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_bkhd,
init_vgmstream_bkhd_fx,
init_vgmstream_diva,
init_vgmstream_imuse,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
......@@ -681,6 +682,10 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
reset_ubi_adpcm(vgmstream->codec_data);
}
if (vgmstream->coding_type == coding_IMUSE) {
reset_imuse(vgmstream->codec_data);
}
if (vgmstream->coding_type == coding_EA_MT) {
reset_ea_mt(vgmstream);
}
......@@ -860,6 +865,11 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
vgmstream->codec_data = NULL;
}
if (vgmstream->coding_type == coding_IMUSE) {
free_imuse(vgmstream->codec_data);
vgmstream->codec_data = NULL;
}
if (vgmstream->coding_type == coding_EA_MT) {
free_ea_mt(vgmstream->codec_data, vgmstream->channels);
vgmstream->codec_data = NULL;
......@@ -1146,6 +1156,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_NGC_DSP_subint:
return 14;
case coding_NGC_AFC:
case coding_VADPCM:
return 16;
case coding_NGC_DTK:
return 28;
......@@ -1301,6 +1312,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return (vgmstream->interleave_block_size - 0x05)*2 + 2;
case coding_UBI_ADPCM:
return 0; /* varies per mode */
case coding_IMUSE:
return 0; /* varies per frame */
case coding_EA_MT:
return 0; /* 432, but variable in looped files */
case coding_CIRCUS_VQ:
......@@ -1345,6 +1358,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_NGC_DSP_subint:
return 0x08 * vgmstream->channels;
case coding_NGC_AFC:
case coding_VADPCM:
return 0x09;
case coding_NGC_DTK:
return 0x20;
......@@ -1493,6 +1507,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return vgmstream->interleave_block_size;
case coding_UBI_ADPCM:
return 0; /* varies per mode? */
case coding_IMUSE:
return 0; /* varies per frame */
case coding_EA_MT:
return 0; /* variable (frames of bit counts or PCM frames) */
#ifdef VGM_USE_ATRAC9
......@@ -1708,6 +1724,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
}
break;
case coding_VADPCM: {
int order = vgmstream->codec_config;
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_vadpcm(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, order);
}
break;
}
case coding_PSX:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_psx(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
......@@ -2170,6 +2194,10 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
decode_ubi_adpcm(vgmstream, buffer+samples_written*vgmstream->channels, samples_to_do);
break;
case coding_IMUSE:
decode_imuse(vgmstream, buffer+samples_written*vgmstream->channels, samples_to_do);
break;
case coding_EA_MT:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_ea_mt(vgmstream, buffer+samples_written*vgmstream->channels+ch,
......@@ -2263,6 +2291,10 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) {
seek_ubi_adpcm(vgmstream->codec_data, vgmstream->loop_sample);
}
if (vgmstream->coding_type == coding_IMUSE) {
seek_imuse(vgmstream->codec_data, vgmstream->loop_sample);
}
if (vgmstream->coding_type == coding_EA_MT) {
seek_ea_mt(vgmstream, vgmstream->loop_sample);
}
......@@ -2828,8 +2860,11 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) {
* - opens its own streamfile from on a base one. One streamfile per channel may be open (to improve read/seeks).
* Should be called in metas before returning the VGMSTREAM.
*/
int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset) {
STREAMFILE * file = NULL;
int vgmstream_open_stream(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_offset) {
return vgmstream_open_stream_bf(vgmstream, sf, start_offset, 0);
}
int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_offset, int force_multibuffer) {
STREAMFILE* file = NULL;
char filename[PATH_LIMIT];
int ch;
int use_streamfile_per_channel = 0;
......@@ -2921,6 +2956,11 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
use_streamfile_per_channel = 1;
}
/* for hard-to-detect fixed offsets or full interleave */
if (force_multibuffer) {
use_streamfile_per_channel = 1;
}
/* for mono or codecs like IMA (XBOX, MS IMA, MS ADPCM) where channels work with the same bytes */
if (vgmstream->layout_type == layout_none) {
use_same_offset_per_channel = 1;
......@@ -2932,17 +2972,16 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
is_stereo_codec = 1;
}