1 module speech.audio.portaudio; 2 3 import speech.audio.exception : AudioException; 4 import deimos.portaudio; 5 6 shared static this() 7 { 8 paEnforce(Pa_Initialize()); 9 } 10 11 shared static ~this() 12 { 13 paEnforce(Pa_Terminate()); 14 } 15 16 class PortaudioException : AudioException 17 { 18 immutable PaError code; 19 20 this(PaError err, string file = __FILE__, uint line = __LINE__, Exception next = null) 21 { 22 import std.string : fromStringz; 23 this.code = err; 24 super(fromStringz(Pa_GetErrorText(err)).idup, file, line, next); 25 } 26 } 27 28 void paEnforce(PaError err, string file = __FILE__, uint line = __LINE__) 29 { 30 import std.string : fromStringz; 31 if(err != paNoError) 32 throw new PortaudioException(err, file, line); 33 } 34 35 struct Device 36 { 37 package(speech): 38 PaDeviceIndex index; 39 const(PaDeviceInfo)* info; 40 41 this(PaDeviceIndex index) 42 { 43 this.index = index; 44 this.info = Pa_GetDeviceInfo(index); 45 } 46 47 public: 48 string name() @property 49 { 50 import std.string : fromStringz; 51 return fromStringz(info.name).idup; 52 } 53 54 int maxInputChannels() @property 55 { 56 return info.maxInputChannels; 57 } 58 59 int maxOutputChannels() @property 60 { 61 return info.maxOutputChannels; 62 } 63 } 64 65 auto outputDevices() 66 { 67 import std.algorithm.iteration : filter, map; 68 import std.range : iota; 69 return iota(0, Pa_GetDeviceCount()).map!(devIndex => Device(devIndex)).filter!(dev => dev.maxOutputChannels > 0); 70 } 71 72 Device defaultOutputDevice() 73 { 74 return Device(Pa_GetDefaultOutputDevice()); 75 } 76