diff --git a/src/meta/wwise.c b/src/meta/wwise.c index 233b3e05..462de2a9 100644 --- a/src/meta/wwise.c +++ b/src/meta/wwise.c @@ -118,9 +118,16 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) { ww.bits_per_sample = (uint16_t)read_16bit(ww.fmt_offset+0x0e,streamFile); if (ww.fmt_size > 0x10 && ww.format != 0x0165 && ww.format != 0x0166) /* ignore XMAWAVEFORMAT */ ww.extra_size = (uint16_t)read_16bit(ww.fmt_offset+0x10,streamFile); - if (ww.extra_size >= 0x06) { /* mostly WAVEFORMATEXTENSIBLE's bitmask, see AkSpeakerConfig.h */ - /* always present (actual RIFFs only have it in WAVEFORMATEXTENSIBLE) */ + if (ww.extra_size >= 0x06) { /* always present (actual RIFFs only have it in WAVEFORMATEXTENSIBLE) */ + /* mostly WAVEFORMATEXTENSIBLE's bitmask (see AkSpeakerConfig.h) */ ww.channel_layout = read_32bit(ww.fmt_offset+0x14,streamFile); + /* latest games have a pseudo-format instead to handle more cases: + * - 8b: uNumChannels + * - 4b: eConfigType (0=none, 1=standard, 2=ambisonic) + * - 19b: uChannelMask */ + if ((ww.channel_layout & 0xFF) == ww.channels) { + ww.channel_layout = (ww.channel_layout >> 12); + } } } diff --git a/src/vgmstream.c b/src/vgmstream.c index b3d47347..3decee66 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -548,6 +548,26 @@ static VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile) { } #endif + /* some players are picky with incorrect channel layouts */ + if (vgmstream->channel_layout > 0) { + int output_channels = vgmstream->channels; + int ch, count = 0, max_ch = 32; + for (ch = 0; ch < max_ch; ch++) { + int bit = (vgmstream->channel_layout >> ch) & 1; + if (ch > 17 && bit) { + VGM_LOG("VGMSTREAM: wrong bit %i in channel_layout %x\n", ch, vgmstream->channel_layout); + vgmstream->channel_layout = 0; + break; + } + count += bit; + } + + if (count > output_channels) { + VGM_LOG("VGMSTREAM: wrong totals %i in channel_layout %x\n", count, vgmstream->channel_layout); + vgmstream->channel_layout = 0; + } + } + /* files can have thousands subsongs, but let's put a limit */ if (vgmstream->num_streams < 0 || vgmstream->num_streams > 65535) { VGM_LOG("VGMSTREAM: wrong num_streams (ns=%i)\n", vgmstream->num_streams);