1 /** 2 * Read support for the RIFF file format (used in .wav files). 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <vladimir@thecybershadow.net> 12 */ 13 14 module ae.utils.sound.riff.reader; 15 16 import std.algorithm.searching; 17 import std.exception; 18 19 import ae.utils.sound.riff.common; 20 21 struct Chunk 22 { 23 struct Header 24 { 25 char[4] name; 26 uint length; 27 ubyte[0] data; 28 } 29 30 Header* header; 31 32 this(ref ubyte[] data) 33 { 34 enforce(data.length >= Header.sizeof); 35 header = cast(Header*)data; 36 data = data[Header.sizeof..$]; 37 38 enforce(data.length >= header.length); 39 data = data[header.length..$]; 40 } 41 42 char[4] name() { return header.name; } 43 ubyte[] data() { return header.data.ptr[0..header.length]; } 44 } 45 46 struct Chunks 47 { 48 ubyte[] data; 49 bool empty() { return data.length == 0; } 50 Chunk front() { auto cData = data; return Chunk(cData); } 51 void popFront() { auto c = Chunk(data); } 52 } 53 54 auto readRiff(ubyte[] data) 55 { 56 return Chunk(data); 57 } 58 59 auto getWave(T)(Chunk chunk) 60 { 61 enforce(chunk.name == "RIFF", "Unknown file format"); 62 auto riffData = chunk.data; 63 enforce(riffData.skipOver("WAVE"), "Unknown RIFF contents"); 64 WaveFmt fmt = (cast(WaveFmt[])Chunks(riffData).find!(c => c.name == "fmt ").front.data)[0]; 65 enforce(fmt.format == 1, "Unknown WAVE format"); 66 enforce(fmt.sampleRate * T.sizeof == fmt.byteRate, "Format mismatch"); 67 auto data = Chunks(riffData).find!(c => c.name == "data").front.data; 68 return cast(T[])data; 69 }