Reorder and comment some function in alhelpers.c
[openal-soft.git] / examples / common / alhelpers.c
blob84d6dad312977ae1f0bf92dbbe074c3e9be8bd34
1 /*
2 * OpenAL Helpers
4 * Copyright (c) 2011 by Chris Robinson <chris.kcat@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 /* This file contains routines to help with some menial OpenAL-related tasks,
26 * such as opening a device and setting up a context, closing the device and
27 * destroying its context, converting between frame counts and byte lengths,
28 * finding an appropriate buffer format, and getting readable strings for
29 * channel configs and sample types. */
31 #include <stdio.h>
33 #include "AL/al.h"
34 #include "AL/alc.h"
35 #include "AL/alext.h"
37 #include "alhelpers.h"
40 /* InitAL opens the default device and sets up a context using default
41 * attributes, making the program ready to call OpenAL functions. */
42 int InitAL(void)
44 ALCdevice *device;
45 ALCcontext *ctx;
47 /* Open and initialize a device with default settings */
48 device = alcOpenDevice(NULL);
49 if(!device)
51 fprintf(stderr, "Could not open a device!\n");
52 return 1;
55 ctx = alcCreateContext(device, NULL);
56 if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
58 if(ctx != NULL)
59 alcDestroyContext(ctx);
60 alcCloseDevice(device);
61 fprintf(stderr, "Could not set a context!\n");
62 return 1;
65 return 0;
68 /* CloseAL closes the device belonging to the current context, and destroys the
69 * context. */
70 void CloseAL(void)
72 ALCdevice *device;
73 ALCcontext *ctx;
75 ctx = alcGetCurrentContext();
76 if(ctx == NULL)
77 return;
79 device = alcGetContextsDevice(ctx);
81 alcMakeContextCurrent(NULL);
82 alcDestroyContext(ctx);
83 alcCloseDevice(device);
87 /* GetFormat retrieves a compatible buffer format given the channel config and
88 * sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
89 * provided, it will be called to find the closest-matching format from
90 * AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
91 * found. */
92 ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
94 ALenum format = AL_NONE;
96 /* If using AL_SOFT_buffer_samples, try looking through its formats */
97 if(palIsBufferFormatSupportedSOFT)
99 /* AL_SOFT_buffer_samples is more lenient with matching formats. The
100 * specified sample type does not need to match the returned format,
101 * but it is nice to try to get something close. */
102 if(type == AL_UNSIGNED_BYTE_SOFT || type == AL_BYTE_SOFT)
104 if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
105 else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
106 else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
107 else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
108 else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
109 else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
111 else if(type == AL_UNSIGNED_SHORT_SOFT || type == AL_SHORT_SOFT)
113 if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
114 else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
115 else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
116 else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
117 else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
118 else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
120 else if(type == AL_UNSIGNED_BYTE3_SOFT || type == AL_BYTE3_SOFT ||
121 type == AL_UNSIGNED_INT_SOFT || type == AL_INT_SOFT ||
122 type == AL_FLOAT_SOFT || type == AL_DOUBLE_SOFT)
124 if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
125 else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
126 else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
127 else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
128 else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
129 else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
132 if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
133 format = AL_NONE;
135 /* A matching format was not found or supported. Try 32-bit float. */
136 if(format == AL_NONE)
138 if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
139 else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
140 else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
141 else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
142 else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
143 else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
145 if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
146 format = AL_NONE;
148 /* 32-bit float not supported. Try 16-bit int. */
149 if(format == AL_NONE)
151 if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
152 else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
153 else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
154 else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
155 else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
156 else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
158 if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
159 format = AL_NONE;
161 /* 16-bit int not supported. Try 8-bit int. */
162 if(format == AL_NONE)
164 if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
165 else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
166 else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
167 else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
168 else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
169 else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
171 if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
172 format = AL_NONE;
175 return format;
178 /* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1,
179 * and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and
180 * AL_EXT_DOUBLE for 64-bit float samples. */
181 if(type == AL_UNSIGNED_BYTE_SOFT)
183 if(channels == AL_MONO_SOFT)
184 format = AL_FORMAT_MONO8;
185 else if(channels == AL_STEREO_SOFT)
186 format = AL_FORMAT_STEREO8;
187 else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
189 if(channels == AL_QUAD_SOFT)
190 format = alGetEnumValue("AL_FORMAT_QUAD8");
191 else if(channels == AL_5POINT1_SOFT)
192 format = alGetEnumValue("AL_FORMAT_51CHN8");
193 else if(channels == AL_6POINT1_SOFT)
194 format = alGetEnumValue("AL_FORMAT_61CHN8");
195 else if(channels == AL_7POINT1_SOFT)
196 format = alGetEnumValue("AL_FORMAT_71CHN8");
199 else if(type == AL_SHORT_SOFT)
201 if(channels == AL_MONO_SOFT)
202 format = AL_FORMAT_MONO16;
203 else if(channels == AL_STEREO_SOFT)
204 format = AL_FORMAT_STEREO16;
205 else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
207 if(channels == AL_QUAD_SOFT)
208 format = alGetEnumValue("AL_FORMAT_QUAD16");
209 else if(channels == AL_5POINT1_SOFT)
210 format = alGetEnumValue("AL_FORMAT_51CHN16");
211 else if(channels == AL_6POINT1_SOFT)
212 format = alGetEnumValue("AL_FORMAT_61CHN16");
213 else if(channels == AL_7POINT1_SOFT)
214 format = alGetEnumValue("AL_FORMAT_71CHN16");
217 else if(type == AL_FLOAT_SOFT && alIsExtensionPresent("AL_EXT_FLOAT32"))
219 if(channels == AL_MONO_SOFT)
220 format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
221 else if(channels == AL_STEREO_SOFT)
222 format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
223 else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
225 if(channels == AL_QUAD_SOFT)
226 format = alGetEnumValue("AL_FORMAT_QUAD32");
227 else if(channels == AL_5POINT1_SOFT)
228 format = alGetEnumValue("AL_FORMAT_51CHN32");
229 else if(channels == AL_6POINT1_SOFT)
230 format = alGetEnumValue("AL_FORMAT_61CHN32");
231 else if(channels == AL_7POINT1_SOFT)
232 format = alGetEnumValue("AL_FORMAT_71CHN32");
235 else if(type == AL_DOUBLE_SOFT && alIsExtensionPresent("AL_EXT_DOUBLE"))
237 if(channels == AL_MONO_SOFT)
238 format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
239 else if(channels == AL_STEREO_SOFT)
240 format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");
243 /* NOTE: It seems OSX returns -1 from alGetEnumValue for unknown enums, as
244 * opposed to 0. Correct it. */
245 if(format == -1)
246 format = 0;
248 return format;
252 void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
253 ALenum internalformat, ALsizei samples,
254 ALenum channels, ALenum type,
255 const ALvoid *data)
257 alBufferData(buffer, internalformat, data,
258 FramesToBytes(samples, channels, type),
259 samplerate);
263 const char *ChannelsName(ALenum chans)
265 switch(chans)
267 case AL_MONO_SOFT: return "Mono";
268 case AL_STEREO_SOFT: return "Stereo";
269 case AL_REAR_SOFT: return "Rear";
270 case AL_QUAD_SOFT: return "Quadraphonic";
271 case AL_5POINT1_SOFT: return "5.1 Surround";
272 case AL_6POINT1_SOFT: return "6.1 Surround";
273 case AL_7POINT1_SOFT: return "7.1 Surround";
275 return "Unknown Channels";
278 const char *TypeName(ALenum type)
280 switch(type)
282 case AL_BYTE_SOFT: return "S8";
283 case AL_UNSIGNED_BYTE_SOFT: return "U8";
284 case AL_SHORT_SOFT: return "S16";
285 case AL_UNSIGNED_SHORT_SOFT: return "U16";
286 case AL_INT_SOFT: return "S32";
287 case AL_UNSIGNED_INT_SOFT: return "U32";
288 case AL_FLOAT_SOFT: return "Float32";
289 case AL_DOUBLE_SOFT: return "Float64";
291 return "Unknown Type";
295 ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
297 switch(channels)
299 case AL_MONO_SOFT: size *= 1; break;
300 case AL_STEREO_SOFT: size *= 2; break;
301 case AL_REAR_SOFT: size *= 2; break;
302 case AL_QUAD_SOFT: size *= 4; break;
303 case AL_5POINT1_SOFT: size *= 6; break;
304 case AL_6POINT1_SOFT: size *= 7; break;
305 case AL_7POINT1_SOFT: size *= 8; break;
308 switch(type)
310 case AL_BYTE_SOFT: size *= sizeof(ALbyte); break;
311 case AL_UNSIGNED_BYTE_SOFT: size *= sizeof(ALubyte); break;
312 case AL_SHORT_SOFT: size *= sizeof(ALshort); break;
313 case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
314 case AL_INT_SOFT: size *= sizeof(ALint); break;
315 case AL_UNSIGNED_INT_SOFT: size *= sizeof(ALuint); break;
316 case AL_FLOAT_SOFT: size *= sizeof(ALfloat); break;
317 case AL_DOUBLE_SOFT: size *= sizeof(ALdouble); break;
320 return size;
323 ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
325 return size / FramesToBytes(1, channels, type);