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 static if (is(Sample C : C[channels_], size_t channels_)) 61 { 62 alias ChannelSample = C; 63 enum channels = channels_; 64 } 65 else 66 { 67 alias ChannelSample = Sample; 68 enum channels = 1; 69 } 70 auto p = pipe(); 71 auto pid = spawnProcess([ 72 "aplay", 73 "--format", aSoundFormat!ChannelSample, 74 "--channels", text(channels), 75 "--rate", text(sampleRate), 76 ], p.readEnd()); 77 while (!wave.empty) 78 { 79 Sample[1] s; 80 s[0] = wave.front; 81 wave.popFront(); 82 p.writeEnd.rawWrite(s[]); 83 } 84 p.writeEnd.close(); 85 enforce(pid.wait() == 0, "aplay failed"); 86 } 87 88 unittest 89 { 90 if (false) 91 playWave(iota(100)); 92 }