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 }