diff options
Diffstat (limited to 'examples/alhelpers.c')
-rw-r--r-- | examples/alhelpers.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/examples/alhelpers.c b/examples/alhelpers.c new file mode 100644 index 00000000..ba23cabd --- /dev/null +++ b/examples/alhelpers.c @@ -0,0 +1,226 @@ +/* + * OpenAL Helpers + * + * Copyright (c) 2011 by Chris Robinson <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* This file contains routines to help with some menial OpenAL-related tasks, + * such as opening a device and setting up a context, closing the device and + * destroying its context, converting between frame counts and byte lengths, + * finding an appropriate buffer format, and getting readable strings for + * channel configs and sample types. */ + +#include <stdio.h> + +#include "AL/al.h" +#include "AL/alc.h" +#include "AL/alext.h" + +#include "alhelpers.h" + + +const char *ChannelsName(ALenum chans) +{ + switch(chans) + { + case AL_MONO: return "Mono"; + case AL_STEREO: return "Stereo"; + case AL_REAR: return "Rear"; + case AL_QUAD: return "Quadraphonic"; + case AL_5POINT1: return "5.1 Surround"; + case AL_6POINT1: return "6.1 Surround"; + case AL_7POINT1: return "7.1 Surround"; + } + return "Unknown Channels"; +} + +const char *TypeName(ALenum type) +{ + switch(type) + { + case AL_BYTE: return "S8"; + case AL_UNSIGNED_BYTE: return "U8"; + case AL_SHORT: return "S16"; + case AL_UNSIGNED_SHORT: return "U16"; + case AL_INT: return "S32"; + case AL_UNSIGNED_INT: return "U32"; + case AL_FLOAT: return "Float32"; + case AL_DOUBLE: return "Float64"; + } + return "Unknown Type"; +} + + +ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type) +{ + switch(channels) + { + case AL_MONO: size *= 1; break; + case AL_STEREO: size *= 2; break; + case AL_REAR: size *= 2; break; + case AL_QUAD: size *= 4; break; + case AL_5POINT1: size *= 6; break; + case AL_6POINT1: size *= 7; break; + case AL_7POINT1: size *= 8; break; + } + + switch(type) + { + case AL_BYTE: size *= sizeof(ALbyte); break; + case AL_UNSIGNED_BYTE: size *= sizeof(ALubyte); break; + case AL_SHORT: size *= sizeof(ALshort); break; + case AL_UNSIGNED_SHORT: size *= sizeof(ALushort); break; + case AL_INT: size *= sizeof(ALint); break; + case AL_UNSIGNED_INT: size *= sizeof(ALuint); break; + case AL_FLOAT: size *= sizeof(ALfloat); break; + case AL_DOUBLE: size *= sizeof(ALdouble); break; + } + + return size; +} + +ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type) +{ + return size / FramesToBytes(1, channels, type); +} + + +ALenum GetFormat(ALenum channels, ALenum type) +{ + ALenum format = 0; + + /* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1, + * and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and + * AL_EXT_DOUBLE for 64-bit float samples. */ + if(type == AL_UNSIGNED_BYTE) + { + if(channels == AL_MONO) + format = AL_FORMAT_MONO8; + else if(channels == AL_STEREO) + format = AL_FORMAT_STEREO8; + else if(alIsExtensionPresent("AL_EXT_MCFORMATS")) + { + if(channels == AL_QUAD) + format = alGetEnumValue("AL_FORMAT_QUAD8"); + else if(channels == AL_5POINT1) + format = alGetEnumValue("AL_FORMAT_51CHN8"); + else if(channels == AL_6POINT1) + format = alGetEnumValue("AL_FORMAT_61CHN8"); + else if(channels == AL_7POINT1) + format = alGetEnumValue("AL_FORMAT_71CHN8"); + } + } + else if(type == AL_SHORT) + { + if(channels == AL_MONO) + format = AL_FORMAT_MONO16; + else if(channels == AL_STEREO) + format = AL_FORMAT_STEREO16; + else if(alIsExtensionPresent("AL_EXT_MCFORMATS")) + { + if(channels == AL_QUAD) + format = alGetEnumValue("AL_FORMAT_QUAD16"); + else if(channels == AL_5POINT1) + format = alGetEnumValue("AL_FORMAT_51CHN16"); + else if(channels == AL_6POINT1) + format = alGetEnumValue("AL_FORMAT_61CHN16"); + else if(channels == AL_7POINT1) + format = alGetEnumValue("AL_FORMAT_71CHN16"); + } + } + else if(type == AL_FLOAT && alIsExtensionPresent("AL_EXT_FLOAT32")) + { + if(channels == AL_MONO) + format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32"); + else if(channels == AL_STEREO) + format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32"); + else if(alIsExtensionPresent("AL_EXT_MCFORMATS")) + { + if(channels == AL_QUAD) + format = alGetEnumValue("AL_FORMAT_QUAD32"); + else if(channels == AL_5POINT1) + format = alGetEnumValue("AL_FORMAT_51CHN32"); + else if(channels == AL_6POINT1) + format = alGetEnumValue("AL_FORMAT_61CHN32"); + else if(channels == AL_7POINT1) + format = alGetEnumValue("AL_FORMAT_71CHN32"); + } + } + else if(type == AL_DOUBLE && alIsExtensionPresent("AL_EXT_DOUBLE")) + { + if(channels == AL_MONO) + format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE"); + else if(channels == AL_STEREO) + format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE"); + } + + /* NOTE: It seems OSX returns -1 from alGetEnumValue for unknown enums, as + * opposed to 0. Correct it. */ + if(format == -1) + format = 0; + + return format; +} + + +int InitAL(void) +{ + ALCdevice *device; + ALCcontext *ctx; + + /* Open and initialize a device with default settings */ + device = alcOpenDevice(NULL); + if(!device) + { + fprintf(stderr, "Could not open a device!\n"); + return 1; + } + + ctx = alcCreateContext(device, NULL); + if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE) + { + if(ctx != NULL) + alcDestroyContext(ctx); + alcCloseDevice(device); + fprintf(stderr, "Could not set a context!\n"); + return 1; + } + + return 0; +} + +void CloseAL(void) +{ + ALCdevice *device; + ALCcontext *ctx; + + /* Close the device belonging to the current context, and destroy the + * context. */ + ctx = alcGetCurrentContext(); + if(ctx == NULL) + return; + + device = alcGetContextsDevice(ctx); + + alcMakeContextCurrent(NULL); + alcDestroyContext(ctx); + alcCloseDevice(device); +} |