diff --git a/.github/changelog.py b/.github/changelog.py index 18616c0c..49d5c9eb 100644 --- a/.github/changelog.py +++ b/.github/changelog.py @@ -46,15 +46,16 @@ def convert_git(stdout): def load_git(): if not USE_GIT: raise ValueError("git disabled") - + args = ['git', 'describe', '--tags', '--abbrev=0'] proc = subprocess.run(args, capture_output=True) if proc.returncode != 0: raise ValueError("git exception") latest_tag = proc.stdout.decode('utf-8').strip() - + + # no apparent portable way to get a utc timezone in date=format #args = ['git','--no-pager','log', '--merges', '--date=format:"%Y-%m-%d %H:%M:%S"', '--max-count', str(GIT_MAX_MERGES) ] - args = ['git','--no-pager','log', '--merges', '--date=format:"%Y-%m-%d %H:%M:%S"', '%s..HEAD' % (latest_tag)] + args = ['git','--no-pager','log', '--merges', '--date=format:"%Y-%m-%d %H:%M:%S %z"', '%s..HEAD' % (latest_tag)] proc = subprocess.run(args, capture_output=True) if proc.returncode != 0: raise ValueError("git exception") @@ -160,7 +161,7 @@ def get_lines(short_log=False): if short_log: lines = [] else: - curr_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + curr_date = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S %z") lines = [ '### CHANGELOG', '(latest changes from previous release, generated on %s)' % (curr_date), diff --git a/doc/FORMATS.md b/doc/FORMATS.md index ed321080..c583a181 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -420,10 +420,6 @@ different internally (encrypted, different versions, etc) and not always can be - CRI AIX header [*AIX*] - *aix*: `.aix` - Subfiles: *adx* -- **ngc_tydsp.c** - - .tydsp Header [*NGC_TYDSP*] - - *ngc_tydsp*: `.tydsp` - - Codecs: NGC_DSP - **wvs.c** - Swingin' Ape .WVS header [*WVS*] - *wvs_xbox*: `.wvs` @@ -500,9 +496,9 @@ different internally (encrypted, different versions, etc) and not always can be - *ngc_pdt*: `.pdt` - *ngc_pdt_split*: `.pdt` - Codecs: NGC_DSP -- **mus_krone.c** - - Krone .MUS header [*MUS_KRONE*] - - *mus_krone*: `.mus` +- **mus_krome.c** + - Krome .MUS header [*MUS_KROME*] + - *mus_krome*: `.mus` - Codecs: NGC_DSP - **dc_asd.c** - ASD Header [*DC_ASD*] @@ -662,10 +658,6 @@ different internally (encrypted, different versions, etc) and not always can be - **redspark.c** - RedSpark Header [*REDSPARK*] - Codecs: NGC_DSP -- **ivaud.c** - - Rockstar .ivaud header [*IVAUD*] - - *ivaud*: `.ivaud .(extensionless)` - - Codecs: PCM16LE XMA1 MPEG IMA_int - **ps2_sps.c** - Ape Escape 2 SPS Header [*PS2_SPS*] - *ps2_sps*: `.sps` @@ -862,7 +854,7 @@ different internally (encrypted, different versions, etc) and not always can be - Codecs: PCM16LE - **sgxd.c** - Sony SGXD header [*SGXD*] - - *sgxd*: `.sgb .sgx .sgd + .sgh .sgb` + - *sgxd*: `.sgb .sgd + .sgh .sgb` - Codecs: PCM16BE OGG_VORBIS PSX ATRAC3 PSX_cfg FFmpeg(various) - **wii_ras.c** - RAS header [*WII_RAS*] @@ -1040,9 +1032,9 @@ different internally (encrypted, different versions, etc) and not always can be - Microsoft XMA RIFF header [*XMA_RIFF*] - *xma*: `.xma .xma2 .wav .lwav .nps .str .kmx` - Codecs: XMA -- **sxd.c** - - Sony SXD header [*SXD*] - - *sxd*: `.sxd .sxd2 .sxd3 + .sxd1` +- **sndx.c** + - Sony SNDX header [*SNDX*] + - *sndx*: `.sxd .sxd2 .sxd3 + .sxd1` - Codecs: PSX HEVAG ATRAC9 - **ogl.c** - Shin'en OGL header [*OGL*] @@ -1793,7 +1785,10 @@ different internally (encrypted, different versions, etc) and not always can be - Torus SqueakStream header [*SQUEAKSTREAM*] - Torus SqueakSample header [*SQUEAKSAMPLE*] - *squeaksample*: `(base) + .asset .(external) .raw` - - Codecs: NGC_DSP PCM16LE PCM16BE PSX PCM8 MS_IMA IMA + - Codecs: NGC_DSP PCM16LE PCM16BE PSX PCM8 MS_IMA IMA XMA2 OGG_VORBIS SPEEX +- **snds.c** + - Sony SNDS header [*SNDS*] + - Codecs: ATRAC9 - **scd_pcm.c** - Lunar: Eternal Blue .PCM header [*SCD_PCM*] - *scd_pcm*: `.pcm` @@ -1826,6 +1821,10 @@ different internally (encrypted, different versions, etc) and not always can be - Tiger Game.com .4 header [*TGC*] - *tgc*: `.4` - Codecs: TGC +- **ivaud.c** + - Rockstar .ivaud header [*IVAUD*] + - *ivaud*: `.ivaud .(extensionless)` + - Codecs: PCM16LE XMA1 MPEG IMA_int - **pos.c** - RIFF WAVE header (.pos looping) [*RIFF_WAVE_POS*] - *pos*: `.pos + .wav` diff --git a/src/coding/coding.h b/src/coding/coding.h index aa52ce7d..c41f7f5b 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -588,6 +588,7 @@ void free_celt_fsb(celt_codec_data* data); typedef struct speex_codec_data speex_codec_data; speex_codec_data* init_speex_ea(int channels); +speex_codec_data* init_speex_torus(int channels); void decode_speex(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do); void reset_speex(speex_codec_data* data); void seek_speex(VGMSTREAM* vgmstream, int32_t num_sample); diff --git a/src/coding/speex_decoder.c b/src/coding/speex_decoder.c index 5bac1038..85186f0f 100644 --- a/src/coding/speex_decoder.c +++ b/src/coding/speex_decoder.c @@ -10,15 +10,19 @@ #define SPEEX_DECODE_OK 0 /* -1 for end of stream, -2 corrupt stream */ +typedef enum { EA, TORUS } type_t; + /* opaque struct */ struct speex_codec_data { + type_t type; + /* config */ int channels; int samples_discard; int encoder_delay; uint8_t buf[SPEEX_MAX_FRAME_SIZE]; - uint8_t frame_size; + int frame_size; int16_t* samples; int frame_samples; @@ -32,7 +36,7 @@ struct speex_codec_data { /* raw SPEEX */ -speex_codec_data* init_speex_ea(int channels) { +static speex_codec_data* init_speex(type_t type, int channels) { int res, sample_rate; speex_codec_data* data = NULL; @@ -40,7 +44,9 @@ speex_codec_data* init_speex_ea(int channels) { data = calloc(1, sizeof(speex_codec_data)); if (!data) goto fail; - //TODO: EA uses N decoders, unknown layout (known samples are mono) + data->type = type; + + //TODO: unknown layout (known samples are mono, EA: N decoders, Torus: N too?) data->channels = channels; if (channels != 1) goto fail; @@ -78,6 +84,14 @@ fail: return NULL; } +speex_codec_data* init_speex_ea(int channels) { + return init_speex(EA, channels); +} + +speex_codec_data* init_speex_torus(int channels) { + return init_speex(TORUS, channels); +} + static int decode_frame(speex_codec_data* data) { int res; @@ -102,8 +116,18 @@ fail: static int read_frame(speex_codec_data* data, VGMSTREAMCHANNEL* stream) { size_t bytes; - data->frame_size = read_u8(stream->offset, stream->streamfile); - stream->offset += 0x01; + switch(data->type) { + case EA: + data->frame_size = read_u8(stream->offset, stream->streamfile); + stream->offset += 0x01; + break; + case TORUS: + data->frame_size = read_u16le(stream->offset, stream->streamfile); + stream->offset += 0x02; + break; + default: + break; + } if (data->frame_size == 0) goto fail; bytes = read_streamfile(data->buf, stream->offset, data->frame_size, stream->streamfile); diff --git a/src/formats.c b/src/formats.c index 72f94223..c15c82b6 100644 --- a/src/formats.c +++ b/src/formats.c @@ -498,7 +498,6 @@ static const char* extension_list[] = { "sgb", "sgd", "sgt", - "sgx", "slb", //txth/reserved [THE Nekomura no Hitobito (PS2)] "sli", "smc", @@ -559,10 +558,10 @@ static const char* extension_list[] = { "tmx", "tra", "trk", + "trs", //txth/semi [Kamiwaza (PS2), Shinobido (PS2)] "tun", "txth", "txtp", - "tydsp", "u0", "ue4opus", @@ -1073,7 +1072,6 @@ static const meta_info meta_info_list[] = { {meta_PS2_VAS, "Konami .VAS header"}, {meta_LP_AP_LEP, "Konami LP/AP/LEP header"}, {meta_SDT, "High Voltage .sdt header"}, - {meta_NGC_TYDSP, ".tydsp Header"}, {meta_WVS, "Swingin' Ape .WVS header"}, {meta_DEC, "Falcom .DEC RIFF header"}, {meta_VS, "Melbourne House .VS header"}, @@ -1088,7 +1086,7 @@ static const meta_info meta_info_list[] = { {meta_YMF, "Yuke's .YMF Header"}, {meta_FAG, "Radical .FAG Header"}, {meta_PS2_MIHB, "Sony MultiStream MIC header"}, - {meta_MUS_KRONE, "Krone .MUS header"}, + {meta_MUS_KROME, "Krome .MUS header"}, {meta_WII_SNG, "SNG DSP Header"}, {meta_RSD, "Radical RSD header"}, {meta_DC_ASD, "ASD Header"}, @@ -1242,7 +1240,7 @@ static const meta_info meta_info_list[] = { {meta_ASTB, "Capcom ASTB header"}, {meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"}, {meta_UBI_RAKI, "Ubisoft RAKI header"}, - {meta_SXD, "Sony SXD header"}, + {meta_SNDX, "Sony SNDX header"}, {meta_OGL, "Shin'en OGL header"}, {meta_MC3, "Paradigm MC3 header"}, {meta_GHS, "Hexadrive GHS/S_P_STH header"}, @@ -1412,6 +1410,7 @@ static const meta_info meta_info_list[] = { {meta_AWD, "RenderWare Audio Wave Dictionary header"}, {meta_SQUEAKSTREAM, "Torus SqueakStream header"}, {meta_SQUEAKSAMPLE, "Torus SqueakSample header"}, + {meta_SNDS, "Sony SNDS header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index c3145a54..af435628 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -175,6 +175,7 @@ + @@ -502,7 +503,7 @@ - + @@ -523,7 +524,6 @@ - @@ -627,6 +627,8 @@ + + @@ -651,7 +653,6 @@ - @@ -737,6 +738,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index d67ac7cd..e7cde615 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -350,6 +350,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -1327,7 +1330,7 @@ meta\Source Files - + meta\Source Files @@ -1390,9 +1393,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1702,6 +1702,12 @@ meta\Source Files + + meta\Source Files + + + meta\Source Files + meta\Source Files @@ -1774,9 +1780,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -2032,6 +2035,9 @@ util\Source Files + + util\Source Files + util\Source Files diff --git a/src/meta/ivaud.c b/src/meta/ivaud.c index 43113eac..13ed4888 100644 --- a/src/meta/ivaud.c +++ b/src/meta/ivaud.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" +#include "../util/endianness.h" typedef struct { int is_music; @@ -31,13 +32,13 @@ VGMSTREAM* init_vgmstream_ivaud(STREAMFILE* sf) { int loop_flag; /* checks */ - /* (hashed filenames are likely extensionless and .ivaud is added by tools) */ + /* (hashed filenames are likely extensionless, .ivaud is added by tools) */ if (!check_extensions(sf, "ivaud,")) - goto fail; + return NULL; /* check header */ if (!parse_ivaud_header(sf, &ivaud)) - goto fail; + return NULL; loop_flag = 0; @@ -121,9 +122,9 @@ fail: /* Parse Rockstar's .ivaud header (much info from SparkIV). */ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { int target_subsong = sf->stream_index; - uint64_t (*read_u64)(off_t,STREAMFILE*); - uint32_t (*read_u32)(off_t,STREAMFILE*); - uint16_t (*read_u16)(off_t,STREAMFILE*); + read_u64_t read_u64; + read_u32_t read_u32; + read_u16_t read_u16; ivaud->big_endian = read_u32be(0x00, sf) == 0; /* table offset at 0x04 > BE (64b) */ @@ -131,6 +132,10 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { read_u32 = ivaud->big_endian ? read_u32be : read_u32le; read_u16 = ivaud->big_endian ? read_u16be : read_u16le; + uint64_t table_offset = read_u64(0x00,sf); + if (table_offset > 0x10000) /* arbitrary max, typically 0x1c~0x1000 */ + return 0; + /* use bank's stream count to detect */ ivaud->is_music = (read_u32(0x10,sf) == 0); @@ -138,7 +143,7 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { off_t block_table_offset, channel_table_offset, channel_info_offset; /* music header */ - block_table_offset = read_u64(0x00,sf); + block_table_offset = table_offset; ivaud->block_count = read_u32(0x08,sf); ivaud->block_size = read_u32(0x0c,sf); /* uses padded blocks */ /* 0x10(4): stream count */ @@ -185,7 +190,7 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { off_t stream_table_offset, stream_info_offset, stream_entry_offset, offset; /* bank header */ - stream_table_offset = read_u64(0x00,sf); + stream_table_offset = table_offset; /* 0x08(8): header size? start offset? */ ivaud->total_subsongs = read_u32(0x10,sf); /* 0x14(4): unknown */ diff --git a/src/meta/meta.h b/src/meta/meta.h index e678c971..56ca00f7 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -257,8 +257,6 @@ VGMSTREAM * init_vgmstream_sdt(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_aix(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ngc_tydsp(STREAMFILE * streamFile); - VGMSTREAM* init_vgmstream_wvs_xbox(STREAMFILE* sf); VGMSTREAM* init_vgmstream_wvs_ngc(STREAMFILE* sf); @@ -298,7 +296,7 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile); -VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_mus_krome(STREAMFILE* sf); VGMSTREAM * init_vgmstream_rsd(STREAMFILE * streamFile); @@ -574,7 +572,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_pasx(STREAMFILE* sf); -VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_sndx(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile); @@ -981,5 +979,6 @@ VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf); VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf); VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_snds(STREAMFILE* sf); #endif /*_META_H*/ diff --git a/src/meta/mus_krone.c b/src/meta/mus_krome.c similarity index 87% rename from src/meta/mus_krone.c rename to src/meta/mus_krome.c index de14948e..c59d84b0 100644 --- a/src/meta/mus_krone.c +++ b/src/meta/mus_krome.c @@ -3,8 +3,8 @@ #include "../coding/coding.h" -/* .mus - from Star Wars: The Force Unleashed (Wii) */ -VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf) { +/* .mus - from Krome games [Ty: The Tasmanian Tiger 2 (GC), Star Wars: The Force Unleashed (Wii)] */ +VGMSTREAM* init_vgmstream_mus_krome(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; uint32_t start_offset, data_size; int channels, loop_flag, interleave; @@ -36,7 +36,7 @@ VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_MUS_KRONE; + vgmstream->meta_type = meta_MUS_KROME; vgmstream->num_samples = num_samples; vgmstream->sample_rate = read_u16be(0x6c,sf); diff --git a/src/meta/ngc_tydsp.c b/src/meta/ngc_tydsp.c deleted file mode 100644 index 37f3a603..00000000 --- a/src/meta/ngc_tydsp.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* TYDSP (Ty - The Tasmanian Tiger) */ -VGMSTREAM * init_vgmstream_ngc_tydsp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("tydsp",filename_extension(filename))) goto fail; - - loop_flag = 1; - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitBE(0x08,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = (uint16_t)(read_16bitBE(0x6C,streamFile)); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = read_32bitBE(0x00,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitBE(0x00,streamFile); - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile); - vgmstream->meta_type = meta_NGC_TYDSP; - - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+i*2,streamFile); - } - if (vgmstream->channels) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x3E +i*2,streamFile); - } - } - } - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/sdrh.c b/src/meta/sdrh.c index 88d43035..72b04a6a 100644 --- a/src/meta/sdrh.c +++ b/src/meta/sdrh.c @@ -216,6 +216,7 @@ VGMSTREAM* init_vgmstream_sdrh_old(STREAMFILE* sf) { * 0x30: file name in a custom 40-char (RADIX style) encoding * others: ? (change in old/new) */ + /* there is also an older version in Shadow Hearts 2, more basic (no section table) and may contain sequences */ /* parse section */ { diff --git a/src/meta/sgxd.c b/src/meta/sgxd.c index c16c53a2..a0ff7135 100644 --- a/src/meta/sgxd.c +++ b/src/meta/sgxd.c @@ -3,16 +3,15 @@ #include "../util/chunks.h" -/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */ +/* SGXD - Sony/SCEI's SGX lib (cousin of RXWS) */ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* sf_head = NULL; STREAMFILE* sf_body = NULL; off_t start_offset, data_offset, chunk_offset, name_offset = 0; size_t stream_size; - uint32_t base1_offset, base2_offset, base3_offset; - - int is_sgx, is_sgd = 0; + uint32_t /*base1_offset,*/ base2_offset, base3_offset; + int is_sgd = 0; int loop_flag, channels, codec, sample_rate; int32_t num_samples, loop_start_sample, loop_end_sample; int total_subsongs, target_subsong = sf->stream_index; @@ -28,35 +27,31 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { } if (!is_id32be(0x00,sf_head, "SGXD")) - goto fail; + return NULL; /* checks */ - /* .sgx: header+data (Genji) - * .sgd: header+data (common) + /* .sgd: header+data (common) * .sgh+sgd: header+data (streams) */ - if (!check_extensions(sf,"sgx,sgd,sgb")) - goto fail; + if (!check_extensions(sf,"sgd,sgb")) + return NULL; /* SGXD base (size 0x10), always LE even on PS3 */ - /* 0x04: SGX = full header size - SGD/SGH = bank name offset (part of NAME table, usually same as filename) */ - /* 0x08: SGX = first chunk offset? (0x10) - SGD/SGH = full header size */ - /* 0x0c: SGX/SGH = full data size with padding / - SGD = full data size ^ (1<<31) with padding */ - base1_offset = read_u32le(0x04, sf_head); + /* 0x04: SGD/SGH = bank name offset (part of NAME table, usually same as filename) */ + /* 0x08: SGD/SGH = full header size */ + /* 0x0c: SGH = full data size with padding + * SGD = full data size ^ (1<<31) with padding */ + //base1_offset = read_u32le(0x04, sf_head); base2_offset = read_u32le(0x08, sf_head); base3_offset = read_u32le(0x0c, sf_head); - is_sgx = base2_offset == 0x10; /* fixed size */ is_sgd = base3_offset & (1 << 31); /* flag */ /* Ogg SGXD don't have flag (probably due to codec hijack, or should be split), allow since it's not so obvious */ - if (!(is_sgx || is_sgd) && get_streamfile_size(sf_head) != base2_offset) /* sgh but wrong header size must be sgd */ + if (!(is_sgd) && get_streamfile_size(sf_head) != base2_offset) /* sgh but wrong header size must be sgd */ is_sgd = 1; /* for plugins that start with .sgh (and don't check extensions) */ - if (!(is_sgx || is_sgd) && sf == sf_head) { + if (!(is_sgd) && sf == sf_head) { sf_body = open_streamfile_by_ext(sf, "sgb"); if (!sf_body) goto fail; } @@ -65,9 +60,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { } - if (is_sgx) { - data_offset = base1_offset; - } else if (is_sgd) { + if (is_sgd) { data_offset = base2_offset; } else { data_offset = 0x00; @@ -76,7 +69,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { /* Format per chunk: * - 0x00: id - * - 0x04: SGX: unknown; SGD/SGH: chunk length + * - 0x04: chunk length * - 0x08: null * - 0x0c: entries */ @@ -103,14 +96,8 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { * - BUSS: bus config? */ /* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */ - if (is_sgx) { /* position after chunk+size */ - if (!is_id32be(0x10,sf_head, "WAVE")) - goto fail; - chunk_offset = 0x18; - } else { - if (!find_chunk_le(sf_head, get_id32be("WAVE"),0x10,0, &chunk_offset, NULL)) - goto fail; - } + if (!find_chunk_le(sf_head, get_id32be("WAVE"),0x10,0, &chunk_offset, NULL)) + goto fail; /* check multi-streams (usually only SE containers; Puppeteer) */ total_subsongs = read_s32le(chunk_offset+0x04,sf_head); @@ -123,8 +110,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/ /* 0x00: ? (00/01/02) */ - if (!is_sgx) /* meaning unknown in .sgx; offset 0 = not a stream (a RGND sample) */ - name_offset = read_u32le(chunk_offset+0x04,sf_head); + name_offset = read_u32le(chunk_offset+0x04,sf_head); codec = read_u8(chunk_offset+0x08,sf_head); channels = read_u8(chunk_offset+0x09,sf_head); /* 0x0a: null */ @@ -141,13 +127,9 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { loop_end_sample = read_s32le(chunk_offset+0x28,sf_head); stream_size = read_u32le(chunk_offset+0x2c,sf_head); /* stream size (without padding) / interleave (for type3) */ - if (is_sgx) { - stream_offset = 0x0; - } else{ - stream_offset = read_u32le(chunk_offset+0x30,sf_head); - } - /* 0x34: SGX = unknown - * SGD/SGH = stream size (with padding) / interleave */ + stream_offset = read_u32le(chunk_offset+0x30,sf_head); + + /* 0x34: SGD/SGH = stream size (with padding) / interleave */ loop_flag = loop_start_sample != -1 && loop_end_sample != -1; start_offset = data_offset + stream_offset; diff --git a/src/meta/snds.c b/src/meta/snds.c new file mode 100644 index 00000000..bb5ec7c2 --- /dev/null +++ b/src/meta/snds.c @@ -0,0 +1,112 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util/chunks.h" + + +/* SSDD - Sony/SCE's SNDS lib format (cousin of SGXD/SNDX) */ +VGMSTREAM* init_vgmstream_snds(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t stream_offset, stream_size; + int loop_flag, channels, codec, sample_rate; + int32_t num_samples, loop_start, loop_end, encoder_delay; + uint32_t at9_config = 0; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!is_id32be(0x00, sf, "SSDD")) + return NULL; + + if (read_u32le(0x04, sf) != get_streamfile_size(sf)) + return NULL; + /* 0x10: file name */ + + /* (extensionless): no apparent extension in debug strings, though comparing other SCE libs possibly ".ssd" */ + if (!check_extensions(sf,"")) + return NULL; + + /* from debug info seems to have free chunks but known files always use the same and 1 subsong */ + off_t base_offset = 0x60, wavs_offset = 0; + if (!find_chunk_le(sf, get_id32be("WAVS"),base_offset,0, &wavs_offset,NULL)) + return NULL; + + if (read_u16le(wavs_offset + 0x00, sf) != 0x2c) /* entry size? */ + return NULL; + + total_subsongs = read_s16le(wavs_offset + 0x02, sf); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) return NULL; + if (total_subsongs != 1) return NULL; /* not seen */ + + /* read stream header */ + { + uint32_t head_offset = wavs_offset + 0x04 + 0x2c * (target_subsong - 1); + /* 0x00: null/flags? */ + /* 0x04: null/offset? */ + /* 0x0c: null/offset? */ + codec = read_u8(head_offset + 0x0c, sf); + channels = read_u16le(head_offset + 0x0d, sf); + /* 0x0e: null? */ + sample_rate = read_u32le(head_offset + 0x10, sf); + at9_config = read_u32le(head_offset + 0x14, sf); /* !!! (only known use of this lib is Android/iOS) */ + num_samples = read_s32le(head_offset + 0x18, sf); + loop_start = read_s32le(head_offset + 0x1c, sf); + loop_end = read_s32le(head_offset + 0x20, sf); + encoder_delay = read_s32le(head_offset + 0x24, sf); + stream_size = read_u32le(head_offset + 0x28, sf); + + loop_flag = loop_end > 0; + } + + /* CUES chunk: cues (various fields, also names) */ + /* CUNS chunk: cue names (flags + hash + offset, then names) */ + + off_t wavd_offset = 0; + if (!find_chunk_le(sf, get_id32be("WAVD"),wavs_offset - 0x08,0, &wavd_offset,NULL)) + return NULL; + stream_offset = wavd_offset + 0x08; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_SNDS; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + switch (codec) { +#ifdef VGM_USE_ATRAC9 + case 0x41: { + atrac9_config cfg = {0}; + + cfg.channels = channels; + cfg.config_data = at9_config; + cfg.encoder_delay = encoder_delay; + + vgmstream->codec_data = init_atrac9(&cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_ATRAC9; + vgmstream->layout_type = layout_none; + break; + } +#endif + default: + VGM_LOG("SNDS: unknown codec 0x%x\n", codec); + goto fail; + } + + /* open the file for reading */ + if (!vgmstream_open_stream(vgmstream, sf, stream_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/sxd.c b/src/meta/sndx.c similarity index 97% rename from src/meta/sxd.c rename to src/meta/sndx.c index 4cbd97fc..798990cd 100644 --- a/src/meta/sxd.c +++ b/src/meta/sndx.c @@ -3,8 +3,8 @@ #include "../util/chunks.h" -/* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */ -VGMSTREAM* init_vgmstream_sxd(STREAMFILE* sf) { +/* SXDF/SXDS - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */ +VGMSTREAM* init_vgmstream_sndx(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* sf_sxd1 = NULL, *sf_sxd2 = NULL, *sf_data = NULL, *sf_h = NULL, *sf_b = NULL; off_t start_offset, chunk_offset, first_offset = 0x60, name_offset = 0; @@ -180,7 +180,7 @@ VGMSTREAM* init_vgmstream_sxd(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_SXD; + vgmstream->meta_type = meta_SNDX; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = num_samples; diff --git a/src/meta/squeak.c b/src/meta/squeak.c index 5e283e0f..710d416a 100644 --- a/src/meta/squeak.c +++ b/src/meta/squeak.c @@ -2,9 +2,10 @@ #include "../layout/layout.h" #include "../coding/coding.h" #include "../util/endianness.h" +#include "../util/layout_utils.h" -#define SQUEAK_MAX_CHANNELS 8 /* seen 3 in some voices */ -typedef enum { PCM16LE, PCM16BE, PCM8, DSP, PSX, MSIMA, IMA } squeak_type_t; +#define SQUEAK_MAX_CHANNELS 6 /* seen 3 in some voices */ +typedef enum { PCM16LE, PCM16BE, PCM8, DSP, PSX, MSIMA, IMA, XMA2, VORBIS, SPEEX } squeak_type_t; typedef struct { squeak_type_t type; @@ -26,6 +27,8 @@ typedef struct { uint32_t coef_offset; uint32_t coef_spacing; + uint32_t data_offsets[SQUEAK_MAX_CHANNELS]; + uint32_t coef_offsets[SQUEAK_MAX_CHANNELS]; uint32_t data_size; bool big_endian; @@ -37,22 +40,21 @@ typedef struct { static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h); -/* SqueakStream - from Torus games (as identified in .hnk subdirs) */ +/* SqueakStream - from Torus games (name/engine as identified in .hnk subdirs) */ VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) { squeak_header_t h = {0}; bool is_old = false; /* checks */ - h.big_endian = false; - if (is_id32be(0x00,sf, "RAWI")) { - h.big_endian = false; + if (is_id32be(0x00,sf, "RAWI") || is_id32be(0x00,sf, "VORB") || is_id32be(0x00,sf, "SPEX")) { + h.big_endian = false; /* VORB/SPEX only use vorbis/speex but no apparent diffs */ } else if (is_id32be(0x00,sf, "IWAR")) { h.big_endian = true; /* Wii/PS3/X360 */ } else { - /* no header id so test codec in dumb endian */ + /* no header id in early version so test codec in dumb endian */ if ((read_u32le(0x00,sf) & 0x00FFFFFF) > 9 || (read_u32be(0x00,sf) & 0x00FFFFFF) > 9) return NULL; is_old = true; @@ -137,13 +139,17 @@ VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) { if (h.extb_offset > h.name_offset) return NULL; switch(h.codec) { - case 0x00: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */ - case 0x01: h.type = PCM16LE; break; /* Falling Skies The Game (PC) */ - case 0x02: h.type = PCM16BE; break; /* Falling Skies The Game (X360) */ - case 0x03: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ - case 0x05: h.type = PCM8; break; /* Scooby Doo and the Spooky Swamp (DS), Scooby Doo! First Frights (DS) */ - case 0x09: h.type = MSIMA; break; /* Turbo Super Stunt Squad (DS) */ + case 0x00: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */ + case 0x01: h.type = PCM16LE; break; /* Falling Skies The Game (PC) */ + case 0x02: h.type = h.big_endian ? PCM16BE : PCM16LE; break; /* Falling Skies The Game (X360)-be, Scooby Doo and the Spooky Swamp (PC)-le */ + case 0x03: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ + case 0x04: h.type = MSIMA; break; /* Barbie Dreamhouse Party (DS) */ + case 0x05: h.type = PCM8; break; /* Scooby Doo and the Spooky Swamp (DS), Scooby Doo! First Frights (DS) */ + case 0x07: h.type = SPEEX; break; /* Scooby Doo and the Spooky Swamp (PC) */ + case 0x08: h.type = VORBIS; break; /* Scooby Doo and the Spooky Swamp (PC) */ + case 0x09: h.type = MSIMA; break; /* Turbo Super Stunt Squad (DS) */ default: + VGM_LOG("SqueakStream: unknown codec %x\n", h.codec); return NULL; } @@ -151,7 +157,7 @@ VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) { } -/* SqueakSample - from Torus games (as identified in .hnk subdirs) */ +/* SqueakSample - from Torus games (name/engine as identified in .hnk subdirs) */ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { squeak_header_t h = {0}; @@ -187,7 +193,6 @@ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { h.loop_end = read_s32(offset + 0x0c,sf); if (h.loop_start > h.loop_end || h.loop_end > h.num_samples) return NULL; h.codec = read_s32(offset + 0x10,sf); - if (h.codec > 0x09) return NULL; h.sample_rate = read_s32(offset + 0x14,sf); if (h.sample_rate > 48000 || h.sample_rate < 0) return NULL; @@ -206,14 +211,25 @@ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { h.external_data = (h.data_offset & 0xF0000000); h.data_offset = h.data_offset & 0x0FFFFFFF; - /* absolute offsets, should read for each channel but simplify - * (also channels may have padding, but files end with no padding) */ - if (h.channels > 1) { - int separation = h.codec == 0xFFFE0001 ? 0x68 : 0x2c; - uint32_t data_offset = read_u32le(offset + 0x04 + 1 * separation, sf) & 0x0FFFFFFF; - uint32_t coef_offset = read_u32le(offset + 0x28 + 1 * separation, sf); - h.interleave = data_offset - h.data_offset; /* distance */ - h.coef_spacing = coef_offset - h.coef_offset; + /* each channel has its own info but mostly repeats (data may have padding, but files end with no padding) */ + { + int separation = 0; + switch(h.codec) { + case 0xFFFE0001: + case 0x0001FFFE: + case 0x01660001: separation = 0x68; break; + default: separation = 0x2c; break; + } + + for (int i = 0; i < h.channels; i++) { + h.data_offsets[i] = read_u32le(offset + 0x04 + i * separation, sf) & 0x0FFFFFFF; + h.coef_offsets[i] = read_u32le(offset + 0x28 + i * separation, sf); + } + + if (h.channels > 1) { + h.interleave = h.data_offsets[1] - h.data_offsets[0]; + h.coef_spacing = h.coef_offsets[1] - h.coef_offsets[0]; + } } switch(h.codec) { @@ -223,8 +239,11 @@ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { case 0x07: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ case 0x08: /* (same as below for unlooped audio) */ case 0x09: h.type = IMA; break; /* Scooby-Doo! First Frights (DS), Turbo Super Stunt Squad (DS) */ - case 0xFFFE0001: h.type = h.big_endian ? PCM16BE : PCM16LE; break; /* Falling Skies The Game (X360) */ + case 0xFFFE0001: h.type = PCM16BE; break; /* Falling Skies The Game (X360) */ + case 0x0001FFFE: h.type = PCM16LE; break; /* Scooby Doo and the Spooky Swamp (PC), Monster High: New Ghoul in School (PC) */ + case 0x01660001: h.type = XMA2; break; /* Rise of the Guardians (X360) */ default: + VGM_LOG("SqueakSample: unknown codec %x\n", h.codec); return NULL; } @@ -295,6 +314,7 @@ fail: static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h) { VGMSTREAM* vgmstream = NULL; STREAMFILE* sb = NULL; + STREAMFILE* sf_body = NULL; /* common */ int loop_flag = h->loop_end > 0; @@ -306,6 +326,7 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* if (!sb) goto fail; } + sf_body = sb ? sb : sf; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(h->channels, loop_flag); @@ -334,12 +355,13 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = h->interleave; /* not 0x02 */ + break; + case PCM16BE: vgmstream->coding_type = coding_PCM16BE; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = h->interleave; /* not 0x02 */ - /* etbl_offset may set offsets to RIFF fmts per channel) */ break; case PSX: @@ -358,7 +380,7 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* vgmstream->coding_type = coding_MS_IMA; vgmstream->layout_type = layout_none; //vgmstream->interleave_block_size = h->interleave; /* unused? (mono) */ - vgmstream->frame_size = 0x20; + vgmstream->frame_size = h->codec == 0x04 ? 0x400 : 0x20; break; case IMA: @@ -370,8 +392,46 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h->data_offset += 0x04; break; +#ifdef VGM_USE_FFMPEG + case XMA2: { + /* uses separate mono streams */ + vgmstream->coding_type = coding_FFmpeg; + for (int i = 0; i < h->channels; i++) { + uint32_t offset = h->data_offsets[i]; + uint32_t next_offset = (i + 1 == h->channels) ? get_streamfile_size(sf_body) : h->data_offsets[i+1]; + uint32_t data_size = next_offset - offset; + int layer_channels = 1; + + vgmstream->codec_data = init_ffmpeg_xma2_raw(sf_body, offset, data_size, h->num_samples, layer_channels, h->sample_rate, 0, 0); + if (!layered_add_codec(vgmstream, 0, layer_channels)) + goto fail; + } + if (!layered_add_done(vgmstream)) + goto fail; + + break; + } +#endif +#ifdef VGM_USE_VORBIS + case VORBIS: + vgmstream->codec_data = init_ogg_vorbis(sf_body, h->data_offset, 0, NULL); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_OGG_VORBIS; + vgmstream->layout_type = layout_none; + + break; +#endif +#ifdef VGM_USE_SPEEX + case SPEEX: { + vgmstream->codec_data = init_speex_torus(h->channels); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_SPEEX; + vgmstream->layout_type = layout_none; + + break; + } +#endif default: - vgm_logi("RAWI: unknown codec %x (report)\n", h->codec); goto fail; } diff --git a/src/util/endianness.h b/src/util/endianness.h index ef67ef05..ab95f352 100644 --- a/src/util/endianness.h +++ b/src/util/endianness.h @@ -1,10 +1,12 @@ -#ifndef _UTIL_ENDIAN_H -#define _UTIL_ENDIAN_H +#ifndef _ENDIANNESS_H +#define _ENDIANNESS_H #include "../streamfile.h" #include "reader_get.h" #include "reader_sf.h" +typedef uint64_t (*read_u64_t)(off_t, STREAMFILE*); +typedef int64_t (*read_s64_t)(off_t, STREAMFILE*); typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*); typedef int32_t (*read_s32_t)(off_t, STREAMFILE*); typedef uint16_t (*read_u16_t)(off_t, STREAMFILE*); diff --git a/src/util/layout_utils.c b/src/util/layout_utils.c new file mode 100644 index 00000000..70d39358 --- /dev/null +++ b/src/util/layout_utils.c @@ -0,0 +1,71 @@ +#include "layout_utils.h" + +#include "../vgmstream.h" +#include "../layout/layout.h" + +bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) { + if (!vs || !vs->codec_data) { + goto fail; + } + + if (!layer_channels) + layer_channels = 1; + if (!layers) + layers = vs->channels / layer_channels; + + int i; + layered_layout_data* data; + + switch(vs->layout_type) { + case layout_segmented: //to be improved + goto fail; + + case layout_layered: + data = vs->layout_data; + + i = data->curr_layer; + break; + + default: + data = init_layout_layered(layers); + if (!data) goto fail; + vs->layout_data = data; + vs->layout_type = layout_layered; + + i = 0; + break; + } + + data->layers[i] = allocate_vgmstream(layer_channels, vs->loop_flag); + if (!data->layers[i]) goto fail; + + data->layers[i]->meta_type = vs->meta_type; + data->layers[i]->sample_rate = vs->sample_rate; + data->layers[i]->num_samples = vs->num_samples; + data->layers[i]->loop_start_sample = vs->loop_start_sample; + data->layers[i]->loop_end_sample = vs->loop_end_sample; + + data->layers[i]->codec_data = vs->codec_data; + if (!data->layers[i]->codec_data) goto fail; + data->layers[i]->coding_type = vs->coding_type; + data->layers[i]->layout_type = layout_none; + + vs->codec_data = NULL; /* moved to layer, don't hold it */ + + data->curr_layer++; + + return true; +fail: + return false; +} + +bool layered_add_done(VGMSTREAM* vs) { + //TODO: some extra checks/setup? + + if (!setup_layout_layered(vs->layout_data)) + goto fail; + + return true; +fail: + return false; +} diff --git a/src/util/layout_utils.h b/src/util/layout_utils.h new file mode 100644 index 00000000..d5247219 --- /dev/null +++ b/src/util/layout_utils.h @@ -0,0 +1,12 @@ +#ifndef _LAYOUTS_UTIL_H +#define _LAYOUTS_UTIL_H + +#include "../vgmstream.h" + +/* add a new layer from codec data (setups layout if needed) + * codec is passed in the vs for easier free/etc control */ +bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels); + +/* call when done adding layers */ +bool layered_add_done(VGMSTREAM* vs); +#endif diff --git a/src/vgmstream.c b/src/vgmstream.c index 745f3b96..9cc129f0 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -103,7 +103,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_lp_ap_lep, init_vgmstream_sdt, init_vgmstream_aix, - init_vgmstream_ngc_tydsp, init_vgmstream_wvs_xbox, init_vgmstream_wvs_ngc, init_vgmstream_dc_str, @@ -129,7 +128,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_mihb, init_vgmstream_ngc_pdt_split, init_vgmstream_ngc_pdt, - init_vgmstream_mus_krone, + init_vgmstream_mus_krome, init_vgmstream_dc_asd, init_vgmstream_spsd, init_vgmstream_rsd, @@ -170,7 +169,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_zsd, init_vgmstream_vgs_ps, init_vgmstream_redspark, - init_vgmstream_ivaud, init_vgmstream_wii_wsd, init_vgmstream_dsp_ndp, init_vgmstream_ps2_sps, @@ -284,7 +282,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ubi_raki, init_vgmstream_pasx, init_vgmstream_xma, - init_vgmstream_sxd, + init_vgmstream_sndx, init_vgmstream_ogl, init_vgmstream_mc3, init_vgmstream_ghs, @@ -523,6 +521,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_pwb, init_vgmstream_squeakstream, init_vgmstream_squeaksample, + init_vgmstream_snds, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, @@ -533,6 +532,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_mic_koei, init_vgmstream_seb, init_vgmstream_tgc, + init_vgmstream_ivaud, /* need companion files */ init_vgmstream_pos, init_vgmstream_sli_loops, diff --git a/src/vgmstream.h b/src/vgmstream.h index 9038f404..65854119 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -273,6 +273,7 @@ typedef struct { int input_channels; /* internal buffer channels */ int output_channels; /* resulting channels (after mixing, if applied) */ int external_looping; /* don't loop using per-layer loops, but layout's own looping */ + int curr_layer; /* helper */ } layered_layout_data; diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index fed12908..64ded87e 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -257,7 +257,7 @@ typedef enum { meta_DSP_SADB, /* .sad */ meta_DSP_WSI, /* .wsi */ meta_IDSP_TT, /* Traveller's Tales games */ - meta_MUS_KRONE, + meta_MUS_KROME, meta_DSP_WII_WSD, /* Phantom Brave (WII) */ meta_WII_NDP, /* Vertigo (Wii) */ meta_DSP_YGO, /* Konami: Yu-Gi-Oh! The Falsebound Kingdom (NGC), Hikaru no Go 3 (NGC) */ @@ -344,7 +344,6 @@ typedef enum { meta_PS2_VAS, /* Pro Baseball Spirits 5 */ meta_LP_AP_LEP, meta_SDT, /* Baldur's Gate - Dark Alliance */ - meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */ meta_DC_STR, /* SEGA Stream Asset Builder */ meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */ meta_SAP, @@ -529,7 +528,7 @@ typedef enum { meta_ASTB, meta_WWISE_RIFF, /* Audiokinetic Wwise RIFF/RIFX */ meta_UBI_RAKI, /* Ubisoft RAKI header (Rayman Legends, Just Dance 2017) */ - meta_SXD, /* Sony SXD (Gravity Rush, Freedom Wars PSV) */ + meta_SNDX, meta_OGL, /* Shin'en Wii/WiiU (Jett Rocket (Wii), FAST Racing NEO (WiiU)) */ meta_MC3, /* Paradigm games (T3 PS2, MX Rider PS2, MI: Operation Surma PS2) */ meta_GHS, @@ -537,7 +536,7 @@ typedef enum { meta_MTA2, meta_XA_XA30, meta_XA_04SW, - meta_TXTH, /* generic text header */ + meta_TXTH, meta_SK_AUD, /* Silicon Knights .AUD (Eternal Darkness GC) */ meta_AHX, meta_STMA, @@ -700,6 +699,7 @@ typedef enum { meta_AWD, meta_SQUEAKSTREAM, meta_SQUEAKSAMPLE, + meta_SNDS, } meta_t;