Merge pull request #1167 from bnnm/vorbis-misc

- Add SNDZ .szd extension
- Fix missing end samples in Wwise Vorbis
- Fix some Wwise Convolution Reverb wem
- Fix truncated ATRAC9 .wem
This commit is contained in:
bnnm 2022-07-14 23:18:27 +02:00 committed by GitHub
commit 5aeecc7fd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 56 additions and 21 deletions

View File

@ -409,6 +409,7 @@ typedef struct {
uint32_t setup_id; /* external setup */
int big_endian; /* flag */
uint32_t stream_end; /* optional, to avoid overreading into next subsong or chunk */
/* Wwise Vorbis config */
wwise_setup_t setup_type;

View File

@ -65,6 +65,9 @@ vorbis_custom_codec_data* init_vorbis_custom(STREAMFILE* sf, off_t start_offset,
/* write output */
config->data_start_offset = data->config.data_start_offset;
if (!data->config.stream_end) {
data->config.stream_end = get_streamfile_size(sf);
}
return data;
@ -78,19 +81,11 @@ fail:
void decode_vorbis_custom(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do, int channels) {
VGMSTREAMCHANNEL *stream = &vgmstream->ch[0];
vorbis_custom_codec_data* data = vgmstream->codec_data;
size_t stream_size = get_streamfile_size(stream->streamfile);
//data->op.packet = data->buffer;/* implicit from init */
int samples_done = 0;
while (samples_done < samples_to_do) {
/* extra EOF check for edge cases */
if (stream->offset >= stream_size) {
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample) * channels);
break;
}
if (data->samples_full) { /* read more samples */
int samples_to_get;
float **pcm;
@ -123,6 +118,12 @@ void decode_vorbis_custom(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t sample
else { /* read more data */
int ok, rc;
/* extra EOF check */
if (stream->offset >= data->config.stream_end) {
/* may need to drain samples? (not a thing in vorbis due to packet types?) */
goto decode_fail;
}
/* not actually needed, but feels nicer */
data->op.granulepos += samples_to_do; /* can be changed next if desired */
data->op.packetno++;

View File

@ -532,6 +532,7 @@ static const char* extension_list[] = {
"sxd",
"sxd2",
"sxd3",
"szd",
"szd1",
"szd3",

View File

@ -206,10 +206,13 @@ VGMSTREAM* init_vgmstream_bkhd_fx(STREAMFILE* sf) {
/* Not an actual stream but typically convolution reverb models and other FX plugin helpers.
* Useless but to avoid "subsong not playing" complaints. */
if (read_u32(0x00, sf) == 0x0400 &&
/* Wwise Convolution Reverb */
if ((read_u32(0x00, sf) == 0x00000400 || /* common */
read_u32(0x00, sf) == 0x00020400 ) && /* Elden Ring */
read_u32(0x04, sf) == 0x0800) {
sample_rate = read_u32(0x08, sf);
channels = read_u32(0x0c, sf) & 0xFF; /* 0x31 at 0x0d in PC, field is 32b vs X360 */
/* 0x10: some id or small size? (related to entries?) */
/* 0x14/18: some float? */
entries = read_u32(0x1c, sf);

View File

@ -477,6 +477,7 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
cfg.channels = fsb5.channels;
cfg.sample_rate = fsb5.sample_rate;
cfg.setup_id = read_u32le(fsb5.extradata_offset,sf);
cfg.stream_end = fsb5.stream_offset + fsb5.stream_size;
vgmstream->codec_data = init_vorbis_custom(sb, fsb5.stream_offset, VORBIS_FSB, &cfg);
if (!vgmstream->codec_data) goto fail;

View File

@ -73,7 +73,30 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
}
/* typical chunks: WAVE, RGND, NAME (strings for WAVE or RGND), SEQD (related to SFX), WSUR, WMKR, BUSS */
/* Format per chunk:
* - 0x00: id
* - 0x04: SGX: unknown; SGD/SGH: chunk length
* - 0x08: null
* - 0x0c: entries */
/* typical chunks (with some entry info):
* - WAVE: wave data (see below)
* - RGND: programs info, notably:
* - 0x18: min note range
* - 0x19: max note range
* - 0x1C: root note
* - 0x34: WAVE id
* > sample_rate = wave_sample_rate * (2 ^ (1/12)) ^ (target_note - root_note)
* - NAME: strings for other chunks
* - 0x00: sub-id?
* - 0x02: type? (possibly: 0000=bank, 0x2xxx=SEQD/WAVE, 0x3xxx=WSUR, 0x4xxx=BUSS, 0x6xxx=CONF)
* - 0x04: absolute offset
* - SEQD: related to SFX (sequences?), entries seem to be offsets to name offset + seq (ps1?) offset
* - WSUR: ?
* - WMKR: ?
* - CONF: ? (name offset + config offset)
* - 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"))
@ -83,7 +106,6 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
if (!find_chunk_le(sf_head, get_id32be("WAVE"),0x10,0, &chunk_offset, NULL))
goto fail;
}
/* 0x04 SGX: unknown; SGD/SGH: chunk length, 0x08 null */
/* check multi-streams (usually only SE containers; Puppeteer) */
total_subsongs = read_s32le(chunk_offset+0x04,sf_head);
@ -95,18 +117,18 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) {
uint32_t stream_offset;
chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/
/* 0x00 ? (00/01/02) */
/* 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);
codec = read_u8(chunk_offset+0x08,sf_head);
channels = read_u8(chunk_offset+0x09,sf_head);
/* 0x0a null */
/* 0x0a: null */
sample_rate = read_s32le(chunk_offset+0x0c,sf_head);
/* 0x10: info_type, meaning of the next value
* (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */
/* 0x14: info_value (see above) */
/* 0x18: unknown (ex. 0x0008/0010/3307/CC02/etc)x2 */
/* 0x18: unknown (ex. 0x0008/0010/3307/CC02/etc, RGND related?) x2 */
/* 0x1c: null */
num_samples = read_s32le(chunk_offset+0x20,sf_head);

View File

@ -26,8 +26,8 @@ VGMSTREAM* init_vgmstream_sndz(STREAMFILE* sf) {
/* .szd1: header + .szd2 = data
* .szd3: szd1 + szd2 */
if (!check_extensions(sf, "szd1,szd3"))
* .szd/szd3: szd1 + szd2 */
if (!check_extensions(sf, "szd1,szd,szd3"))
goto fail;
/* parse chunk table and WAVS with offset to offset to WAVD */

View File

@ -172,6 +172,7 @@ VGMSTREAM* init_vgmstream_wwise_bnk(STREAMFILE* sf, int* p_prefetch) {
cfg.channels = ww.channels;
cfg.sample_rate = ww.sample_rate;
cfg.big_endian = ww.big_endian;
cfg.stream_end = ww.data_offset + ww.data_size;
if (ww.block_size != 0 || ww.bits_per_sample != 0) goto fail; /* always 0 for Worbis */
@ -237,7 +238,7 @@ VGMSTREAM* init_vgmstream_wwise_bnk(STREAMFILE* sf, int* p_prefetch) {
uint32_t setup_id = read_u32be(start_offset + setup_offset + 0x06, sf);
/* if the setup after header starts with "(data)BCV" it's an inline codebook) */
if ((setup_id & 0x00FFFFFF) == 0x00424356) { /* 0"BCV" */
if ((setup_id & 0x00FFFFFF) == get_id32be("\0BCV")) {
cfg.setup_type = WWV_FULL_SETUP;
}
/* if the setup is suspiciously big it's probably trimmed inline codebooks */
@ -582,7 +583,7 @@ VGMSTREAM* init_vgmstream_wwise_bnk(STREAMFILE* sf, int* p_prefetch) {
case mapping_2POINT1_xiph: /* 2ch+1ch, 2 streams */
case mapping_STEREO: cfg.coupled_count = 1; break; /* 2ch, 1 stream */
default: cfg.coupled_count = 0; break; /* 1ch, 1 stream */
//TODO: AK OPUS doesn't seem to handles others mappings, though AK's .h imply they exist (uses 0 coupleds?)
//TODO: AK OPUS doesn't seem to handle others mappings, though AK's .h imply they exist (uses 0 coupleds?)
}
/* total number internal OPUS streams (should be >0) */
@ -650,6 +651,11 @@ VGMSTREAM* init_vgmstream_wwise_bnk(STREAMFILE* sf, int* p_prefetch) {
vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_s32(ww.fmt_offset + 0x1c, sf);
if (ww.prefetch) {
vgmstream->num_samples = atrac9_bytes_to_samples_cfg(ww.file_size - start_offset, cfg.config_data);
}
break;
}
#endif
@ -932,8 +938,8 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) {
}
if (ww->codec == PCM || ww->codec == IMA || ww->codec == VORBIS || ww->codec == DSP || ww->codec == XMA2 ||
ww->codec == OPUSNX || ww->codec == OPUS || ww->codec == OPUSWW || ww->codec == PTADPCM || ww->codec == XWMA) {
ww->prefetch = 1; /* only seen those, probably all exist (XWMA, AAC, HEVAG, ATRAC9?) */
ww->codec == OPUSNX || ww->codec == OPUS || ww->codec == OPUSWW || ww->codec == PTADPCM || ww->codec == XWMA || ww->codec == ATRAC9) {
ww->prefetch = 1; /* only seen those, probably all exist (missing XWMA, AAC, HEVAG) */
} else {
vgm_logi("WWISE: wrong expected size, maybe prefetch (report)\n");
goto fail;
@ -945,7 +951,7 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) {
* From init bank and CAkSound's sources, those may be piped through their plugins. They come in
* .opuspak (no names), have wrong riff/data sizes and only seem used for sfx (other audio is Vorbis). */
if (ww->format == 0xFFFE && ww->prefetch) {
if (read_u32be(ww->data_offset + 0x00, sf) == 0x4F676753) {
if (is_id32be(ww->data_offset + 0x00, sf, "OggS")) {
ww->codec = OPUSCPR;
}
}