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 }