1 /** 2 * 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; 15 16 import std.algorithm; 17 import std.conv; 18 import std.range; 19 20 struct ValueReprRange(T) 21 { 22 ubyte[T.sizeof] bytes; 23 size_t p; 24 25 this(ref T t) 26 { 27 bytes[] = (cast(ubyte[])((&t)[0..1]))[]; 28 } 29 30 @property ubyte front() { return bytes[p]; } 31 void popFront() { p++; } 32 @property bool empty() { return p == T.sizeof; } 33 @property size_t length() { return T.sizeof - p; } 34 } 35 36 auto valueReprRange(T)(auto ref T t) { return ValueReprRange!T(t); } 37 38 auto fourCC(char[4] name) 39 { 40 return valueReprRange(name); 41 } 42 43 auto riffChunk(R)(char[4] name, R data) 44 { 45 return chain( 46 fourCC(name), 47 valueReprRange(data.length.to!uint), 48 data 49 ); 50 } 51 52 struct WaveFmt 53 { 54 ushort format; 55 ushort numChannels; 56 uint sampleRate; 57 uint byteRate; 58 ushort blockAlign; 59 ushort bitsPerSample; 60 } 61 62 auto makeRiff(R)(R r, uint sampleRate = 44100) 63 { 64 static if (!is(typeof(r.front) == struct)) 65 { 66 struct Mono { typeof(r.front) sample; } 67 return makeRiff(r.map!(s => Mono(s)), sampleRate); 68 } 69 else 70 { 71 enum numChannels = r.front.tupleof.length; 72 auto bytesPerSample = r.front.tupleof[0].sizeof; 73 auto bitsPerSample = bytesPerSample * 8; 74 75 return riffChunk("RIFF", 76 chain( 77 fourCC("WAVE"), 78 riffChunk("fmt ", 79 valueReprRange(WaveFmt( 80 1, // PCM 81 to!ushort(numChannels), 82 sampleRate, 83 to!uint (sampleRate * bytesPerSample * numChannels), 84 to!ushort(bytesPerSample * numChannels), 85 to!ushort(bitsPerSample), 86 )), 87 ), 88 riffChunk("data", 89 r.map!(s => valueReprRange(s)).joiner.takeExactly(r.length * r.front.sizeof), 90 ), 91 ), 92 ); 93 } 94 }