1 /** 2 * Play waves using ALSA command-line tools 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.asound; 15 16 import std.conv; 17 import std.exception; 18 import std.process; 19 import std.range; 20 import std.traits; 21 22 /// Return the ALSA format name corresponding to the given type. 23 template aSoundFormat(T) 24 { 25 version(LittleEndian) 26 enum aSoundEndianness = "_LE"; 27 else 28 enum aSoundEndianness = "_BE"; 29 30 static if (is(T==ubyte)) 31 enum aSoundFormat = "U8"; 32 else 33 static if (is(T==byte)) 34 enum aSoundFormat = "S8"; 35 else 36 static if (is(T==ushort)) 37 enum aSoundFormat = "U16" ~ aSoundEndianness; 38 else 39 static if (is(T==short)) 40 enum aSoundFormat = "S16" ~ aSoundEndianness; 41 else 42 static if (is(T==uint)) 43 enum aSoundFormat = "U32" ~ aSoundEndianness; 44 else 45 static if (is(T==int)) 46 enum aSoundFormat = "S32" ~ aSoundEndianness; 47 else 48 static if (is(T==float)) 49 enum aSoundFormat = "FLOAT" ~ aSoundEndianness; 50 else 51 static if (is(T==double)) 52 enum aSoundFormat = "FLOAT64" ~ aSoundEndianness; 53 else 54 static assert(false, "Can't represent sample type in asound format: " ~ T.stringof); 55 } 56 57 void playWave(Wave)(Wave wave, int sampleRate = 44100) 58 { 59 alias Sample = typeof(wave.front); 60 auto p = pipe(); 61 auto pid = spawnProcess([ 62 "aplay", 63 "--format", aSoundFormat!Sample, 64 "--rate", text(sampleRate), 65 ], p.readEnd()); 66 while (!wave.empty) 67 { 68 Sample[1] s; 69 s[0] = wave.front; 70 wave.popFront(); 71 p.writeEnd.rawWrite(s[]); 72 } 73 p.writeEnd.close(); 74 enforce(pid.wait() == 0, "aplay failed"); 75 } 76 77 unittest 78 { 79 if (false) 80 playWave(iota(100)); 81 }