diff --git a/src/meta/wave.c b/src/meta/wave.c index 921c8a71..c22d2efa 100644 --- a/src/meta/wave.c +++ b/src/meta/wave.c @@ -8,7 +8,6 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) { uint32_t start_offset, extradata_offset, interleave; int channels, loop_flag, sample_rate, codec, version; int32_t num_samples, loop_start, loop_end; - int big_endian; read_u32_t read_u32; read_s32_t read_s32; read_f32_t read_f32; @@ -25,7 +24,7 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) { if (!check_extensions(sf, "wave")) return NULL; - big_endian = read_u32be(0x00,sf) == 0xE5B7ECFE || is_id32be(0x00,sf, "WWAV"); + bool big_endian = read_u32be(0x00,sf) == 0xE5B7ECFE || is_id32be(0x00,sf, "WWAV"); if (big_endian) { read_u32 = read_u32be; read_s32 = read_s32be; @@ -46,7 +45,7 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) { loop_end = read_s32(0x18, sf); codec = read_u8(0x1c, sf); - channels = read_u8(0x1d, sf); + channels = read_u8(0x1d, sf); // DS can only do mono if (read_u8(0x1e, sf) != 0x00) goto fail; /* unknown */ if (read_u8(0x1f, sf) != 0x00) goto fail; /* unknown */ @@ -60,14 +59,19 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) { if(!loop_flag && loop_start == 0 && loop_end == num_samples /* full loop */ && (channels > 1 || (channels == 1 && start_offset <= 0x40)) - && num_samples > 30*sample_rate) { /* in seconds */ + && num_samples > 30 * sample_rate) { /* in seconds */ loop_flag = 1; } - /* normalize codec: WWAV uses codec 0x00 for DSP */ + /* normalize codec (files generated by DsBuildWave/3dsBuildWave) */ if (codec == 0x00 && version == 0x00050000 && start_offset > 0x40) { + /* WWAV uses codec 0x00 for DSP (only one?) */ codec = 0x02; } + else if (codec == 0x02 && start_offset <= 0x40) { + /* DS games use IMA, no apparent flag (could also test ID) */ + codec = 0x03; + } /* build the VGMSTREAM */ @@ -81,39 +85,51 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) { vgmstream->meta_type = meta_WAVE; - /* not sure if there are other codecs but anyway (based on wave-segmented) */ + /* some codecs aren't used by known games but can be created by DsBuildWave/3dsBuildWave */ switch(codec) { - case 0x02: - /* DS games use IMA, no apparent flag (could also test ID) */ - if (start_offset <= 0x40) { - vgmstream->coding_type = coding_IMA_int; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - - /* extradata: - * 0x00: base hist? (only seen 0) - * 0x02: base step? (only seen 0) - * 0x04: loop hist? - * 0x06: loop step? - */ - } - else { - 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 */ - int head_spacing = 0x2c; - int hist_spacing = 0x22; - if (version == 0x00050000) { /* has an extra empty 16b after coefs */ - head_spacing = 0x2e; - hist_spacing = 0x24; - } - - dsp_read_coefs(vgmstream, sf, extradata_offset + 0x00, head_spacing, big_endian); - dsp_read_hist(vgmstream, sf, extradata_offset + hist_spacing, head_spacing, big_endian); - } + case 0x00: // PCM8 (not seen) + vgmstream->coding_type = coding_PCM8; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; break; + + case 0x01: // PCM16 (not seen) + vgmstream->coding_type = coding_PCM16BE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + break; + + case 0x02: { // DSP (3DS only, common) + 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 */ + int head_spacing = 0x2c; + int hist_spacing = 0x22; + if (version == 0x00050000) { /* has an extra empty 16b after coefs */ + head_spacing = 0x2e; + hist_spacing = 0x24; + } + + dsp_read_coefs(vgmstream, sf, extradata_offset + 0x00, head_spacing, big_endian); + dsp_read_hist(vgmstream, sf, extradata_offset + hist_spacing, head_spacing, big_endian); + break; + } + + case 0x03: //IMA (DS uses codec 02 for IMA, common; 3DS: uses 03 but not seen) + vgmstream->coding_type = coding_IMA_int; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + /* extradata: + * 0x00: base hist? (only seen 0) + * 0x02: base step? (only seen 0) + * 0x04: loop hist? + * 0x06: loop step? + */ + break; + default: goto fail; }