1 /++ 2 + Authors: Avaxar <avaxar@nekkl.org> 3 + Copyright: Copyright © 2023, Avaxar 4 + License: $(LINK2 https://mit-license.org, MIT License) 5 +/ 6 7 module dsdl2.audio; 8 @safe: 9 10 import bindbc.sdl; 11 import dsdl2.sdl; 12 13 import core.memory : GC; 14 import std.conv : to; 15 import std.format : format; 16 import std.string : toStringz; 17 18 /++ 19 + D enum that wraps `SDL_AudioFormat` defining scalar type per audio sample 20 +/ 21 enum AudioFormat { 22 /++ 23 + Wraps `AUDIO_*` enumeration constants 24 +/ 25 u8 = AUDIO_U8, 26 s8 = AUDIO_S8, /// ditto 27 u16LSB = AUDIO_U16LSB, /// ditto 28 s16LSB = AUDIO_S16LSB, /// ditto 29 u16MSB = AUDIO_U16MSB, /// ditto 30 s16MSB = AUDIO_S16MSB, /// ditto 31 u16 = AUDIO_U16, /// ditto 32 s16 = AUDIO_S16, /// ditto 33 s32LSB = AUDIO_S32LSB, /// ditto 34 s32MSB = AUDIO_S32MSB, /// ditto 35 s32 = AUDIO_S32, /// ditto 36 f32LSB = AUDIO_F32LSB, /// ditto 37 f32MSB = AUDIO_F32MSB, /// ditto 38 f32 = AUDIO_F32, /// ditto 39 40 u16Sys = AUDIO_U16SYS, /// ditto 41 s16Sys = AUDIO_S16SYS, /// ditto 42 s32Sys = AUDIO_S32SYS, /// ditto 43 f32Sys = AUDIO_F32SYS /// ditto 44 } 45 46 /++ 47 + D enum that wraps `SDL_AUDIO_*` status enumerations 48 +/ 49 enum AudioStatus { 50 /++ 51 + Wraps `SDL_AUDIO_*` enumeration constants 52 +/ 53 stopped = SDL_AUDIO_STOPPED, 54 playing = SDL_AUDIO_PLAYING, /// ditto 55 paused = SDL_AUDIO_PAUSED /// ditto 56 } 57 58 enum maxVolume = cast(ubyte) SDL_MIX_MAXVOLUME; /// Alias to `SDL_MIX_MAXVOLUME` 59 60 /++ 61 + Wraps `SDL_AudioInit` which initializes the audio subsystem while specifying the audio driver used 62 + 63 + Params: 64 + driverName = the name of the audio driver 65 + Throws: `dsdl2.SDLException` if the audio driver could not be initialized 66 +/ 67 void initAudio(string driverName) @trusted { 68 if (SDL_AudioInit(driverName.toStringz()) != 0) { 69 throw new SDLException; 70 } 71 } 72 73 /++ 74 + Wraps `SDL_AudioQuit` which quits the audio subsystem 75 +/ 76 void quitAudio() @trusted { 77 SDL_AudioQuit(); 78 } 79 80 /++ 81 + Wraps `SDL_GetNumAudioDrivers` and `SDL_GetAudioDriver` which return a list of available audio drivers 82 + 83 + Returns: names of the available audio drivers 84 + Throws: `dsdl2.SDLException` if failed to get the available audio drivers 85 +/ 86 const(string[]) getAudioDrivers() @trusted { 87 int numDrivers = SDL_GetNumAudioDrivers(); 88 if (numDrivers <= 0) { 89 throw new SDLException; 90 } 91 92 static string[] drivers; 93 if (drivers !is null) { 94 size_t originalLength = drivers.length; 95 drivers.length = numDrivers; 96 97 if (numDrivers > originalLength) { 98 foreach (i; originalLength .. numDrivers) { 99 drivers[i] = SDL_GetAudioDriver(i.to!int).to!string; 100 } 101 } 102 } 103 else { 104 drivers = new string[](numDrivers); 105 106 foreach (i; 0 .. numDrivers) { 107 drivers[i] = SDL_GetAudioDriver(i).to!string; 108 } 109 } 110 111 return drivers; 112 } 113 114 /++ 115 + Wraps `SDL_GetCurrentAudioDriver` which returns the current audio driver 116 + 117 + Returns: name of the current audio driver 118 +/ 119 string getCurrentAudioDriver() @trusted { 120 return SDL_GetCurrentAudioDriver().to!string; 121 } 122 123 // TODO 124 struct AudioSpec { 125 SDL_AudioSpec sdlAudioSpec; /// Internal `SDL_AudioSpec` struct 126 } 127 128 // TODO 129 final class AudioDevice { 130 const SDL_AudioDeviceID sdlAudioDeviceID; /// Internal `SDL_AudioDeviceID` 131 } 132 133 private const(string[]) getAudioDeviceNamesRaw(int isCapture)() @trusted { 134 int numDrivers = SDL_GetNumAudioDevices(isCapture); 135 if (numDrivers <= 0) { 136 throw new SDLException; 137 } 138 139 static string[] drivers; 140 if (drivers !is null) { 141 size_t originalLength = drivers.length; 142 drivers.length = numDrivers; 143 144 if (numDrivers > originalLength) { 145 foreach (i; originalLength .. numDrivers) { 146 drivers[i] = SDL_GetAudioDeviceName(i.to!int, isCapture).to!string; 147 } 148 } 149 } 150 else { 151 drivers = new string[](numDrivers); 152 153 foreach (i; 0 .. numDrivers) { 154 drivers[i] = SDL_GetAudioDeviceName(i, isCapture).to!string; 155 } 156 } 157 158 return drivers; 159 } 160 161 /++ 162 + Acts as `SDL_GetNumAudioDevices(0)` and `SDL_GetAudioDeviceName(..., 0)` which return a name list of available 163 + non-capturing audio devices 164 + 165 + Returns: names of the available non-capturing audio devices 166 + Throws: `dsdl2.SDLException` if failed to get the available non-capturing audio devices 167 +/ 168 const(string[]) getAudioDeviceNames() @trusted { 169 return getAudioDeviceNamesRaw!0; 170 } 171 172 /++ 173 + Acts as `SDL_GetNumAudioDevices(1)` and `SDL_GetAudioDeviceName(..., 1)` which return a name list of available 174 + capturing audio devices 175 + 176 + Returns: names of the available capturing audio devices 177 + Throws: `dsdl2.SDLException` if failed to get the available capturing audio devices 178 +/ 179 const(string[]) getCapturingAudioDeviceNames() @trusted { 180 return getAudioDeviceNamesRaw!1; 181 } 182 183 /++ 184 + Wraps `SDL_OpenAudio` which opens the default audio device 185 + 186 + Params: 187 + desired = desired `dsdl2.AudioSpec`ifications 188 + Returns: obtained `dsdl2.AudioSpec`ifications 189 +/ 190 AudioSpec openAudio(AudioSpec desired) @trusted { 191 // TODO: implement handling for `AudioSpec` 192 assert(false, "Not implemented"); 193 } 194 195 /++ 196 + Wraps `SDL_CloseAudio` which closes the default audio device 197 +/ 198 void closeAudio() @trusted { 199 SDL_CloseAudio(); 200 } 201 202 /++ 203 + Wraps `SDL_GetAudioStatus` which returns the current status of the default audio device 204 + 205 + Returns: `dsdl2.AudioStatus` of the default audio device 206 +/ 207 AudioStatus getAudioStatus() @trusted { 208 return cast(AudioStatus) SDL_GetAudioStatus(); 209 } 210 211 /++ 212 + Wraps `SDL_PauseAudio` which pauses the default audio device 213 + 214 + Params: 215 + paused = `true` to pause by default; `false` to resume 216 +/ 217 void pauseAudio(bool paused = true) @trusted { 218 SDL_PauseAudio(paused ? 1 : 0); 219 } 220 221 /++ 222 + Acts as `SDL_PauseAudio(0)` which resumes the default audio device 223 +/ 224 void resumeAudio() @trusted { 225 SDL_PauseAudio(0); 226 } 227 228 /++ 229 + Wraps `SDL_LockAudio` which locks the default audio device 230 +/ 231 void lockAudio() @trusted { 232 SDL_LockAudio(); 233 } 234 235 /++ 236 + Wraps `SDL_UnlockAudio` which unlocks the default audio device 237 +/ 238 void unlockAudio() @trusted { 239 SDL_UnlockAudio(); 240 }