zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
alhelpers.c
Go to the documentation of this file.
1 /*
2  * OpenAL Helpers
3  *
4  * Copyright (c) 2011 by Chris Robinson <chris.kcat@gmail.com>
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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.
23  */
24 
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. */
30 
31 #include <stdio.h>
32 
33 #include "AL/al.h"
34 #include "AL/alc.h"
35 #include "AL/alext.h"
36 
37 #include "alhelpers.h"
38 
39 
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)
43 {
44  ALCdevice *device;
45  ALCcontext *ctx;
46 
47  /* Open and initialize a device with default settings */
48  device = alcOpenDevice(NULL);
49  if(!device)
50  {
51  fprintf(stderr, "Could not open a device!\n");
52  return 1;
53  }
54 
55  ctx = alcCreateContext(device, NULL);
56  if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
57  {
58  if(ctx != NULL)
59  alcDestroyContext(ctx);
60  alcCloseDevice(device);
61  fprintf(stderr, "Could not set a context!\n");
62  return 1;
63  }
64 
65  printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
66  return 0;
67 }
68 
69 /* CloseAL closes the device belonging to the current context, and destroys the
70  * context. */
71 void CloseAL(void)
72 {
73  ALCdevice *device;
74  ALCcontext *ctx;
75 
76  ctx = alcGetCurrentContext();
77  if(ctx == NULL)
78  return;
79 
80  device = alcGetContextsDevice(ctx);
81 
83  alcDestroyContext(ctx);
84  alcCloseDevice(device);
85 }
86 
87 
88 /* GetFormat retrieves a compatible buffer format given the channel config and
89  * sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
90  * provided, it will be called to find the closest-matching format from
91  * AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
92  * found. */
93 ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
94 {
96 
97  /* If using AL_SOFT_buffer_samples, try looking through its formats */
98  if(palIsBufferFormatSupportedSOFT)
99  {
100  /* AL_SOFT_buffer_samples is more lenient with matching formats. The
101  * specified sample type does not need to match the returned format,
102  * but it is nice to try to get something close. */
103  if(type == AL_UNSIGNED_BYTE_SOFT || type == AL_BYTE_SOFT)
104  {
105  if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
106  else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
107  else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
108  else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
109  else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
110  else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
111  }
112  else if(type == AL_UNSIGNED_SHORT_SOFT || type == AL_SHORT_SOFT)
113  {
114  if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
115  else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
116  else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
117  else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
118  else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
119  else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
120  }
121  else if(type == AL_UNSIGNED_BYTE3_SOFT || type == AL_BYTE3_SOFT ||
122  type == AL_UNSIGNED_INT_SOFT || type == AL_INT_SOFT ||
123  type == AL_FLOAT_SOFT || type == AL_DOUBLE_SOFT)
124  {
125  if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
126  else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
127  else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
128  else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
129  else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
130  else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
131  }
132 
133  if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
134  format = AL_NONE;
135 
136  /* A matching format was not found or supported. Try 32-bit float. */
137  if(format == AL_NONE)
138  {
139  if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
140  else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
141  else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
142  else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
143  else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
144  else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
145 
146  if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
147  format = AL_NONE;
148  }
149  /* 32-bit float not supported. Try 16-bit int. */
150  if(format == AL_NONE)
151  {
152  if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
153  else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
154  else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
155  else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
156  else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
157  else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
158 
159  if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
160  format = AL_NONE;
161  }
162  /* 16-bit int not supported. Try 8-bit int. */
163  if(format == AL_NONE)
164  {
165  if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
166  else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
167  else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
168  else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
169  else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
170  else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
171 
172  if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
173  format = AL_NONE;
174  }
175 
176  return format;
177  }
178 
179  /* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1,
180  * and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and
181  * AL_EXT_DOUBLE for 64-bit float samples. */
182  if(type == AL_UNSIGNED_BYTE_SOFT)
183  {
184  if(channels == AL_MONO_SOFT)
185  format = AL_FORMAT_MONO8;
186  else if(channels == AL_STEREO_SOFT)
187  format = AL_FORMAT_STEREO8;
188  else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
189  {
190  if(channels == AL_QUAD_SOFT)
191  format = alGetEnumValue("AL_FORMAT_QUAD8");
192  else if(channels == AL_5POINT1_SOFT)
193  format = alGetEnumValue("AL_FORMAT_51CHN8");
194  else if(channels == AL_6POINT1_SOFT)
195  format = alGetEnumValue("AL_FORMAT_61CHN8");
196  else if(channels == AL_7POINT1_SOFT)
197  format = alGetEnumValue("AL_FORMAT_71CHN8");
198  }
199  }
200  else if(type == AL_SHORT_SOFT)
201  {
202  if(channels == AL_MONO_SOFT)
203  format = AL_FORMAT_MONO16;
204  else if(channels == AL_STEREO_SOFT)
205  format = AL_FORMAT_STEREO16;
206  else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
207  {
208  if(channels == AL_QUAD_SOFT)
209  format = alGetEnumValue("AL_FORMAT_QUAD16");
210  else if(channels == AL_5POINT1_SOFT)
211  format = alGetEnumValue("AL_FORMAT_51CHN16");
212  else if(channels == AL_6POINT1_SOFT)
213  format = alGetEnumValue("AL_FORMAT_61CHN16");
214  else if(channels == AL_7POINT1_SOFT)
215  format = alGetEnumValue("AL_FORMAT_71CHN16");
216  }
217  }
218  else if(type == AL_FLOAT_SOFT && alIsExtensionPresent("AL_EXT_FLOAT32"))
219  {
220  if(channels == AL_MONO_SOFT)
221  format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
222  else if(channels == AL_STEREO_SOFT)
223  format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
224  else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
225  {
226  if(channels == AL_QUAD_SOFT)
227  format = alGetEnumValue("AL_FORMAT_QUAD32");
228  else if(channels == AL_5POINT1_SOFT)
229  format = alGetEnumValue("AL_FORMAT_51CHN32");
230  else if(channels == AL_6POINT1_SOFT)
231  format = alGetEnumValue("AL_FORMAT_61CHN32");
232  else if(channels == AL_7POINT1_SOFT)
233  format = alGetEnumValue("AL_FORMAT_71CHN32");
234  }
235  }
236  else if(type == AL_DOUBLE_SOFT && alIsExtensionPresent("AL_EXT_DOUBLE"))
237  {
238  if(channels == AL_MONO_SOFT)
239  format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
240  else if(channels == AL_STEREO_SOFT)
241  format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");
242  }
243 
244  /* NOTE: It seems OSX returns -1 from alGetEnumValue for unknown enums, as
245  * opposed to 0. Correct it. */
246  if(format == -1)
247  format = 0;
248 
249  return format;
250 }
251 
252 
255  ALenum channels, ALenum type,
256  const ALvoid *data)
257 {
258  alBufferData(buffer, internalformat, data,
259  FramesToBytes(samples, channels, type),
260  samplerate);
261 }
262 
263 
264 const char *ChannelsName(ALenum chans)
265 {
266  switch(chans)
267  {
268  case AL_MONO_SOFT: return "Mono";
269  case AL_STEREO_SOFT: return "Stereo";
270  case AL_REAR_SOFT: return "Rear";
271  case AL_QUAD_SOFT: return "Quadraphonic";
272  case AL_5POINT1_SOFT: return "5.1 Surround";
273  case AL_6POINT1_SOFT: return "6.1 Surround";
274  case AL_7POINT1_SOFT: return "7.1 Surround";
275  }
276  return "Unknown Channels";
277 }
278 
279 const char *TypeName(ALenum type)
280 {
281  switch(type)
282  {
283  case AL_BYTE_SOFT: return "S8";
284  case AL_UNSIGNED_BYTE_SOFT: return "U8";
285  case AL_SHORT_SOFT: return "S16";
286  case AL_UNSIGNED_SHORT_SOFT: return "U16";
287  case AL_INT_SOFT: return "S32";
288  case AL_UNSIGNED_INT_SOFT: return "U32";
289  case AL_FLOAT_SOFT: return "Float32";
290  case AL_DOUBLE_SOFT: return "Float64";
291  }
292  return "Unknown Type";
293 }
294 
295 
297 {
298  switch(channels)
299  {
300  case AL_MONO_SOFT: size *= 1; break;
301  case AL_STEREO_SOFT: size *= 2; break;
302  case AL_REAR_SOFT: size *= 2; break;
303  case AL_QUAD_SOFT: size *= 4; break;
304  case AL_5POINT1_SOFT: size *= 6; break;
305  case AL_6POINT1_SOFT: size *= 7; break;
306  case AL_7POINT1_SOFT: size *= 8; break;
307  }
308 
309  switch(type)
310  {
311  case AL_BYTE_SOFT: size *= sizeof(ALbyte); break;
312  case AL_UNSIGNED_BYTE_SOFT: size *= sizeof(ALubyte); break;
313  case AL_SHORT_SOFT: size *= sizeof(ALshort); break;
314  case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
315  case AL_INT_SOFT: size *= sizeof(ALint); break;
316  case AL_UNSIGNED_INT_SOFT: size *= sizeof(ALuint); break;
317  case AL_FLOAT_SOFT: size *= sizeof(ALfloat); break;
318  case AL_DOUBLE_SOFT: size *= sizeof(ALdouble); break;
319  }
320 
321  return size;
322 }
323 
325 {
326  return size / FramesToBytes(1, channels, type);
327 }
#define AL_APIENTRY
Definition: al.h:21
#define AL_6POINT1_32F_SOFT
Definition: alext.h:247
unsigned char ALubyte
Definition: al.h:47
#define AL_5POINT1_8_SOFT
Definition: alext.h:242
void ALvoid
Definition: al.h:74
#define AL_STEREO_SOFT
Definition: alext.h:210
#define AL_6POINT1_16_SOFT
Definition: alext.h:246
#define AL_NONE
Definition: al.h:80
#define AL_6POINT1_SOFT
Definition: alext.h:214
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
Definition: alBuffer.c:289
#define AL_6POINT1_8_SOFT
Definition: alext.h:245
#define NULL
Definition: ftobjs.h:61
#define AL_QUAD32F_SOFT
Definition: alext.h:238
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
Definition: ALc.c:2590
void CloseAL(void)
Definition: alhelpers.c:71
#define AL_REAR_SOFT
Definition: alext.h:211
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device)
Definition: ALc.c:2884
ALC_API const ALCchar *ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
Definition: ALc.c:2066
int ALsizei
Definition: al.h:62
int ALint
Definition: al.h:56
#define AL_MONO8_SOFT
Definition: alext.h:230
ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
Definition: ALc.c:2539
#define AL_STEREO32F_SOFT
Definition: alext.h:235
short ALshort
Definition: al.h:50
void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data)
Definition: alhelpers.c:253
#define AL_UNSIGNED_INT_SOFT
Definition: alext.h:223
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
Definition: alhelpers.c:296
float ALfloat
Definition: al.h:68
#define AL_7POINT1_8_SOFT
Definition: alext.h:248
signed char ALbyte
Definition: al.h:44
#define AL_INT_SOFT
Definition: alext.h:222
AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename)
Definition: alExtension.c:95
#define AL_DOUBLE_SOFT
Definition: alext.h:225
ALboolean(AL_APIENTRY * LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum)
Definition: alext.h:261
ALC_API ALCcontext *ALC_APIENTRY alcGetCurrentContext(void)
Definition: ALc.c:2563
EGLContext EGLenum EGLClientBuffer buffer
Definition: eglext.h:87
#define ALC_FALSE
Definition: alc.h:81
#define AL_5POINT1_SOFT
Definition: alext.h:213
double ALdouble
Definition: al.h:71
#define AL_SHORT_SOFT
Definition: alext.h:220
const char * TypeName(ALenum type)
Definition: alhelpers.c:279
#define AL_UNSIGNED_BYTE_SOFT
Definition: alext.h:219
#define AL_FLOAT_SOFT
Definition: alext.h:224
#define AL_QUAD8_SOFT
Definition: alext.h:236
unsigned short ALushort
Definition: al.h:53
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define AL_7POINT1_SOFT
Definition: alext.h:215
#define AL_BYTE3_SOFT
Definition: alext.h:226
GLsizei samples
Definition: gl2ext.h:970
int ALenum
Definition: al.h:65
#define AL_FORMAT_MONO16
Definition: al.h:340
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl2ext.h:845
#define AL_QUAD_SOFT
Definition: alext.h:212
#define AL_5POINT1_16_SOFT
Definition: alext.h:243
#define AL_FORMAT_MONO8
Definition: al.h:339
unsigned int ALuint
Definition: al.h:59
#define ALC_DEVICE_SPECIFIER
Definition: alc.h:136
ALC_API ALCcontext *ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
Definition: ALc.c:2463
#define AL_QUAD16_SOFT
Definition: alext.h:237
ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
Definition: alhelpers.c:324
#define AL_MONO32F_SOFT
Definition: alext.h:232
GLint GLenum internalformat
Definition: gl2ext.h:845
#define AL_BYTE_SOFT
Definition: alext.h:218
ALC_API ALCdevice *ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
Definition: ALc.c:2638
ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
Definition: alhelpers.c:93
const char * ChannelsName(ALenum chans)
Definition: alhelpers.c:264
AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname)
Definition: alExtension.c:49
#define AL_STEREO16_SOFT
Definition: alext.h:234
#define AL_FORMAT_STEREO16
Definition: al.h:342
int InitAL(void)
Definition: alhelpers.c:42
#define AL_MONO16_SOFT
Definition: alext.h:231
#define AL_UNSIGNED_SHORT_SOFT
Definition: alext.h:221
#define AL_STEREO8_SOFT
Definition: alext.h:233
#define AL_7POINT1_16_SOFT
Definition: alext.h:249
#define AL_FORMAT_STEREO8
Definition: al.h:341
#define AL_7POINT1_32F_SOFT
Definition: alext.h:250
ALC_API ALCdevice *ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
Definition: ALc.c:2658
#define AL_UNSIGNED_BYTE3_SOFT
Definition: alext.h:227
#define AL_5POINT1_32F_SOFT
Definition: alext.h:244
#define AL_MONO_SOFT
Definition: alext.h:209
GLsizei size
Definition: gl2ext.h:1467
EGLContext ctx
Definition: eglext.h:87