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