#include "meta.h" #include "../coding/coding.h" /* .WAVE - WayForward "EngineBlack" games [Mighty Switch Force! (3DS), Adventure Time: Hey Ice King! Why'd You Steal Our Garbage?! (3DS)] */ VGMSTREAM * init_vgmstream_wave(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset, extradata_offset; int loop_flag = 0, channel_count, sample_rate, codec; int32_t num_samples, loop_start = 0, loop_end = 0; size_t interleave; int big_endian; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; //int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; /* checks */ if (!check_extensions(streamFile, "wave")) goto fail; if (read_32bitLE(0x00,streamFile) != 0xE5B7ECFE && /* header id */ read_32bitBE(0x00,streamFile) != 0xE5B7ECFE) goto fail; if (read_32bitBE(0x04,streamFile) != 0x00) /* version? */ goto fail; /* assumed */ big_endian = read_32bitBE(0x00,streamFile) == 0xE5B7ECFE; if (big_endian) { read_32bit = read_32bitBE; //read_16bit = read_16bitBE; } else { read_32bit = read_32bitLE; //read_16bit = read_16bitLE; } channel_count = read_8bit(0x05,streamFile); if (read_32bit(0x08,streamFile) != get_streamfile_size(streamFile)) goto fail; if (read_8bit(0x0c,streamFile) != 0x00) /* ? */ goto fail; /* sample rate in 32b float (WHY?)*/ { uint32_t sample_int = (uint32_t)read_32bit(0x0c, streamFile); float* sample_float; sample_float = (float*)&sample_int; sample_rate = (int)(*sample_float); } num_samples = read_32bit(0x10, streamFile); loop_start = read_32bit(0x14, streamFile); loop_end = read_32bit(0x18, streamFile); codec = read_8bit(0x1c, streamFile); channel_count = read_8bit(0x1d, streamFile); if (read_8bit(0x1e, streamFile) != 0x00) goto fail; /* unknown */ if (read_8bit(0x1f, streamFile) != 0x00) goto fail; /* unknown */ start_offset = read_32bit(0x20, streamFile); interleave = read_32bit(0x24, streamFile); /* typically half data_size */ extradata_offset = read_32bit(0x28, streamFile); /* OR: extradata size (0x2c) */ loop_flag = (loop_start > 0); /* some songs (ex. Adventure Time's m_candykingdom_overworld.wave) do full loops, but there is no way * to tell them apart from sfx/voices, so we try to detect if it's long enough. */ if(!loop_flag && loop_start == 0 && loop_end == num_samples /* full loop */ && channel_count > 1 && num_samples > 20*sample_rate) { /* in seconds */ loop_flag = 1; } /* 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->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; vgmstream->meta_type = meta_WAVE; /* not sure if there are other codecs but anyway */ switch(codec) { case 0x02: vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = interleave; /* ADPCM setup: 0x20 coefs + 0x06 initial ps/hist1/hist2 + 0x06 loop ps/hist1/hist2, per channel */ dsp_read_coefs(vgmstream, streamFile, extradata_offset+0x00, 0x2c, big_endian); dsp_read_hist(vgmstream, streamFile, extradata_offset+0x22, 0x2c, big_endian); break; default: goto fail; } if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) goto fail; return vgmstream; fail: close_vgmstream(vgmstream); return NULL; }