1 /+
2 +            Copyright 2022 – 2023 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, but doesn't hurt to use here
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** audio_buf, uint* len) @nogc nothrow{
133 	return SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1, spec, audio_buf, 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 	string[][] ret;
144 	ret ~= makeFnBinds([
145 		[q{int}, q{SDL_GetNumAudioDrivers}, q{}],
146 		[q{const(char)*}, q{SDL_GetAudioDriver}, q{int index}],
147 		[q{int}, q{SDL_AudioInit}, q{const(char)* driver_name}],
148 		[q{void}, q{SDL_AudioQuit}, q{}],
149 		[q{const(char)*}, q{SDL_GetCurrentAudioDriver}, q{}],
150 		[q{int}, q{SDL_OpenAudio}, q{SDL_AudioSpec* desired, SDL_AudioSpec* obtained}],
151 		[q{int}, q{SDL_GetNumAudioDevices}, q{int iscapture}],
152 		[q{const(char)*}, q{SDL_GetAudioDeviceName}, q{int index, int iscapture}],
153 		[q{SDL_AudioDeviceID}, q{SDL_OpenAudioDevice}, q{const(char)* device, int iscapture, const(SDL_AudioSpec)* desired, SDL_AudioSpec* obtained, int allowed_changes}],
154 		[q{SDL_AudioStatus}, q{SDL_GetAudioStatus}, q{}],
155 		[q{SDL_AudioStatus}, q{SDL_GetAudioDeviceStatus}, q{SDL_AudioDeviceID dev}],
156 		[q{void}, q{SDL_PauseAudio}, q{int pause_on}],
157 		[q{void}, q{SDL_PauseAudioDevice}, q{SDL_AudioDeviceID dev, int pause_on}],
158 		[q{SDL_AudioSpec*}, q{SDL_LoadWAV_RW}, q{SDL_RWops* src, int freesrc, SDL_AudioSpec* spec, ubyte** audio_buf, uint* audio_len}],
159 		[q{void}, q{SDL_FreeWAV}, q{ubyte* audio_buf}],
160 		[q{int}, q{SDL_BuildAudioCVT}, q{SDL_AudioCVT* cvt, SDL_AudioFormat src_format, ubyte src_channels, int src_rate, SDL_AudioFormat dst_format, ubyte dst_channels, int dst_rate}],
161 		[q{int}, q{SDL_ConvertAudio}, q{SDL_AudioCVT* cvt}],
162 		[q{void}, q{SDL_MixAudio}, q{ubyte* dst, const(ubyte)* src, uint len, int volume}],
163 		[q{void}, q{SDL_MixAudioFormat}, q{ubyte* dst, const(ubyte)* src, SDL_AudioFormat format, uint len, int volume}],
164 		[q{void}, q{SDL_LockAudio}, q{}],
165 		[q{void}, q{SDL_LockAudioDevice}, q{SDL_AudioDeviceID dev}],
166 		[q{void}, q{SDL_UnlockAudio}, q{}],
167 		[q{void}, q{SDL_UnlockAudioDevice}, q{SDL_AudioDeviceID dev}],
168 		[q{void}, q{SDL_CloseAudio}, q{}],
169 		[q{void}, q{SDL_CloseAudioDevice}, q{SDL_AudioDeviceID dev}],
170 	]);
171 	static if(sdlSupport >= SDLSupport.v2_0_4){
172 		ret ~= makeFnBinds([
173 			[q{int}, q{SDL_QueueAudio}, q{SDL_AudioDeviceID dev, const(void)* data, uint len}],
174 			[q{int}, q{SDL_ClearQueuedAudio}, q{SDL_AudioDeviceID dev}],
175 			[q{int}, q{SDL_GetQueuedAudioSize}, q{SDL_AudioDeviceID dev}],
176 		]);
177 	}
178 	static if(sdlSupport >= SDLSupport.v2_0_5){
179 		ret ~= makeFnBinds([
180 			[q{uint}, q{SDL_DequeueAudio}, q{SDL_AudioDeviceID dev, void* data, uint len}],
181 		]);
182 	}
183 	static if(sdlSupport >= SDLSupport.v2_0_7){
184 		ret ~= makeFnBinds([
185 			[q{SDL_AudioStream*}, q{SDL_NewAudioStream}, q{const SDL_AudioFormat src_format, const ubyte src_channels, const int src_rate, const SDL_AudioFormat dst_format, const ubyte dst_channels, const int dst_rate}],
186 			[q{int}, q{SDL_AudioStreamPut}, q{SDL_AudioStream* stream, const(void)* buf, int len}],
187 			[q{int}, q{SDL_AudioStreamGet}, q{SDL_AudioStream* stream, void* buf, int len}],
188 			[q{int}, q{SDL_AudioStreamAvailable}, q{SDL_AudioStream* stream}],
189 			[q{int}, q{SDL_AudioStreamFlush}, q{SDL_AudioStream* stream}],
190 			[q{void}, q{SDL_AudioStreamClear}, q{SDL_AudioStream* stream}],
191 			[q{void}, q{SDL_FreeAudioStream}, q{SDL_AudioStream* stream}],
192 		]);
193 	}
194 	static if(sdlSupport >= SDLSupport.v2_0_16){
195 		ret ~= makeFnBinds([
196 			[q{int}, q{SDL_GetAudioDeviceSpec}, q{int index, int iscapture, SDL_AudioSpec *spec}],
197 		]);
198 	}
199 	static if(sdlSupport >= SDLSupport.v2_24){
200 		ret ~= makeFnBinds([
201 			[q{int}, q{SDL_GetDefaultAudioInfo}, q{char** name, SDL_AudioSpec* spec, int iscapture}],
202 		]);
203 	}
204 	return ret;
205 }()));