From 3c03891d13705cc8d5687e8e36c84a3580372468 Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 29 Jul 2021 23:41:27 +0200 Subject: [PATCH] cleanup: etc --- src/coding/imuse_decoder.c | 8 +- src/meta/aif_asobo.c | 102 +++++++------- src/meta/bar_streamfile.h | 164 +++++++++++----------- src/meta/vs_str.c | 112 +++++++-------- src/meta/wavebatch.c | 273 ++++++++++++++++++------------------- 5 files changed, 328 insertions(+), 331 deletions(-) diff --git a/src/coding/imuse_decoder.c b/src/coding/imuse_decoder.c index 823fca02..9ce7c546 100644 --- a/src/coding/imuse_decoder.c +++ b/src/coding/imuse_decoder.c @@ -420,7 +420,7 @@ static void decode_vima1(sbuf_t* sbuf, uint8_t* buf, size_t data_left, int block sbuf->filled += data_left / sizeof(int16_t) / chs; } -static int decode_block1(STREAMFILE* sf, imuse_codec_data* data, uint8_t* block, size_t data_left) { +static int decode_block1(imuse_codec_data* data, uint8_t* block, size_t data_left) { int block_num = data->current_block; switch(data->block_table[block_num].flags) { @@ -554,7 +554,7 @@ static void decode_vima2(sbuf_t* sbuf, uint8_t* buf, size_t data_left, uint16_t* sbuf->filled += data_left / sizeof(int16_t) / chs; } -static int decode_block2(STREAMFILE* sf, imuse_codec_data* data, uint8_t* block, size_t data_left) { +static int decode_block2(imuse_codec_data* data, uint8_t* block, size_t data_left) { int block_num = data->current_block; switch(data->block_table[block_num].flags) { @@ -597,11 +597,11 @@ static int decode_block(STREAMFILE* sf, imuse_codec_data* data) { switch(data->type) { case COMP: - ok = decode_block1(sf, data, block, data_left); + ok = decode_block1(data, block, data_left); break; case MCMP: - ok = decode_block2(sf, data, block, data_left); + ok = decode_block2(data, block, data_left); break; default: diff --git a/src/meta/aif_asobo.c b/src/meta/aif_asobo.c index 9610dc67..5a551727 100644 --- a/src/meta/aif_asobo.c +++ b/src/meta/aif_asobo.c @@ -1,51 +1,51 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* .AIF - from Asobo Studio games [Ratatouille (PC), WALL-E (PC), Up (PC)] */ -VGMSTREAM * init_vgmstream_aif_asobo(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - size_t data_size; - int loop_flag, channel_count; - - - /* checks */ - /* aif: standard, .laif/aiffl: for plugins */ - if ( !check_extensions(streamFile,"aif,laif,aiffl") ) - goto fail; - if ((uint16_t)read_16bitLE(0x00,streamFile) != 0x69) /* Xbox codec */ - goto fail; - - channel_count = read_16bitLE(0x02,streamFile); /* assumed, only stereo is known */ - if (channel_count != 2) goto fail; - - /* 0x08: ? */ - if ((uint16_t)read_16bitLE(0x0c,streamFile) != 0x24*channel_count) /* Xbox block */ - goto fail; - if ((uint16_t)read_16bitLE(0x0e,streamFile) != 0x04) /* Xbox bps */ - goto fail; - loop_flag = 0; - - start_offset = 0x14; - data_size = get_streamfile_size(streamFile) - start_offset; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_AIF_ASOBO; - vgmstream->sample_rate = read_32bitLE(0x04,streamFile); - vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size,channel_count); - - vgmstream->coding_type = coding_XBOX_IMA; - vgmstream->layout_type = layout_none; - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .AIF - from Asobo Studio games [Ratatouille (PC), WALL-E (PC), Up (PC)] */ +VGMSTREAM* init_vgmstream_aif_asobo(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + size_t data_size; + int loop_flag, channel_count; + + + /* checks */ + /* aif: standard, .laif/aiffl: for plugins */ + if ( !check_extensions(sf,"aif,laif,aiffl") ) + goto fail; + if ((uint16_t)read_16bitLE(0x00,sf) != 0x69) /* Xbox codec */ + goto fail; + + channel_count = read_16bitLE(0x02,sf); /* assumed, only stereo is known */ + if (channel_count != 2) goto fail; + + /* 0x08: ? */ + if ((uint16_t)read_16bitLE(0x0c,sf) != 0x24*channel_count) /* Xbox block */ + goto fail; + if ((uint16_t)read_16bitLE(0x0e,sf) != 0x04) /* Xbox bps */ + goto fail; + loop_flag = 0; + + start_offset = 0x14; + data_size = get_streamfile_size(sf) - start_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_AIF_ASOBO; + vgmstream->sample_rate = read_32bitLE(0x04,sf); + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size,channel_count); + + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + + if ( !vgmstream_open_stream(vgmstream, sf, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/bar_streamfile.h b/src/meta/bar_streamfile.h index fbe45595..aed4fd90 100644 --- a/src/meta/bar_streamfile.h +++ b/src/meta/bar_streamfile.h @@ -1,82 +1,82 @@ -#ifndef _BAR_STREAMFILE_H_ -#define _BAR_STREAMFILE_H_ -#include "../streamfile.h" - -/* a streamfile wrapping another for decryption */ - -enum {BAR_KEY_LENGTH = 16}; - -// don't know if this is unique, but seems accurate -static const uint8_t bar_key[BAR_KEY_LENGTH] = { - 0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6, - 0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80 -}; - -typedef struct _BARSTREAMFILE { - STREAMFILE sf; - STREAMFILE *real_file; -} BARSTREAMFILE; - - -/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file); - - -static size_t read_bar(BARSTREAMFILE *streamFile, uint8_t *dest, off_t offset, size_t length) { - off_t i; - size_t read_length = streamFile->real_file->read(streamFile->real_file, dest, offset, length); - - for (i = 0; i < read_length; i++) { - dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH]; - } - - return read_length; -} - -static size_t get_size_bar(BARSTREAMFILE *streamFile) { - return streamFile->real_file->get_size(streamFile->real_file); -} - -static size_t get_offset_bar(BARSTREAMFILE *streamFile) { - return streamFile->real_file->get_offset(streamFile->real_file); -} - -static void get_name_bar(BARSTREAMFILE *streamFile, char *name, size_t length) { - streamFile->real_file->get_name(streamFile->real_file, name, length); -} - -STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) { - STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize); - if (!newfile) - return NULL; - - return wrap_bar_STREAMFILE(newfile); -} - -static void close_bar(BARSTREAMFILE *streamFile) { - streamFile->real_file->close(streamFile->real_file); - free(streamFile); - return; -} - - -/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) { - BARSTREAMFILE *streamfile = malloc(sizeof(BARSTREAMFILE)); - - if (!streamfile) - return NULL; - - memset(streamfile, 0, sizeof(BARSTREAMFILE)); - - streamfile->sf.read = (void*)read_bar; - streamfile->sf.get_size = (void*)get_size_bar; - streamfile->sf.get_offset = (void*)get_offset_bar; - streamfile->sf.get_name = (void*)get_name_bar; - streamfile->sf.open = (void*)open_bar; - streamfile->sf.close = (void*)close_bar; - - streamfile->real_file = file; - - return &streamfile->sf; -} - -#endif /* _BAR_STREAMFILE_H_ */ +#ifndef _BAR_STREAMFILE_H_ +#define _BAR_STREAMFILE_H_ +#include "../streamfile.h" + +/* a streamfile wrapping another for decryption */ + +enum {BAR_KEY_LENGTH = 16}; + +// don't know if this is unique, but seems accurate +static const uint8_t bar_key[BAR_KEY_LENGTH] = { + 0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6, + 0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80 +}; + +typedef struct _BARSTREAMFILE { + STREAMFILE sf; + STREAMFILE *real_file; +} BARSTREAMFILE; + + +/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file); + + +static size_t read_bar(BARSTREAMFILE *streamFile, uint8_t *dest, off_t offset, size_t length) { + off_t i; + size_t read_length = streamFile->real_file->read(streamFile->real_file, dest, offset, length); + + for (i = 0; i < read_length; i++) { + dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH]; + } + + return read_length; +} + +static size_t get_size_bar(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_size(streamFile->real_file); +} + +static size_t get_offset_bar(BARSTREAMFILE *streamFile) { + return streamFile->real_file->get_offset(streamFile->real_file); +} + +static void get_name_bar(BARSTREAMFILE *streamFile, char *name, size_t length) { + streamFile->real_file->get_name(streamFile->real_file, name, length); +} + +static STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) { + STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize); + if (!newfile) + return NULL; + + return wrap_bar_STREAMFILE(newfile); +} + +static void close_bar(BARSTREAMFILE *streamFile) { + streamFile->real_file->close(streamFile->real_file); + free(streamFile); + return; +} + + +/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) { + BARSTREAMFILE *streamfile = malloc(sizeof(BARSTREAMFILE)); + + if (!streamfile) + return NULL; + + memset(streamfile, 0, sizeof(BARSTREAMFILE)); + + streamfile->sf.read = (void*)read_bar; + streamfile->sf.get_size = (void*)get_size_bar; + streamfile->sf.get_offset = (void*)get_offset_bar; + streamfile->sf.get_name = (void*)get_name_bar; + streamfile->sf.open = (void*)open_bar; + streamfile->sf.close = (void*)close_bar; + + streamfile->real_file = file; + + return &streamfile->sf; +} + +#endif /* _BAR_STREAMFILE_H_ */ diff --git a/src/meta/vs_str.c b/src/meta/vs_str.c index a6002b36..587cec33 100644 --- a/src/meta/vs_str.c +++ b/src/meta/vs_str.c @@ -1,56 +1,56 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../coding/coding.h" - -/* .vs/STRx - from The Bouncer (PS2) */ -VGMSTREAM * init_vgmstream_vs_str(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - int channel_count, loop_flag; - off_t start_offset; - - - /* checks */ - /* .vs: real extension (from .nam container) - * .str: fake, partial header id */ - if (!check_extensions(streamFile, "vs,str")) - goto fail; - - if (!(read_32bitBE(0x000,streamFile) == 0x5354524C && /* "STRL" */ - read_32bitBE(0x800,streamFile) == 0x53545252) && /* "STRR" */ - read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */ - goto fail; - - - loop_flag = 0; - channel_count = (read_32bitBE(0x00,streamFile) == 0x5354524D) ? 1 : 2; /* "STRM"=mono (voices) */ - start_offset = 0x00; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_VS_STR; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_blocked_vs_str; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - /* calc num_samples */ - { - vgmstream->next_block_offset = start_offset; - do { - block_update(vgmstream->next_block_offset,vgmstream); - vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); - } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - block_update(start_offset, vgmstream); - } - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + +/* .vs/STRx - from The Bouncer (PS2) */ +VGMSTREAM* init_vgmstream_vs_str(STREAMFILE* sf) { + VGMSTREAM * vgmstream = NULL; + int channel_count, loop_flag; + off_t start_offset; + + + /* checks */ + /* .vs: real extension (from .nam container) + * .str: fake, partial header id */ + if (!check_extensions(sf, "vs,str")) + goto fail; + + if (!(read_32bitBE(0x000,sf) == 0x5354524C && /* "STRL" */ + read_32bitBE(0x800,sf) == 0x53545252) && /* "STRR" */ + read_32bitBE(0x00,sf) != 0x5354524D) /* "STRM" */ + goto fail; + + + loop_flag = 0; + channel_count = (read_32bitBE(0x00,sf) == 0x5354524D) ? 1 : 2; /* "STRM"=mono (voices) */ + start_offset = 0x00; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_VS_STR; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_vs_str; + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + + /* calc num_samples */ + { + vgmstream->next_block_offset = start_offset; + do { + block_update(vgmstream->next_block_offset,vgmstream); + vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); + } + while (vgmstream->next_block_offset < get_streamfile_size(sf)); + block_update(start_offset, vgmstream); + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/wavebatch.c b/src/meta/wavebatch.c index 03cb3a50..5539f123 100644 --- a/src/meta/wavebatch.c +++ b/src/meta/wavebatch.c @@ -1,138 +1,135 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* WBAT - Firebrand Games header [Need for Speed: The Run (3DS), Fast & Furious: Showdown (3DS)] */ -VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, name_offset, offset, stream_offset; - size_t names_size, stream_size; - int loop_flag, channel_count, sample_rate, num_samples; - int big_endian, version, codec; - int total_subsongs, target_subsong = streamFile->stream_index; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - - - /* checks */ - if (!check_extensions(streamFile, "wavebatch")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x54414257) /* "TABW" */ - goto fail; - - /* section0: base header */ - big_endian = ((uint16_t)read_16bitBE(0x04,streamFile) == 0xFEFF); /* BOM (always LE on 3DS/Android) */ - if (big_endian) { - read_32bit = read_32bitBE; - read_16bit = read_16bitBE; - } else { - read_32bit = read_32bitLE; - read_16bit = read_16bitLE; - } - - - version = read_16bit(0x06, streamFile); /* assumed */ - if (version != 0x06 && version != 0x07) /* v6 = NFS: The Run , v7 = F&F Showndown */ - goto fail; - - total_subsongs = read_32bit(0x08,streamFile); - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - names_size = read_32bit(0x0c,streamFile); - /* 0x10/14: see below */ - /* 0x18: data size (all subsongs) */ - offset = 0x1c + names_size; /* skip names table */ - - /* the following 2 sections (rarely) won't match total_subsongs */ - - /* section1: unknown */ - { - size_t unknown_size = read_32bit(0x10,streamFile); - /* 0x00: usually 0, rarely 0x20? */ - offset += unknown_size*0x04; - } - - /* section2: samples */ - { - size_t samples_size = read_32bit(0x14,streamFile); - /* 0x00: num_samples */ - offset += samples_size*0x04; - } - - /* section3: headers */ - { - off_t header_offset = offset+(target_subsong-1)*0x24; - - name_offset = read_32bit(header_offset+0x00, streamFile) + 0x1c; /* within name table */ - codec = read_32bit(header_offset+0x04, streamFile); - sample_rate = read_32bit(header_offset+0x08, streamFile); - channel_count = read_32bit(header_offset+0x0c, streamFile); - /* 0x10: index within section1/2? */ - /* 0x14: flags? 0x01 or (rarely) 0x02 */ - stream_offset = read_32bit(header_offset+0x18, streamFile); - stream_size = read_32bit(header_offset+0x1c, streamFile); /* including DSP config */ - num_samples = read_32bit(header_offset+0x20, streamFile) / channel_count; /* nibble/PCMs */ - - offset += total_subsongs*0x24; - } - - loop_flag = 0; - start_offset = offset + stream_offset; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; - - vgmstream->meta_type = meta_WAVEBATCH; - - switch(codec) { - case 0x00: /* PCM16 [NASCAR Unleashed (3DS), Solar Flux Pocket (Android)] */ - vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x02; - break; - - case 0x01: /* PCM8 [Cars 2 (3DS)] */ - vgmstream->coding_type = coding_PCM8; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x01; - break; - - case 0x02: { /* DSP [WRC FIA World Rally Championship (3DS)] */ - size_t config_size = (0x20+0x14)*channel_count + (0x0c)*channel_count; /* coefs+hist + padding */ - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = (stream_size - config_size) / channel_count; /* full interleave*/; - - dsp_read_coefs(vgmstream,streamFile,start_offset+0x00,0x20+0x14,big_endian); - dsp_read_hist (vgmstream,streamFile,start_offset+0x20,0x14+0x20,big_endian); - start_offset += config_size; - - break; - } - - default: - VGM_LOG("WAVEBATCH: unknown codec %x\n", codec); - goto fail; - } - - - - read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamFile); /* always null-terminated */ - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* WBAT - Firebrand Games header [Need for Speed: The Run (3DS), Fast & Furious: Showdown (3DS)] */ +VGMSTREAM * init_vgmstream_wavebatch(STREAMFILE *sf) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, name_offset, offset, stream_offset; + size_t names_size, stream_size; + int loop_flag, channel_count, sample_rate, num_samples; + int big_endian, version, codec; + int total_subsongs, target_subsong = sf->stream_index; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + + /* checks */ + if (!check_extensions(sf, "wavebatch")) + goto fail; + if (!is_id32be(0x00,sf, "TABW")) + goto fail; + + /* section0: base header */ + big_endian = (read_u16be(0x04,sf) == 0xFEFF); /* BOM (always LE on 3DS/Android) */ + if (big_endian) { + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + + version = read_16bit(0x06, sf); /* assumed */ + if (version != 0x06 && version != 0x07) /* v6 = NFS: The Run , v7 = F&F Showndown */ + goto fail; + + total_subsongs = read_32bit(0x08,sf); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + names_size = read_32bit(0x0c,sf); + /* 0x10/14: see below */ + /* 0x18: data size (all subsongs) */ + offset = 0x1c + names_size; /* skip names table */ + + /* the following 2 sections (rarely) won't match total_subsongs */ + + /* section1: unknown */ + { + size_t unknown_size = read_32bit(0x10,sf); + /* 0x00: usually 0, rarely 0x20? */ + offset += unknown_size*0x04; + } + + /* section2: samples */ + { + size_t samples_size = read_32bit(0x14,sf); + /* 0x00: num_samples */ + offset += samples_size*0x04; + } + + /* section3: headers */ + { + off_t header_offset = offset+(target_subsong-1)*0x24; + + name_offset = read_32bit(header_offset+0x00, sf) + 0x1c; /* within name table */ + codec = read_32bit(header_offset+0x04, sf); + sample_rate = read_32bit(header_offset+0x08, sf); + channel_count = read_32bit(header_offset+0x0c, sf); + /* 0x10: index within section1/2? */ + /* 0x14: flags? 0x01 or (rarely) 0x02 */ + stream_offset = read_32bit(header_offset+0x18, sf); + stream_size = read_32bit(header_offset+0x1c, sf); /* including DSP config */ + num_samples = read_32bit(header_offset+0x20, sf) / channel_count; /* nibble/PCMs */ + + offset += total_subsongs*0x24; + } + + loop_flag = 0; + start_offset = offset + stream_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + vgmstream->meta_type = meta_WAVEBATCH; + + switch(codec) { + case 0x00: /* PCM16 [NASCAR Unleashed (3DS), Solar Flux Pocket (Android)] */ + vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + break; + + case 0x01: /* PCM8 [Cars 2 (3DS)] */ + vgmstream->coding_type = coding_PCM8; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x01; + break; + + case 0x02: { /* DSP [WRC FIA World Rally Championship (3DS)] */ + size_t config_size = (0x20+0x14)*channel_count + (0x0c)*channel_count; /* coefs+hist + padding */ + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = (stream_size - config_size) / channel_count; /* full interleave*/; + + dsp_read_coefs(vgmstream,sf,start_offset+0x00,0x20+0x14,big_endian); + dsp_read_hist (vgmstream,sf,start_offset+0x20,0x14+0x20,big_endian); + start_offset += config_size; + + break; + } + + default: + VGM_LOG("WAVEBATCH: unknown codec %x\n", codec); + goto fail; + } + + read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf); /* always null-terminated */ + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +}