diff --git a/src/formats.c b/src/formats.c index 6f02bae9..0f4538d3 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1283,6 +1283,7 @@ static const meta_info meta_info_list[] = { {meta_TGC, "Tiger Game.com .4 header"}, {meta_KWB, "Koei Tecmo WaveBank header"}, {meta_LRMD, "Sony LRMD header"}, + {meta_WWISE_FX, "Audiokinetic Wwise FX header"}, }; diff --git a/src/meta/bkhd.c b/src/meta/bkhd.c index 85e65b35..4788aad1 100644 --- a/src/meta/bkhd.c +++ b/src/meta/bkhd.c @@ -42,12 +42,19 @@ VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf) { subfile_offset = read_u32(offset + 0x04, sf) + data_offset; subfile_size = read_u32(offset + 0x08, sf); - + //;VGM_LOG("BKHD: %lx, %x\n", subfile_offset, subfile_size); temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "wem"); if (!temp_sf) goto fail; - vgmstream = init_vgmstream_wwise(temp_sf); - if (!vgmstream) goto fail; + subfile_id = read_u32(0x00, temp_sf); + if (subfile_id == 0x52494646 || subfile_id == 0x52494658) { /* "RIFF" / "RIFX" */ + vgmstream = init_vgmstream_wwise(temp_sf); + if (!vgmstream) goto fail; + } + else { + vgmstream = init_vgmstream_bkhd_fx(temp_sf); + if (!vgmstream) goto fail; + } vgmstream->num_streams = total_subsongs; snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%u", subfile_id); @@ -60,3 +67,60 @@ fail: close_vgmstream(vgmstream); return NULL; } + + +/* BKHD mini format, probably from a generator plugin [Borderlands 2 (X360)] */ +VGMSTREAM* init_vgmstream_bkhd_fx(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset, data_size; + int big_endian, loop_flag, channels, sample_rate, entries; + uint32_t (*read_u32)(off_t,STREAMFILE*); + + + /* checks */ + if (!check_extensions(sf,"wem,bnk")) /* assumed */ + goto fail; + big_endian = guess_endianness32bit(0x00, sf); + read_u32 = big_endian ? read_u32be : read_u32le; + + if (read_u32(0x00, sf) != 0x0400) /* codec? */ + goto fail; + if (read_u32(0x04, sf) != 0x0800) /* codec? */ + goto fail; + sample_rate = read_u32(0x08, sf); + channels = read_u32(0x0c, sf); + /* 0x10: some id or small size? */ + /* 0x14/18: some float? */ + entries = read_u32(0x1c, sf); + /* 0x20 data size / 0x10 */ + if (read_u8(0x24, sf) != 4) /* bps */ + goto fail; + /* 0x30: unknown table of 16b that goes up and down */ + + start_offset = 0x30 + align_size_to_block(entries * 0x02, 0x10); + data_size = get_streamfile_size(sf) - start_offset; + loop_flag = 0; + + /* output sounds a bit funny, maybe not an actual stream but parts using the table */ + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_WWISE_FX; + vgmstream->sample_rate = sample_rate; + + vgmstream->coding_type = coding_PCMFLOAT; + vgmstream->layout_type = layout_interleave; + vgmstream->codec_endian = big_endian; + vgmstream->interleave_block_size = 0x4; + + vgmstream->num_samples = pcm_bytes_to_samples(data_size, channels, 32); + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + return vgmstream; +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index cce4b04a..f5b4d19a 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -889,5 +889,6 @@ VGMSTREAM * init_vgmstream_kwb(STREAMFILE* sf); VGMSTREAM * init_vgmstream_lrmd(STREAMFILE* sf); VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_bkhd_fx(STREAMFILE* sf); #endif /*_META_H*/ diff --git a/src/vgmstream.c b/src/vgmstream.c index 7796e5f8..b9370f3d 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -491,6 +491,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_kwb, init_vgmstream_lrmd, init_vgmstream_bkhd, + init_vgmstream_bkhd_fx, /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ diff --git a/src/vgmstream.h b/src/vgmstream.h index a05e6a82..e53c5bcd 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -724,6 +724,7 @@ typedef enum { meta_TGC, meta_KWB, meta_LRMD, + meta_WWISE_FX, } meta_t; /* standard WAVEFORMATEXTENSIBLE speaker positions */