mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-13 18:20:50 +01:00
Add partial Wwise support (PCM/DSP/AAC/HEVAG)
This commit is contained in:
parent
2ec41eb054
commit
4f73cfc18d
@ -670,6 +670,7 @@ DECLARE_MULTIPLE_FILE_TYPE("WAD Audio File (*.WAD)", wad);
|
|||||||
DECLARE_MULTIPLE_FILE_TYPE("WAM Audio File (*.WAM)", wam);
|
DECLARE_MULTIPLE_FILE_TYPE("WAM Audio File (*.WAM)", wam);
|
||||||
DECLARE_MULTIPLE_FILE_TYPE("WAVM Audio File (*.WAVM)", wavm);
|
DECLARE_MULTIPLE_FILE_TYPE("WAVM Audio File (*.WAVM)", wavm);
|
||||||
DECLARE_MULTIPLE_FILE_TYPE("WAS Audio File (*.WAS)", was);
|
DECLARE_MULTIPLE_FILE_TYPE("WAS Audio File (*.WAS)", was);
|
||||||
|
DECLARE_MULTIPLE_FILE_TYPE("WEM Audio File (*.WEM)", was);
|
||||||
DECLARE_MULTIPLE_FILE_TYPE("WII Audio File (*.WII)", wii);
|
DECLARE_MULTIPLE_FILE_TYPE("WII Audio File (*.WII)", wii);
|
||||||
DECLARE_MULTIPLE_FILE_TYPE("WMUS Audio File (*.WMUS)", wmus);
|
DECLARE_MULTIPLE_FILE_TYPE("WMUS Audio File (*.WMUS)", wmus);
|
||||||
DECLARE_MULTIPLE_FILE_TYPE("WP2 Audio File (*.WP2)", wp2);
|
DECLARE_MULTIPLE_FILE_TYPE("WP2 Audio File (*.WP2)", wp2);
|
||||||
|
@ -315,7 +315,8 @@ META_OBJS=meta/adx_header.o \
|
|||||||
meta/dsp_adx.o \
|
meta/dsp_adx.o \
|
||||||
meta/bik.o \
|
meta/bik.o \
|
||||||
meta/akb.o \
|
meta/akb.o \
|
||||||
meta/x360_ast.o
|
meta/x360_ast.o \
|
||||||
|
meta/wwise.o \
|
||||||
|
|
||||||
EXT_LIBS = ../ext_libs/clHCA.o
|
EXT_LIBS = ../ext_libs/clHCA.o
|
||||||
|
|
||||||
|
@ -298,6 +298,7 @@ static const char* extension_list[] = {
|
|||||||
//"wav", //common
|
//"wav", //common
|
||||||
"wavm",
|
"wavm",
|
||||||
"wb",
|
"wb",
|
||||||
|
"wem",
|
||||||
"wii",
|
"wii",
|
||||||
"wmus",
|
"wmus",
|
||||||
"wp2",
|
"wp2",
|
||||||
@ -835,6 +836,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_X360_PASX, "Namco PASX header"},
|
{meta_X360_PASX, "Namco PASX header"},
|
||||||
{meta_XMA_RIFF, "Microsoft XMA RIFF header"},
|
{meta_XMA_RIFF, "Microsoft XMA RIFF header"},
|
||||||
{meta_X360_AST, "Capcom AST header"},
|
{meta_X360_AST, "Capcom AST header"},
|
||||||
|
{meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"},
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
||||||
|
@ -1154,6 +1154,10 @@
|
|||||||
RelativePath=".\meta\wvs.c"
|
RelativePath=".\meta\wvs.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\wwise.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\x360_ast.c"
|
RelativePath=".\meta\x360_ast.c"
|
||||||
>
|
>
|
||||||
|
@ -382,6 +382,7 @@
|
|||||||
<ClCompile Include="meta\wii_sts.c" />
|
<ClCompile Include="meta\wii_sts.c" />
|
||||||
<ClCompile Include="meta\ws_aud.c" />
|
<ClCompile Include="meta\ws_aud.c" />
|
||||||
<ClCompile Include="meta\wvs.c" />
|
<ClCompile Include="meta\wvs.c" />
|
||||||
|
<ClCompile Include="meta\wwise.c" />
|
||||||
<ClCompile Include="meta\xbox_hlwav.c" />
|
<ClCompile Include="meta\xbox_hlwav.c" />
|
||||||
<ClCompile Include="meta\xbox_ims.c" />
|
<ClCompile Include="meta\xbox_ims.c" />
|
||||||
<ClCompile Include="meta\xbox_stma.c" />
|
<ClCompile Include="meta\xbox_stma.c" />
|
||||||
|
@ -697,6 +697,9 @@
|
|||||||
<ClCompile Include="meta\wvs.c">
|
<ClCompile Include="meta\wvs.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\wwise.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\xbox_hlwav.c">
|
<ClCompile Include="meta\xbox_hlwav.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -254,5 +254,6 @@ libmeta_la_SOURCES += dsp_adx.c
|
|||||||
libmeta_la_SOURCES += bik.c
|
libmeta_la_SOURCES += bik.c
|
||||||
libmeta_la_SOURCES += akb.c
|
libmeta_la_SOURCES += akb.c
|
||||||
libmeta_la_SOURCES += x360_ast.c
|
libmeta_la_SOURCES += x360_ast.c
|
||||||
|
libmeta_la_SOURCES += wwise.c
|
||||||
|
|
||||||
EXTRA_DIST = meta.h
|
EXTRA_DIST = meta.h
|
||||||
|
@ -674,4 +674,6 @@ VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile);
|
|||||||
|
|
||||||
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile);
|
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile);
|
||||||
|
|
||||||
#endif /*_META_H*/
|
#endif /*_META_H*/
|
||||||
|
357
src/meta/wwise.c
Normal file
357
src/meta/wwise.c
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../util.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Wwise uses a custom RIFF/RIFX header, non-standard enough that it's parsed it here.
|
||||||
|
* There is some repetition from other metas, but not enough to bother me.
|
||||||
|
*
|
||||||
|
* Some info: https://www.audiokinetic.com/en/library/edge/
|
||||||
|
*/
|
||||||
|
typedef enum { PCM, IMA, VORBIS, DSP, XMA2, XWMA, AAC, HEVAG, ATRAC9 } wwise_codec;
|
||||||
|
typedef struct {
|
||||||
|
int big_endian;
|
||||||
|
size_t file_size;
|
||||||
|
|
||||||
|
/* chunks references */
|
||||||
|
off_t fmt_offset;
|
||||||
|
size_t fmt_size;
|
||||||
|
off_t data_offset;
|
||||||
|
size_t data_size;
|
||||||
|
|
||||||
|
/* standard fmt stuff */
|
||||||
|
wwise_codec codec;
|
||||||
|
int format;
|
||||||
|
int channels;
|
||||||
|
int sample_rate;
|
||||||
|
int block_align;
|
||||||
|
int bit_per_sample;
|
||||||
|
size_t extra_size;
|
||||||
|
|
||||||
|
int loop_flag;
|
||||||
|
uint32_t num_samples;
|
||||||
|
uint32_t loop_start_sample;
|
||||||
|
uint32_t loop_end_sample;
|
||||||
|
} wwise_header;
|
||||||
|
|
||||||
|
|
||||||
|
/* Wwise - Audiokinetic Wwise (Wave Works Interactive Sound Engine) middleware */
|
||||||
|
VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
wwise_header ww;
|
||||||
|
off_t start_offset, first_offset = 0xc;
|
||||||
|
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||||
|
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
||||||
|
|
||||||
|
/* basic checks */
|
||||||
|
/* .wem (Wwise Encoded Media) is "newer Wwise", used after the 2011.2 SDK (~july)
|
||||||
|
* .wav (ex. Shadowrun X360) and .ogg (ex. KOF XII X360) are used only in older Wwise */
|
||||||
|
if (!check_extensions(streamFile,"wem,wav,lwav,ogg,logg")) goto fail; /* .xma may be possible? */
|
||||||
|
|
||||||
|
if ((read_32bitBE(0x00,streamFile) != 0x52494646) && /* "RIFF" (LE) */
|
||||||
|
(read_32bitBE(0x00,streamFile) != 0x52494658)) /* "RIFX" (BE) */
|
||||||
|
goto fail;
|
||||||
|
if ((read_32bitBE(0x08,streamFile) != 0x57415645)) /* "WAVE" */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
memset(&ww,0,sizeof(wwise_header));
|
||||||
|
|
||||||
|
ww.big_endian = read_32bitBE(0x00,streamFile) == 0x52494658;/* RIFX */
|
||||||
|
if (ww.big_endian) { /* Wwise honors machine's endianness (PC=RIFF, X360=RIFX --unlike XMA) */
|
||||||
|
read_32bit = read_32bitBE;
|
||||||
|
read_16bit = read_16bitBE;
|
||||||
|
} else {
|
||||||
|
read_32bit = read_32bitLE;
|
||||||
|
read_16bit = read_16bitLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ww.file_size = streamFile->get_size(streamFile);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* sometimes uses a RIFF size that doesn't count chunk/sizes, or just wrong...? */
|
||||||
|
if (4+4+read_32bit(0x04,streamFile) != ww.file_size) {
|
||||||
|
VGM_LOG("WWISE: bad riff size (real=0x%x vs riff=0x%x)\n", 4+4+read_32bit(0x04,streamFile), ww.file_size);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* parse WAVEFORMATEX (roughly spec-compliant but some massaging is needed) */
|
||||||
|
{
|
||||||
|
off_t loop_offset;
|
||||||
|
size_t loop_size;
|
||||||
|
|
||||||
|
/* find basic chunks */
|
||||||
|
if (!find_chunk(streamFile, 0x666d7420,first_offset,0, &ww.fmt_offset,&ww.fmt_size, ww.big_endian, 0)) goto fail; /*"fmt "*/
|
||||||
|
if (!find_chunk(streamFile, 0x64617461,first_offset,0, &ww.data_offset,&ww.data_size, ww.big_endian, 0)) goto fail; /*"data"*/
|
||||||
|
|
||||||
|
if (ww.data_size > ww.file_size) {
|
||||||
|
VGM_LOG("WWISE: bad data size (real=0x%x > riff=0x%x)\n", ww.data_size, ww.file_size);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* base fmt */
|
||||||
|
if (ww.fmt_size < 0x12) goto fail;
|
||||||
|
ww.format = (uint16_t)read_16bit(ww.fmt_offset+0x00,streamFile);
|
||||||
|
ww.channels = read_16bit(ww.fmt_offset+0x02,streamFile);
|
||||||
|
ww.sample_rate = read_32bit(ww.fmt_offset+0x04,streamFile);
|
||||||
|
/* 0x08: average samples per second */
|
||||||
|
ww.block_align = (uint16_t)read_16bit(ww.fmt_offset+0x0c,streamFile);
|
||||||
|
ww.bit_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 0
|
||||||
|
/* channel bitmask, see AkSpeakerConfig.h (ex. 1ch uses FRONT_CENTER 0x4, 2ch FRONT_LEFT 0x1 | FRONT_RIGHT 0x2) */
|
||||||
|
if (ww.extra_size >= 6)
|
||||||
|
ww.channel_config = read_32bit(ww.fmt_offset+0x14,streamFile);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* find loop info (both used in early and late Wwise and seem to follow the spec) */
|
||||||
|
if (find_chunk(streamFile, 0x736D706C,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"smpl"*/
|
||||||
|
if (loop_size >= 0x34
|
||||||
|
&& read_32bit(loop_offset+0x1c, streamFile)==1 /*loop count*/
|
||||||
|
&& read_32bit(loop_offset+0x24+4, streamFile)==0) {
|
||||||
|
ww.loop_flag = 1;
|
||||||
|
ww.loop_start_sample = read_32bit(loop_offset+0x24+0x8, streamFile);
|
||||||
|
ww.loop_end_sample = read_32bit(loop_offset+0x24+0xc,streamFile);
|
||||||
|
//todo fix repeat looping
|
||||||
|
}
|
||||||
|
} else if (find_chunk(streamFile, 0x4C495354,first_offset,0, &loop_offset,&loop_size, ww.big_endian, 0)) { /*"LIST"*/
|
||||||
|
//todo parse "adtl" (does it ever contain loop info in Wwise?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* other Wwise specific: */
|
||||||
|
//"JUNK": optional padding so that raw data starts in an offset multiple of 0x10 (0-size JUNK exists)
|
||||||
|
//"akd ": unknown (IMA/PCM; "audiokinetic data"?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* format to codec */
|
||||||
|
switch(ww.format) {
|
||||||
|
case 0x0001: ww.codec = PCM; break; /* older Wwise */
|
||||||
|
case 0x0002: ww.codec = IMA; break; /* newer Wwise (conflicts with MSADPCM) */
|
||||||
|
case 0x0011: ww.codec = IMA; break; /* older Wwise */
|
||||||
|
case 0x0069: ww.codec = IMA; break; /* older Wwise */
|
||||||
|
case 0x0165: ww.codec = XMA2; break;
|
||||||
|
case 0x0166: ww.codec = XMA2; break;
|
||||||
|
case 0xAAC0: ww.codec = AAC; break;
|
||||||
|
case 0xFFF0: ww.codec = DSP; break;
|
||||||
|
case 0xFFFB: ww.codec = HEVAG; break;
|
||||||
|
case 0xFFFC: ww.codec = ATRAC9; break;
|
||||||
|
case 0xFFFE: ww.codec = PCM; break; /* newer Wwise ("PCM for Wwise Authoring") (conflicts with WAVEFORMATEXTENSIBLE) */
|
||||||
|
case 0xFFFF: ww.codec = VORBIS; break;
|
||||||
|
default:
|
||||||
|
VGM_LOG("WWISE: unknown codec 0x%x \n", ww.format);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* fix for newer Wwise DSP with coefs: Epic Mickey 2 (Wii), Batman Arkham Origins Blackgate (3DS) */
|
||||||
|
if (ww.format == 0x0002 && ww.extra_size == 0x0c + ww.channels * 0x2e) {
|
||||||
|
ww.codec = DSP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(ww.channels,ww.loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = ww.sample_rate;
|
||||||
|
vgmstream->num_samples = ww.num_samples;
|
||||||
|
vgmstream->loop_start_sample = ww.loop_start_sample;
|
||||||
|
vgmstream->loop_end_sample = ww.loop_end_sample;
|
||||||
|
vgmstream->meta_type = meta_WWISE_RIFF;
|
||||||
|
|
||||||
|
start_offset = ww.data_offset;
|
||||||
|
|
||||||
|
switch(ww.codec) {
|
||||||
|
case PCM: /* common */
|
||||||
|
/* normally riff.c has priority but it's needed when .wem is used */
|
||||||
|
if (ww.bit_per_sample != 16) goto fail;
|
||||||
|
|
||||||
|
vgmstream->coding_type = (ww.big_endian ? coding_PCM16BE : coding_PCM16LE);
|
||||||
|
vgmstream->layout_type = ww.channels > 1 ? layout_interleave : layout_none;
|
||||||
|
vgmstream->interleave_block_size = 0x02;
|
||||||
|
|
||||||
|
vgmstream->num_samples = ww.data_size / ww.channels / (ww.bit_per_sample/8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMA: /* common */
|
||||||
|
/* slightly modified MS-IMA.
|
||||||
|
* Original research by hcs in ima_rejigger (https://github.com/hcs64/vgm_ripping/tree/master/demux/ima_rejigger5) */
|
||||||
|
#if 0
|
||||||
|
if (ww.bit_per_sample != 4) goto fail;
|
||||||
|
vgmstream->coding_type = coding_WWISE_IMA;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->interleave_block_size = ww.block_align;
|
||||||
|
|
||||||
|
vgmstream->num_samples = (ww.data_size / ww.block_align) * (ww.block_align - 4 * vgmstream->channels) * 2 /vgmstream->channels;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
VGM_LOG("WWISE: IMA found (unsupported)\n");
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
#ifdef VGM_USE_VORBIS
|
||||||
|
case VORBIS: { /* common */
|
||||||
|
/* Wwise uses custom Vorbis, which changed over time (config must be detected to pass to the decoder).
|
||||||
|
* Original research by hcs in ww2ogg (https://github.com/hcs64/ww2ogg) */
|
||||||
|
#if 0
|
||||||
|
off_t vorb_offset;
|
||||||
|
size_t vorb_size;
|
||||||
|
|
||||||
|
int packet_header_type = 0; /* 1 = size 8 (4-granule + 4-size), 2 = size 6 (4-granule + 2-size) or 3 = size 2 (2-size) */
|
||||||
|
int packet_type = 0; /* 1 = standard, 2 = modified vorbis packets */
|
||||||
|
int setup_type = 0; /* 1: triad, 2 = inline codebooks, 3 = external codebooks, 4 = external aoTuV codebooks */
|
||||||
|
int blocksize_0_pow = 0, blocksize_1_pow = 0;
|
||||||
|
|
||||||
|
if (ww.block_align != 0 || ww.bit_per_sample != 0) goto fail;
|
||||||
|
|
||||||
|
/* autodetect format */
|
||||||
|
if (find_chunk(streamFile, 0x766F7262,first_offset,0, &vorb_offset,&vorb_size, ww.big_endian, 0)) { /*"vorb"*/
|
||||||
|
/* older Wwise (~2011) */
|
||||||
|
switch (vorb_size) {
|
||||||
|
case 0x28:
|
||||||
|
case 0x2A:
|
||||||
|
case 0x2C:
|
||||||
|
case 0x32:
|
||||||
|
case 0x34:
|
||||||
|
default: goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* newer Wwise (~2012+) */
|
||||||
|
if (ww.extra_size != 0x30) goto fail; //todo some 0x2a exist
|
||||||
|
|
||||||
|
packet_header_type = 3; /* size 2 */
|
||||||
|
packet_type = 1; //todo mod packets false on certain configs
|
||||||
|
setup_type = 4; /* aoTuV */
|
||||||
|
|
||||||
|
/* 0x12 (2): unk (00,10,18) not related to seek table*/
|
||||||
|
/* 0x14 (4): channel config */
|
||||||
|
vgmstream->num_samples = read_32bit(ww.fmt_offset + 0x18, streamFile);
|
||||||
|
/* 0x20 (4): config, 0xcb/0xd9/etc */
|
||||||
|
/* 0x24 (4): ? samples? */
|
||||||
|
/* 0x28 (4): seek table size (setup packet offset within data) */
|
||||||
|
/* 0x2c (4): setup size (first audio packet offset within data) */
|
||||||
|
/* 0x30 (2): ? */
|
||||||
|
/* 0x32 (2): ? */
|
||||||
|
/* 0x34 (4): ? */
|
||||||
|
/* 0x38 (4): ? */
|
||||||
|
/* 0x3c (4): uid */ //todo same as external crc32?
|
||||||
|
blocksize_0_pow = read_8bit(ww.fmt_offset + 0x40, streamFile);
|
||||||
|
blocksize_1_pow = read_8bit(ww.fmt_offset + 0x41, streamFile);
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vgmstream->codec_data = init_wwise_vorbis_codec_data(streamFile, start_offset, vgmstream->channels, vgmstream->sample_rate);//pass endianness too
|
||||||
|
if (!vgmstream->codec_data) goto fail;
|
||||||
|
vgmstream->coding_type = coding_wwise_vorbis;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
VGM_LOG("WWISE: VORBIS found (unsupported)\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case DSP: { /* Wii/3DS/WiiU */
|
||||||
|
off_t wiih_offset;
|
||||||
|
size_t wiih_size;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ww.bit_per_sample != 4) goto fail;
|
||||||
|
|
||||||
|
vgmstream->coding_type = coding_NGC_DSP;
|
||||||
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = 0x8; /* ww.block_align = 0x8 in older Wwise, samples per block in newer Wwise */
|
||||||
|
|
||||||
|
/* find coef position */
|
||||||
|
if (find_chunk(streamFile, 0x57696948,first_offset,0, &wiih_offset,&wiih_size, ww.big_endian, 0)) { /*"WiiH"*/ /* older Wwise */
|
||||||
|
vgmstream->num_samples = ww.data_size / ww.channels / 8 * 14;
|
||||||
|
if (wiih_size != 0x2e * ww.channels) goto fail;
|
||||||
|
}
|
||||||
|
else if (ww.extra_size == 0x0c + ww.channels * 0x2e) { /* newer Wwise */
|
||||||
|
vgmstream->num_samples = read_32bit(ww.fmt_offset + 0x18, streamFile);
|
||||||
|
wiih_offset = ww.fmt_offset + 0x1c;
|
||||||
|
wiih_size = 0x2e * ww.channels;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get coefs and default history */
|
||||||
|
dsp_read_coefs(vgmstream,streamFile,wiih_offset, 0x2e, ww.big_endian);
|
||||||
|
for (i=0; i < ww.channels; i++) {
|
||||||
|
vgmstream->ch[i].adpcm_history1_16 = read_16bitBE(wiih_offset + i * 0x2e + 0x24,streamFile);
|
||||||
|
vgmstream->ch[i].adpcm_history2_16 = read_16bitBE(wiih_offset + i * 0x2e + 0x26,streamFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VGM_USE_FFMPEG
|
||||||
|
case XMA2: { /* X360/XBone */
|
||||||
|
//chunks:
|
||||||
|
//"XMA2", "seek": same as the official ones
|
||||||
|
//"XMAc": Wwise extension, XMA2 physical loop regions (loop_start_b, loop_end_b, loop_subframe_data)
|
||||||
|
|
||||||
|
VGM_LOG("WWISE: XMA2 found (unsupported)\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XWMA: /* X360 */
|
||||||
|
VGM_LOG("WWISE: XWMA found (unsupported)\n");
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
case AAC: { /* iOS/Mac */
|
||||||
|
ffmpeg_codec_data * ffmpeg_data = NULL;
|
||||||
|
if (ww.block_align != 0 || ww.bit_per_sample != 0) goto fail;
|
||||||
|
|
||||||
|
/* extra: size 0x12, unknown values */
|
||||||
|
|
||||||
|
ffmpeg_data = init_ffmpeg_offset(streamFile, ww.data_offset,ww.data_size);
|
||||||
|
if (!ffmpeg_data) goto fail;
|
||||||
|
vgmstream->codec_data = ffmpeg_data;
|
||||||
|
vgmstream->coding_type = coding_FFmpeg;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
|
||||||
|
vgmstream->num_samples = ffmpeg_data->totalSamples;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case HEVAG: /* PSV */
|
||||||
|
/* swapped values, another bizarre Wwise quirk */
|
||||||
|
if (ww.bit_per_sample != 4 && ww.block_align == 4) {
|
||||||
|
ww.block_align = ww.bit_per_sample;
|
||||||
|
ww.bit_per_sample = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extra_data: size 0x06, @0x00: samples per block (28), @0x04: channel config */
|
||||||
|
|
||||||
|
if (ww.bit_per_sample != 4) goto fail;
|
||||||
|
if (ww.big_endian) goto fail;
|
||||||
|
|
||||||
|
vgmstream->coding_type = coding_HEVAG;
|
||||||
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = ww.block_align;
|
||||||
|
|
||||||
|
vgmstream->num_samples = ww.data_size * 28 / 16 / ww.channels;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ATRAC9: /* PSV/PS4 */
|
||||||
|
VGM_LOG("WWISE: ATRAC9 found (unsupported)\n");
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -341,6 +341,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
|||||||
init_vgmstream_akb_multi,
|
init_vgmstream_akb_multi,
|
||||||
init_vgmstream_akb2_multi,
|
init_vgmstream_akb2_multi,
|
||||||
init_vgmstream_x360_ast,
|
init_vgmstream_x360_ast,
|
||||||
|
init_vgmstream_wwise,
|
||||||
|
|
||||||
#ifdef VGM_USE_FFMPEG
|
#ifdef VGM_USE_FFMPEG
|
||||||
init_vgmstream_xma,
|
init_vgmstream_xma,
|
||||||
|
@ -598,6 +598,7 @@ typedef enum {
|
|||||||
meta_X360_PASX, /* Namco PASX (Soul Calibur II HD X360) */
|
meta_X360_PASX, /* Namco PASX (Soul Calibur II HD X360) */
|
||||||
meta_XMA_RIFF, /* Microsoft RIFF XMA */
|
meta_XMA_RIFF, /* Microsoft RIFF XMA */
|
||||||
meta_X360_AST, /* Dead Rising (X360) */
|
meta_X360_AST, /* Dead Rising (X360) */
|
||||||
|
meta_WWISE_RIFF, /* Audiokinetic Wwise RIFF/RIFX */
|
||||||
|
|
||||||
#ifdef VGM_USE_VORBIS
|
#ifdef VGM_USE_VORBIS
|
||||||
meta_OGG_VORBIS, /* Ogg Vorbis */
|
meta_OGG_VORBIS, /* Ogg Vorbis */
|
||||||
|
Loading…
Reference in New Issue
Block a user