1 /+
2 +            Copyright 2022 – 2024 Aya Partridge
3 +          Copyright 2018 - 2022 Michael D. Parker
4 + Distributed under the Boost Software License, Version 1.0.
5 +     (See accompanying file LICENSE_1_0.txt or copy at
6 +           http://www.boost.org/LICENSE_1_0.txt)
7 +/
8 module sdl.audio;
9 
10 import bindbc.sdl.config;
11 import bindbc.sdl.codegen;
12 
13 import sdl.rwops;
14 
15 enum: ushort{
16 	SDL_AUDIO_MASK_BITSIZE   = 0xFF,
17 	SDL_AUDIO_MASK_DATATYPE  = 1<<8,
18 	SDL_AUDIO_MASK_ENDIAN    = 1<<12,
19 	SDL_AUDIO_MASK_SIGNED    = 1<<15,
20 }
21 
22 pragma(inline, true) nothrow @nogc pure @safe{
23 	SDL_AudioFormat SDL_AUDIO_BITSIZE(SDL_AudioFormat x){ return cast(SDL_AudioFormat)(x & SDL_AUDIO_MASK_BITSIZE); }
24 	SDL_AudioFormat SDL_AUDIO_ISFLOAT(SDL_AudioFormat x){ return cast(SDL_AudioFormat)(x & SDL_AUDIO_MASK_DATATYPE); }
25 	SDL_AudioFormat SDL_AUDIO_ISBIGENDIAN(SDL_AudioFormat x){ return cast(SDL_AudioFormat)(x & SDL_AUDIO_MASK_ENDIAN); }
26 	SDL_AudioFormat SDL_AUDIO_ISSIGNED(SDL_AudioFormat x){ return cast(SDL_AudioFormat)(x & SDL_AUDIO_MASK_SIGNED); }
27 	bool SDL_AUDIO_ISINT(SDL_AudioFormat x){ return !SDL_AUDIO_ISFLOAT(x); }
28 	bool SDL_AUDIO_ISLITTLEENDIAN(SDL_AudioFormat x){ return !SDL_AUDIO_ISBIGENDIAN(x); }
29 	bool SDL_AUDIO_ISUNSIGNED(SDL_AudioFormat x){ return !SDL_AUDIO_ISSIGNED(x); }
30 }
31 deprecated("Please use the non-template variant instead"){
32 	enum SDL_AUDIO_BITSIZE(SDL_AudioFormat x)         = x & SDL_AUDIO_MASK_BITSIZE;
33 	enum SDL_AUDIO_ISFLOAT(SDL_AudioFormat x)         = x & SDL_AUDIO_MASK_DATATYPE;
34 	enum SDL_AUDIO_ISBIGENDIAN(SDL_AudioFormat x)     = x & SDL_AUDIO_MASK_ENDIAN;
35 	enum SDL_AUDIO_ISSIGNED(SDL_AudioFormat x)        = x & SDL_AUDIO_MASK_SIGNED;
36 	enum SDL_AUDIO_ISINT(SDL_AudioFormat x)           = !SDL_AUDIO_ISFLOAT(x);
37 	enum SDL_AUDIO_ISLITTLEENDIAN(SDL_AudioFormat x)  = !SDL_AUDIO_ISBIGENDIAN(x);
38 	enum SDL_AUDIO_ISUNSIGNED(SDL_AudioFormat x)      = !SDL_AUDIO_ISSIGNED(x);
39 }
40 
41 alias SDL_AudioFormat = ushort;
42 enum: SDL_AudioFormat{
43 	AUDIO_U8      = 0x0008,
44 	AUDIO_S8      = 0x8008,
45 	AUDIO_U16LSB  = 0x0010,
46 	AUDIO_S16LSB  = 0x8010,
47 	AUDIO_U16MSB  = 0x1010,
48 	AUDIO_S16MSB  = 0x9010,
49 	AUDIO_U16     = AUDIO_U16LSB,
50 	AUDIO_S16     = AUDIO_S16LSB,
51 	AUDIO_S32LSB  = 0x8020,
52 	AUDIO_S32MSB  = 0x9020,
53 	AUDIO_S32     = AUDIO_S32LSB,
54 	AUDIO_F32LSB  = 0x8120,
55 	AUDIO_F32MSB  = 0x9120,
56 	AUDIO_F32     = AUDIO_F32LSB,
57 }
58 
59 version(LittleEndian){
60 	alias AUDIO_U16SYS  = AUDIO_U16LSB;
61 	alias AUDIO_S16SYS  = AUDIO_S16LSB;
62 	alias AUDIO_S32SYS  = AUDIO_S32LSB;
63 	alias AUDIO_F32SYS  = AUDIO_F32LSB;
64 }else{
65 	alias AUDIO_U16SYS  = AUDIO_U16MSB;
66 	alias AUDIO_S16SYS  = AUDIO_S16MSB;
67 	alias AUDIO_S32SYS  = AUDIO_S32MSB;
68 	alias AUDIO_F32SYS  = AUDIO_F32MSB;
69 }
70 
71 enum{
72 	SDL_AUDIO_ALLOW_FREQUENCY_CHANGE  = 0x00000001,
73 	SDL_AUDIO_ALLOW_FORMAT_CHANGE     = 0x00000002,
74 	SDL_AUDIO_ALLOW_CHANNELS_CHANGE   = 0x00000004,
75 }
76 static if(sdlSupport >= SDLSupport.v2_0_9)
77 enum{
78 	SDL_AUDIO_ALLOW_SAMPLES_CHANGE    = 0x00000008,
79 	SDL_AUDIO_ALLOW_ANY_CHANGE        =
80 		SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_FORMAT_CHANGE |
81 		SDL_AUDIO_ALLOW_CHANNELS_CHANGE  | SDL_AUDIO_ALLOW_SAMPLES_CHANGE,
82 }
83 else
84 enum{
85 	SDL_AUDIO_ALLOW_ANY_CHANGE        =
86 		SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_FORMAT_CHANGE |
87 		SDL_AUDIO_ALLOW_CHANNELS_CHANGE,
88 }
89 
90 alias SDL_AudioCallback = extern(C) void function(void* userData, ubyte* stream, int len) nothrow;
91 
92 struct SDL_AudioSpec{
93 	int freq;
94 	SDL_AudioFormat format;
95 	ubyte channels;
96 	ubyte silence;
97 	ushort samples;
98 	ushort padding;
99 	uint size;
100 	SDL_AudioCallback callback;
101 	void* userdata;
102 }
103 
104 //Declared in 2.0.6
105 enum SDL_AUDIOCVT_MAX_FILTERS = 9;
106 
107 alias SDL_AudioFilter = extern(C) void function(SDL_AudioCVT* cvt, SDL_AudioFormat format) nothrow;
108 
109 struct SDL_AudioCVT{
110 	int needed;
111 	SDL_AudioFormat src_format;
112 	SDL_AudioFormat dst_format;
113 	double rate_incr;
114 	ubyte* buf;
115 	int len;
116 	int len_cvt;
117 	int len_mult;
118 	double len_ratio;
119 	SDL_AudioFilter[SDL_AUDIOCVT_MAX_FILTERS + 1] filters;
120 	int filter_index;
121 }
122 
123 alias SDL_AudioDeviceID = uint;
124 
125 alias SDL_AudioStatus = int;
126 enum: SDL_AudioStatus{
127 	SDL_AUDIO_STOPPED  = 0,
128 	SDL_AUDIO_PLAYING  = 1,
129 	SDL_AUDIO_PAUSED   = 2,
130 }
131 
132 pragma(inline, true) SDL_AudioSpec* SDL_LoadWAV(const(char)* file, SDL_AudioSpec* spec, ubyte** audioBuf, uint* len) nothrow @nogc{
133 	return SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1, spec, audioBuf, len);
134 }
135 
136 static if(sdlSupport >= SDLSupport.v2_0_7){
137 	struct SDL_AudioStream;
138 }
139 
140 enum SDL_MIX_MAXVOLUME = 128;
141 
142 mixin(joinFnBinds((){
143 	FnBind[] ret = [
144 		{q{int}, q{SDL_GetNumAudioDrivers}, q{}},
145 		{q{const(char)*}, q{SDL_GetAudioDriver}, q{int index}},
146 		{q{int}, q{SDL_AudioInit}, q{const(char)* driverName}},
147 		{q{void}, q{SDL_AudioQuit}, q{}},
148 		{q{const(char)*}, q{SDL_GetCurrentAudioDriver}, q{}},
149 		{q{int}, q{SDL_OpenAudio}, q{SDL_AudioSpec* desired, SDL_AudioSpec* obtained}},
150 		{q{int}, q{SDL_GetNumAudioDevices}, q{int isCapture}},
151 		{q{const(char)*}, q{SDL_GetAudioDeviceName}, q{int index, int isCapture}},
152 		{q{SDL_AudioDeviceID}, q{SDL_OpenAudioDevice}, q{const(char)* device, int isCapture, const(SDL_AudioSpec)* desired, SDL_AudioSpec* obtained, int allowedChanges}},
153 		{q{SDL_AudioStatus}, q{SDL_GetAudioStatus}, q{}},
154 		{q{SDL_AudioStatus}, q{SDL_GetAudioDeviceStatus}, q{SDL_AudioDeviceID dev}},
155 		{q{void}, q{SDL_PauseAudio}, q{int pauseOn}},
156 		{q{void}, q{SDL_PauseAudioDevice}, q{SDL_AudioDeviceID dev, int pauseOn}},
157 		{q{SDL_AudioSpec*}, q{SDL_LoadWAV_RW}, q{SDL_RWops* src, int freeSrc, SDL_AudioSpec* spec, ubyte** audioBuf, uint* audioLen}},
158 		{q{void}, q{SDL_FreeWAV}, q{ubyte* audioBuf}},
159 		{q{int}, q{SDL_BuildAudioCVT}, q{SDL_AudioCVT* cvt, SDL_AudioFormat srcFormat, ubyte srcChannels, int srcRate, SDL_AudioFormat dstFormat, ubyte dstChannels, int dstRate}},
160 		{q{int}, q{SDL_ConvertAudio}, q{SDL_AudioCVT* cvt}},
161 		{q{void}, q{SDL_MixAudio}, q{ubyte* dst, const(ubyte)* src, uint len, int volume}},
162 		{q{void}, q{SDL_MixAudioFormat}, q{ubyte* dst, const(ubyte)* src, SDL_AudioFormat format, uint len, int volume}},
163 		{q{void}, q{SDL_LockAudio}, q{}},
164 		{q{void}, q{SDL_LockAudioDevice}, q{SDL_AudioDeviceID dev}},
165 		{q{void}, q{SDL_UnlockAudio}, q{}},
166 		{q{void}, q{SDL_UnlockAudioDevice}, q{SDL_AudioDeviceID dev}},
167 		{q{void}, q{SDL_CloseAudio}, q{}},
168 		{q{void}, q{SDL_CloseAudioDevice}, q{SDL_AudioDeviceID dev}},
169 	];
170 	if(sdlSupport >= SDLSupport.v2_0_4){
171 		FnBind[] add = [
172 			{q{int}, q{SDL_QueueAudio}, q{SDL_AudioDeviceID dev, const(void)* data, uint len}},
173 			{q{int}, q{SDL_ClearQueuedAudio}, q{SDL_AudioDeviceID dev}},
174 			{q{int}, q{SDL_GetQueuedAudioSize}, q{SDL_AudioDeviceID dev}},
175 		];
176 		ret ~= add;
177 	}
178 	if(sdlSupport >= SDLSupport.v2_0_5){
179 		FnBind[] add = [
180 			{q{uint}, q{SDL_DequeueAudio}, q{SDL_AudioDeviceID dev, void* data, uint len}},
181 		];
182 		ret ~= add;
183 	}
184 	if(sdlSupport >= SDLSupport.v2_0_7){
185 		FnBind[] add = [
186 			{q{SDL_AudioStream*}, q{SDL_NewAudioStream}, q{const SDL_AudioFormat srcFormat, const ubyte srcChannels, const int srcRate, const SDL_AudioFormat dstFormat, const ubyte dstChannels, const int dstRate}},
187 			{q{int}, q{SDL_AudioStreamPut}, q{SDL_AudioStream* stream, const(void)* buf, int len}},
188 			{q{int}, q{SDL_AudioStreamGet}, q{SDL_AudioStream* stream, void* buf, int len}},
189 			{q{int}, q{SDL_AudioStreamAvailable}, q{SDL_AudioStream* stream}},
190 			{q{int}, q{SDL_AudioStreamFlush}, q{SDL_AudioStream* stream}},
191 			{q{void}, q{SDL_AudioStreamClear}, q{SDL_AudioStream* stream}},
192 			{q{void}, q{SDL_FreeAudioStream}, q{SDL_AudioStream* stream}},
193 		];
194 		ret ~= add;
195 	}
196 	if(sdlSupport >= SDLSupport.v2_0_16){
197 		FnBind[] add = [
198 			{q{int}, q{SDL_GetAudioDeviceSpec}, q{int index, int isCapture, SDL_AudioSpec* spec}},
199 		];
200 		ret ~= add;
201 	}
202 	if(sdlSupport >= SDLSupport.v2_24){
203 		FnBind[] add = [
204 			{q{int}, q{SDL_GetDefaultAudioInfo}, q{char** name, SDL_AudioSpec* spec, int isCapture}},
205 		];
206 		ret ~= add;
207 	}
208 	return ret;
209 }()));