1 module iota.audio.types;
2 
3 public import core.time : Duration;
4 
5 /** 
6  * Defines audio driver types.
7  */
8 enum DriverType {
9 	None,			///No driver have been initialized, etc.
10 	WASAPI,			///Windows Audio Stream API
11 	DirectAudio,	///Direct Audio API (Legacy)
12 	ALSA,			///Advanced Linux Sound Architecture
13 	JACK,			///JACK Audio Connection Kit
14 }
15 version (Windows) {
16 	static immutable DriverType OS_PREFERRED_DRIVER = DriverType.WASAPI;
17 } else version (linux) {
18 	static immutable DriverType OS_PREFERRED_DRIVER = DriverType.ALSA;
19 } else {
20 	static immutable DriverType OS_PREFERRED_DRIVER = DriverType.None;
21 }
22 /** 
23  * Defines audio initialization status codes.
24  */
25 enum AudioInitializationStatus {
26 	AllOk		=	0,		///No issues were encountered during initialization
27 	OSNotSupported,			///OS doesn't support this driver
28 	DriverNotAvailable,		///Driver is not available
29 	UninitializedDriver,	///Driver has not been initialized
30 	NoAudioDeviceFound,		///No audio device was found
31 	DeviceNotFound,			///Specified device cannot be found
32 	InternalError,			///Error likely due to this library
33 	OutOfMemory,			///Not enough memory to initialize driver
34 	Unknown,				///Error cannot be defined
35 }
36 /** 
37  * Defines stream initialization status codes.
38  */
39 enum StreamInitializationStatus {
40 	AllOk		=	0,		///No issues were encountered during initialization
41 	NoAudioService,			///Audio service not found
42 	OutOfMemory,			///Not enough memory to initialize stream
43 	UnsupportedFormat,		///Format isn't supported
44 	ModeNotSupported,		///Mode not supported
45 	DeviceInUse,			///Audio device is either in exclusive mode by another library, or can't get exclusive mode
46 	DeviceNotFound,			///Specified device cannot be found (e.g. got disconnected)
47 	InternalError,			///Error likely due to this library
48 	Unknown,				///Error cannot be defined
49 }
50 /**
51  * Defines stream execution status codes.
52  */
53 enum StreamRuntimeStatus {
54 	AllOk		=	0,		///No issues were encountered during startup of runtime
55 	BufferUnderrun,			///During runtime, a buffer underrun event happened
56 	BufferCallbackNotSet,	///The buffer callback wasn't set up
57 	DeviceNotFound,			///Specified device cannot be found (e.g. got disconnected)
58 	NoAudioService,			///Audio service not found
59 	InternalError,			///Error likely due to this library
60 	Unknown,				///Unexpected error code
61 }
62 /** 
63  * Defines an audio sample format for streams.
64  */
65 public struct SampleFormat {
66 	/// The number of bits for each sample.
67 	ubyte		bits;
68 	/// Flags that define the properties of the format.
69 	ubyte		flags;
70 	public enum Flag : ubyte {
71 		Type_Unknown		=	0x0,	/// Indicates either an unknown, or a format not directly supported by iota.
72 		Type_Unsigned		=	0x1,	/// Unsigned integer
73 		Type_Signed			=	0x2,	/// Signed integer
74 		Type_Float			=	0x3,	/// Floating-point
75 		/// To test types in branching
76 		Type_Test			=	0x3,
77 		/// Set if format is big endian
78 		BigEndian			=	0x4,
79 		/// Set if format is padded to whole byte boundary
80 		PaddedToByte		=	0x8,
81 		/// Set if format is padded to word (16/32/64 bit etc.) boundary
82 		PaddedToWord		=	0x10,
83 		/// Set if type is emulated
84 		IsEmulated			=	0x20,
85 	}
86 	/// Compression type, or zero if uncompressed.
87 	ubyte		cmprType;
88 	/// Auxilliary byte for padding, compression parameters, etc.
89 	ubyte		aux;
90 	/** 
91 	 * Returns true if format is in native endian format.
92 	 */
93 	public bool isNativeEndian() @nogc @safe pure nothrow const {
94 		version (LittleEndian)
95 			return (flags & Flag.BigEndian) == 0;
96 		else
97 			return (flags & Flag.BigEndian) != 0;
98 	}
99 }
100 /**
101  * Contains commonly used predefined formats.
102  */
103 public immutable SampleFormat[] predefinedFormats = [
104 	//Little endian formats (does anyone still using big endian?)
105 	SampleFormat(0x08, 0x01, 0x00, 0x00),	//8 bit unsigned integer
106 	SampleFormat(0x08, 0x02, 0x00, 0x00),	//8 bit signed integer
107 	SampleFormat(0x10, 0x01, 0x00, 0x00),	//16 bit unsigned integer
108 	SampleFormat(0x10, 0x02, 0x00, 0x00),	//16 bit signed integer
109 	SampleFormat(0x18, 0x01, 0x00, 0x00),	//24 bit unsigned integer
110 	SampleFormat(0x18, 0x02, 0x00, 0x00),	//24 bit signed integer
111 	SampleFormat(0x18, 0x11, 0x00, 0x00),	//24 bit unsigned integer (padded to 32 bit word)
112 	SampleFormat(0x18, 0x12, 0x00, 0x00),	//24 bit signed integer (padded to 32 bit word)
113 	SampleFormat(0x20, 0x01, 0x00, 0x00),	//32 bit unsigned integer
114 	SampleFormat(0x20, 0x02, 0x00, 0x00),	//32 bit signed integer
115 	SampleFormat(0x20, 0x03, 0x00, 0x00),	//32 bit floating-point
116 ];
117 public enum PredefinedFormats {
118 	UI8,		//8 bit unsigned integer
119 	SI8,		//8 bit signed integer
120 	UI16,		//16 bit unsigned integer
121 	SI16,		//16 bit signed integer
122 	UI24UP,		//24 bit unsigned integer
123 	SI24UP,		//24 bit signed integer
124 	UI24,		//24 bit unsigned integer (padded to 32 bit word)
125 	SI24,		//24 bit signed integer (padded to 32 bit word)
126 	UI32,		//32 bit unsigned integer
127 	SI32,		//32 bit signed integer
128 	FP32,		//32 bit floating-point
129 }
130 /** 
131  * Used to set audio specifications, etc.
132  *
133  * Note on buffer length: When requesting, only one of the bufferSize parameters have to be set. If both are set, then
134  * `bufferSize_slmp` takes priority. If neither are set, then the library tries to request a recommended buffer size.
135  * On returning, both are set to reflect on the current specifications.
136  */
137 public struct AudioSpecs {
138 	/// The format of the audio
139 	SampleFormat	format;
140 	/// The sample rate of the specified stream.
141 	int				sampleRate;
142 	/// The number of input channels.
143 	short			inputChannels;
144 	/// The number of output channels.
145 	short			outputChannels;
146 	/// The length of the audio buffer in samples.
147 	/// See note on buffer length.
148 	uint			bufferSize_slmp;
149 	/// The length of the audio buffer in a given time.
150 	/// See note on buffer length.
151 	Duration		bufferSize_time;
152 	/** 
153 	 * Returns the number of bits per channel, including padding.
154 	 */
155 	public uint bits() @nogc @safe pure nothrow const {
156 		uint result = format.bits;
157 		if (format.flags & format.Flag.PaddedToByte) {
158 			result += 8 - (format.bits % 8);
159 		} else if (format.flags & format.Flag.PaddedToWord) {
160 			result += 32 - (format.bits % 32);
161 		}
162 		return result;
163 	}
164 	/** 
165 	 * Mirrors the buffer sizes if one is set to T.init.
166 	 */
167 	public void mirrorBufferSizes() {
168 		import core.time : hnsecs;
169 		if (bufferSize_slmp) {
170 			bufferSize_time = hnsecs(cast(long)((1 / cast(real)sampleRate) * bufferSize_slmp * 10_000_000.0));
171 		} else if (cast(bool)bufferSize_time) {
172 			bufferSize_slmp = cast(uint)((bufferSize_time.total!"hnsecs" / 10_000_000.0) / (1 / cast(real)sampleRate));
173 		}
174 	}
175 	/**
176 	 * Returns a string representation of this struct.
177 	 */
178 	public string toString() const @safe { 
179 		import std.format : format;
180 		string result;
181 		result ~= format("%s bits ", this.format.bits);
182 		switch (this.format.flags & SampleFormat.Flag.Type_Test) {
183 			case SampleFormat.Flag.Type_Signed:
184 				result ~= "signed; ";
185 				break;
186 			case SampleFormat.Flag.Type_Unsigned:
187 				result ~= "unsigned; ";
188 				break;
189 			case SampleFormat.Flag.Type_Float:
190 				result ~= "floating point; ";
191 				break;
192 			default: break;
193 		}
194 		result ~= format("sample rate: %s Hz; ", sampleRate);
195 		result ~= format("input channels: %s ; ", inputChannels);
196 		result ~= format("output channels: %s ; ", outputChannels);
197 		result ~= format("buffer size (in samples): %s ; ", bufferSize_slmp);
198 		result ~= format("buffer size (in time): %s ms; ", (cast(real)bufferSize_time.total!"hnsecs" / 10_000.0));
199 		return result;
200 	}
201 }
202 /** 
203  * Tells the stream initializer which specs are needed, or tells it to recommend a spec.
204  */
205 public enum AudioSpecsInitFlags {
206 	init,
207 
208 	CloseBufferSize			=	1<<0,	///Buffer size won't be higher than the nearest power of two
209 	ExactBits				=	1<<1,	///Requests exactly the same number of bits (might be emulated)
210 	ExactFormat				=	1<<2,	///Requests exactly the same format (might be emulated)
211 	CloseSampleRate			=	1<<3,	///Requests a nearby sample rate
212 	ExactSampleRate			=	1<<4,	///Requests the exact sample rate
213 	ExactInputChannels		=	1<<5,	///Requests the exact number of input channels
214 	ExactOutputChannels		=	1<<6,	///Requests the exact number of output channels
215 
216 	UseRecommendedSpecs		=	-1,
217 	UseRecommendedHDSpecs	=	-2,
218 }
219 /** 
220  * Tells whether the audio stream is shared with other applications.
221  * Some drivers might work only in one mode, others can be switched.
222  */
223 public enum AudioShareMode : ubyte {
224 	Shared,
225 	Exlusive
226 }
227 /** 
228  * Defines MIDI initialization status codes.
229  */
230 public enum MIDIInitializationStatus {
231 	AllOk	=	0,		///No errors were encountered, operation was successful.
232 	DevicesNotFound,	///No devices are found.
233 	InitError,			///Initialization error otherwise not specified.
234 	OSNotSupported		///OS not (yet) supported.
235 }
236 /** 
237  * Defines MIDI device initialization status codes.
238  */
239 public enum MIDIDeviceInitStatus {
240 	AllOk	=	0,		///No errors were encountered, operation was successful.
241 	InvalidDeviceID,	///Invalid device ID.
242 	DeviceDisconnected,	///Device disconnected, or invalidated.
243 	InitError,			///Initialization error otherwise not specified.
244 	OutOfMemory,		///Out of memory error.
245 	OSNotSupported		///OS not (yet) supported.
246 }
247 /** 
248  * Defines MIDI device status codes.
249  */
250 public enum MIDIDeviceStatus {
251 	AllOk	=	0,		///No errors were encountered, operation was successful.
252 	DeviceDisconnected,	///Device disconnected, or invalidated.
253 }