Merge pull request #1361 from bnnm/fsbopus-txth

- Add FSB Opus [LEGO 2K Drive (Switch)]
- Add TXTH experimental 'subsong_sum' feature
- Add .wvd extension [Donkey Kong Barrel Blast (Wii)]
This commit is contained in:
bnnm 2023-05-29 00:40:02 +02:00 committed by GitHub
commit 2ffc539ccf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 121 additions and 81 deletions

View File

@ -87,6 +87,7 @@ static void usage(const char* progname, int is_help) {
" -v: validate extensions (for extension testing)\n" " -v: validate extensions (for extension testing)\n"
" -r: reset and output a second file (for reset testing)\n" " -r: reset and output a second file (for reset testing)\n"
" -k N: kills (seeks) N samples before decoding (for seek testing)\n" " -k N: kills (seeks) N samples before decoding (for seek testing)\n"
" -2 seeks to loop start, -3 seeks to loop end\n"
" -K N: kills (seeks) again to N samples before decoding (for seek testing)\n" " -K N: kills (seeks) again to N samples before decoding (for seek testing)\n"
" -t: print !tags found in !tags.m3u (for tag testing)\n" " -t: print !tags found in !tags.m3u (for tag testing)\n"
" -T: print title (for title testing)\n" " -T: print title (for title testing)\n"
@ -736,15 +737,24 @@ static int convert_file(cli_config* cfg) {
/* get final play config */ /* get final play config */
len_samples = vgmstream_get_samples(vgmstream); len_samples = vgmstream_get_samples(vgmstream);
if (len_samples <= 0) if (len_samples <= 0) {
fprintf(stderr, "wrong time config\n");
goto fail; goto fail;
}
if (cfg->seek_samples1 < -1) /* ex value for loop testing */ /* special values for loop testing */
if (cfg->seek_samples1 == -2) { /* loop start...end */
cfg->seek_samples1 = vgmstream->loop_start_sample; cfg->seek_samples1 = vgmstream->loop_start_sample;
if (cfg->seek_samples1 >= len_samples) }
cfg->seek_samples1 = -1; if (cfg->seek_samples1 == -3) { /* loop end..end */
if (cfg->seek_samples2 >= len_samples) cfg->seek_samples1 = vgmstream->loop_end_sample;
cfg->seek_samples2 = -1; }
/* would be ignored by seek code though (allowed for seek_samples2 to test this) */
if (cfg->seek_samples1 < -1 || cfg->seek_samples1 >= len_samples) {
fprintf(stderr, "wrong seek config\n");
goto fail;
}
if (cfg->play_forever && !vgmstream_get_play_forever(vgmstream)) { if (cfg->play_forever && !vgmstream_get_play_forever(vgmstream)) {
fprintf(stderr, "file can't be played forever"); fprintf(stderr, "file can't be played forever");

View File

@ -246,74 +246,85 @@ This list is not complete and many other files are supported.
Quick list of most codecs vgmstream supports, including many obscure ones that Quick list of most codecs vgmstream supports, including many obscure ones that
are used in few games. are used in few games.
- PCM 16-bit - PCM
- PCM 8-bit (signed, unsigned) - PCM 16-bit (little endian, big endian)
- PCM 4-bit (signed, unsigned) - PCM 8-bit (signed, unsigned, sign bit)
- PCM 32-bit float - PCM 4-bit (signed, unsigned)
- u-Law/a-LAW - PCM 24-bit (little endian, big endian)
- CRI ADX (standard, fixed, exponential, encrypted) - PCM 32-bit float
- Nintendo DSP ADPCM a.k.a GC ADPCM - u-Law/a-LAW
- Nintendo DTK ADPCM - ADPCM (BRR/XA-style)
- Nintendo AFC ADPCM - CD-ROM XA ADPCM
- ITU-T G.721 - Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable, extended)
- CD-ROM XA ADPCM - CRI ADX (standard, fixed, exponential, encrypted)
- Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable, extended) - Silicon Graphics VADPCM
- Sony HEVAG - Nintendo DSP ADPCM a.k.a GC ADPCM
- Electronic Arts EA-XA (stereo, mono, Maxis) - Nintendo DTK ADPCM
- Electronic Arts EA-XAS (v0, v1) - Nintendo AFC ADPCM
- DVI/IMA ADPCM (stereo/mono + high/low nibble, 3DS, Quantic Dream, SNDS, etc) - Microsoft MSADPCM (standard, mono, Cricket Audio)
- Microsoft MS IMA ADPCM (standard, Xbox, NDS, Radical, Wwise, FSB, WV6, etc) - Electronic Arts EA-XA (stereo, mono, Maxis)
- Microsoft MS ADPCM (standard, Cricket Audio) - Electronic Arts EA-XAS (v0, v1)
- Westwood VBR ADPCM - Konami MTAF ADPCM
- Yamaha ADPCM (AICA, Aska) - Konami MTA2 ADPCM
- Procyon Studio ADPCM - FMOD FADPCM ADPCM
- Level-5 0x555 ADPCM - Procyon Studio ADPCM
- lsf ADPCM - Level-5 0x555 ADPCM
- Konami MTAF ADPCM - Konami XMD ADPCM
- Konami MTA2 ADPCM - Argonaut ASF ADPCM
- Paradigm MC3 ADPCM - Tantalus ADPCM
- FMOD FADPCM 4-bit ADPCM - ADPCM (IMA-style)
- Konami XMD 4-bit ADPCM - DVI/IMA ADPCM (stereo/mono + high/low nibble, 3DS, Quantic Dream, SNDS, etc)
- Platinum 4-bit ADPCM - Microsoft MS-IMA ADPCM (standard, Xbox, NDS, Radical, Wwise, FSB, WV6, etc)
- Argonaut ASF 4-bit ADPCM - Yamaha ADPCM (AICA, Aska)
- Tantalus 4-bit ADPCM - Westwood VBR ADPCM
- Ocean DSA 4-bit ADPCM - OKI ADPCM (16-bit output, 4-shift, PC-FX)
- Circus XPCM ADPCM - LucasArts iMUSE VBR ADPCM
- Circus XPCM VQ - Tiger Game.com ADPCM
- OKI 4-bit ADPCM (16-bit output, 4-shift, PC-FX) - ADPCM (others)
- Ubisoft 4/6-bit ADPCM - Sony HEVAG
- Tiger Game.com ADPCM - Ubisoft 4/6-bit ADPCM
- LucasArts iMUSE VBR ADPCM - Platinum ADPCM
- CompressWave (CWav) Huffman ADPCM - Paradigm MC3 ADPCM
- SDX2 2:1 Squareroot-Delta-Exact compression DPCM - Ocean DSA ADPCM
- CBD2 2:1 Cuberoot-Delta-Exact compression DPCM - lsf ADPCM
- Activision EXAKT SASSC DPCM - ITU-T G.721
- Xilam DERF DPCM - CompressWave (CWav) Huffman ADPCM
- InterPlay ACM - Perceptual/transform-based
- VisualArt's NWA - MPEG MP1/2/3 (standard, AHX, XVAG, FSB, AWC, P3D, EA, etc)
- Electronic Arts MicroTalk a.k.a. UTK or UMT - Xiph Vorbis (Ogg, FSB, Wwise, OGL, Silicon Knights)
- Relic Codec - CRI HCA
- CRI HCA - ITU-T G.722.1 annex C a.k.a. Polycom Siren 14 (Namco)
- tri-Ace PS2 Codec - ITU-T G.719 annex B a.k.a. Polycom Siren 22
- Xiph Vorbis (Ogg, FSB5, Wwise, OGL, Silicon Knights) - Xiph Opus (Ogg, Switch, EA, UE4, Exient, FSB)
- MPEG MP1/2/3 (standard, AHX, XVAG, FSB, AWC, P3D, EA, etc) - Xiph CELT (FSB)
- ITU-T G.722.1 annex C a.k.a. Polycom Siren 14 (Namco) - Microsoft XMA1/2
- ITU-T G.719 annex B a.k.a. Polycom Siren 22 - Microsoft WMA v1, WMA v2, WMAPro
- Electronic Arts EASpeex - AAC
- Electronic Arts EALayer3 - Sony ATRAC3
- Electronic Arts EA-XMA - Sony ATRAC3plus
- Sony ATRAC3, ATRAC3plus - Sony ATRAC9
- Sony ATRAC9 - Relic Codec
- Microsoft XMA1/2 - tri-Ace PS2 Codec
- Microsoft WMA v1, WMA v2, WMAPro - Bink
- AAC - AC3/SPDIF
- Bink - Musepack
- AC3/SPDIF - Electronic Arts EASpeex
- Xiph Opus (Ogg, Switch, EA, UE4, Exient) - Electronic Arts EALayer3
- Xiph CELT (FSB) - Electronic Arts EA-XMA
- Musepack - Electronic Arts MicroTalk a.k.a. UTK or UMT
- FLAC - Inti Creates DCT codec
- Inti Creates' Range / DCT codecs - Circus XPCM VQ
- Misc
- SDX2 2:1 Squareroot-Delta-Exact compression DPCM
- CBD2 2:1 Cuberoot-Delta-Exact compression DPCM
- Activision EXAKT SASSC DPCM
- Xilam DERF DPCM
- Circus XPCM DPCM
- VisualArt's NWA PCM/DPCM
- Marble WADY PCM/DPCM
- InterPlay ACM
- Inti Creates Range codec
- FLAC
- Others - Others
Sometimes standard codecs come in non-standard layouts that aren't normally Sometimes standard codecs come in non-standard layouts that aren't normally

View File

@ -53,8 +53,7 @@ The following can be used in place of `(value)` for `(key) = (value)` commands.
* `:LE|BE`: value is little/big endian (optional, defaults to LE) * `:LE|BE`: value is little/big endian (optional, defaults to LE)
* `$1|2|3|4`: value has size of 8/16/24/32 bit (optional, defaults to 4) * `$1|2|3|4`: value has size of 8/16/24/32 bit (optional, defaults to 4)
* Example: `@0x10:BE$2` means `get big endian 16b value at 0x10` * Example: `@0x10:BE$2` means `get big endian 16b value at 0x10`
- `(field)`: uses current value of some fields. Accepted strings: - `(field)`: uses current value of some fields (`interleave`, `channels`, `start_offset`, `data_size`, `num_samples`, `subsong_count`, `subfile_size`, `base_offset`, `name_valueX`, etc)
- `interleave, interleave_last, channels, sample_rate, start_offset, data_size, num_samples, loop_start_sample, loop_end_sample, subsong_count, subsong_spacing, subfile_offset, subfile_size, base_offset, name_valueX`
- `subsong` is a special field for current subsong - `subsong` is a special field for current subsong
- `(other)`: other special values for certain keys, described per key - `(other)`: other special values for certain keys, described per key
@ -419,12 +418,14 @@ Sets the number of subsongs in the file, adjusting reads per subsong N: `value =
Instead of `subsong_spacing` you can use `subsong_offset` (older alias). Instead of `subsong_spacing` you can use `subsong_offset` (older alias).
Mainly for bigfiles with consecutive headers per subsong, set subsong_offset to 0 when done as it affects any reads. The current subsong number is handled externally by plugins or TXTP. Mainly for bigfiles with consecutive headers per subsong, set `subsong_offset` to 0 when done as it affects any reads. The current subsong number is handled externally by plugins or TXTP.
``` ```
subsong_count = (value) subsong_count = (value)
subsong_spacing = (value) subsong_spacing = (value)
``` ```
A experimental field is `subsong_sum = (value)`, that sums all subsong values up to current subsong. Mainly meant when offsets are the sum of subsong sizes: if you have a table of sizes at 0x10 for 3 subsongs, each of size 0x1000, then `subsong_sum = @0x10` for first subsong sums 0x0000, 0x1000 for second, 0x2000 for third (can be used later as `start_offset = subsong_sum`).
#### NAMES #### NAMES
Sets the name of the stream, most useful when used with subsongs. TXTH will read a string at `name_offset`, with `name_size characters`. Sets the name of the stream, most useful when used with subsongs. TXTH will read a string at `name_offset`, with `name_size characters`.

View File

@ -639,6 +639,7 @@ static const char* extension_list[] = {
"wua", "wua",
"wv2", "wv2",
"wv6", "wv6",
"wvd", //txth/reserved [Donkey Kong Barrel Blast (Wii)]
"wve", "wve",
"wvs", "wvs",
"wvx", "wvx",

View File

@ -488,10 +488,9 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
vgmstream->interleave_block_size = 0x8c; vgmstream->interleave_block_size = 0x8c;
break; break;
#if 0 //disabled until some game is found, can be created in the GUI tool
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x11: { /* FMOD_SOUND_FORMAT_OPUS */ case 0x11: { /* FMOD_SOUND_FORMAT_OPUS [LEGO 2K Drive (Switch)] */
int skip = 312; //fsb_opus_get_encoder_delay(fsb5.stream_offset, sb); /* returns 120 but this seems correct */ int skip = 312; //fsb_opus_get_encoder_delay(fsb5.stream_offset, sb); /* returns 120 but this seems correct in test files */
//vgmstream->num_samples -= skip; //vgmstream->num_samples -= skip;
vgmstream->codec_data = init_ffmpeg_fsb_opus(sb, fsb5.stream_offset, fsb5.stream_size, vgmstream->channels, skip, vgmstream->sample_rate); vgmstream->codec_data = init_ffmpeg_fsb_opus(sb, fsb5.stream_offset, fsb5.stream_size, vgmstream->channels, skip, vgmstream->sample_rate);
@ -500,7 +499,6 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
break; break;
} }
#endif
#endif #endif
default: default:
vgm_logi("FSB5: unknown codec 0x%x (report)\n", fsb5.codec); vgm_logi("FSB5: unknown codec 0x%x (report)\n", fsb5.codec);

View File

@ -116,6 +116,7 @@ typedef struct {
int target_subsong; int target_subsong;
uint32_t subsong_count; uint32_t subsong_count;
uint32_t subsong_spacing; uint32_t subsong_spacing;
uint32_t subsong_sum;
uint32_t name_offset_set; uint32_t name_offset_set;
uint32_t name_offset; uint32_t name_offset;
@ -1300,6 +1301,23 @@ static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, cha
else if (is_string(key,"subsong_spacing") || is_string(key,"subsong_offset")) { else if (is_string(key,"subsong_spacing") || is_string(key,"subsong_offset")) {
if (!parse_num(txth->sf_head,txth,val, &txth->subsong_spacing)) goto fail; if (!parse_num(txth->sf_head,txth,val, &txth->subsong_spacing)) goto fail;
} }
else if (is_string(key,"subsong_sum")) {
/* add all values up to current subsong (for example, to add all sizes to get current offset, so get start_offset)
* doesn't include current (that is, reading size from fist subsong doesn't add anything) */
int default_subsong = txth->target_subsong;
uint32_t subsong_sum = 0;
for (int i = 0; i < default_subsong - 1; i++) {
txth->target_subsong = i + 1;
if (!parse_num(txth->sf_head,txth,val, &subsong_sum)) goto fail;
txth->subsong_sum += subsong_sum;
}
txth->target_subsong = default_subsong;
}
else if (is_string(key,"name_offset")) { else if (is_string(key,"name_offset")) {
if (!parse_num(txth->sf_head,txth,val, &txth->name_offset)) goto fail; if (!parse_num(txth->sf_head,txth,val, &txth->name_offset)) goto fail;
txth->name_offset_set = 1; txth->name_offset_set = 1;
@ -2001,6 +2019,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_
else if ((n = is_string_field(val,"subsong_count"))) value = txth->subsong_count; else if ((n = is_string_field(val,"subsong_count"))) value = txth->subsong_count;
else if ((n = is_string_field(val,"subsong_spacing"))) value = txth->subsong_spacing; else if ((n = is_string_field(val,"subsong_spacing"))) value = txth->subsong_spacing;
else if ((n = is_string_field(val,"subsong_offset"))) value = txth->subsong_spacing; else if ((n = is_string_field(val,"subsong_offset"))) value = txth->subsong_spacing;
else if ((n = is_string_field(val,"subsong_sum"))) value = txth->subsong_sum;
else if ((n = is_string_field(val,"subfile_offset"))) value = txth->subfile_offset; else if ((n = is_string_field(val,"subfile_offset"))) value = txth->subfile_offset;
else if ((n = is_string_field(val,"subfile_size"))) value = txth->subfile_size; else if ((n = is_string_field(val,"subfile_size"))) value = txth->subfile_size;
else if ((n = is_string_field(val,"base_offset"))) value = txth->base_offset; else if ((n = is_string_field(val,"base_offset"))) value = txth->base_offset;