| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /*
- * 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"
- /* InitAL opens the default device and sets up a context using default
- * attributes, making the program ready to call OpenAL functions. */
- 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;
- }
- printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
- return 0;
- }
- /* CloseAL closes the device belonging to the current context, and destroys the
- * context. */
- void CloseAL(void)
- {
- ALCdevice *device;
- ALCcontext *ctx;
- ctx = alcGetCurrentContext();
- if(ctx == NULL)
- return;
- device = alcGetContextsDevice(ctx);
- alcMakeContextCurrent(NULL);
- alcDestroyContext(ctx);
- alcCloseDevice(device);
- }
- /* GetFormat retrieves a compatible buffer format given the channel config and
- * sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
- * provided, it will be called to find the closest-matching format from
- * AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
- * found. */
- ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
- {
- ALenum format = AL_NONE;
- /* If using AL_SOFT_buffer_samples, try looking through its formats */
- if(palIsBufferFormatSupportedSOFT)
- {
- /* AL_SOFT_buffer_samples is more lenient with matching formats. The
- * specified sample type does not need to match the returned format,
- * but it is nice to try to get something close. */
- if(type == AL_UNSIGNED_BYTE_SOFT || type == AL_BYTE_SOFT)
- {
- if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
- else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
- else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
- else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
- else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
- else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
- }
- else if(type == AL_UNSIGNED_SHORT_SOFT || type == AL_SHORT_SOFT)
- {
- if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
- else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
- else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
- else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
- else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
- else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
- }
- else if(type == AL_UNSIGNED_BYTE3_SOFT || type == AL_BYTE3_SOFT ||
- type == AL_UNSIGNED_INT_SOFT || type == AL_INT_SOFT ||
- type == AL_FLOAT_SOFT || type == AL_DOUBLE_SOFT)
- {
- if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
- else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
- else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
- else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
- else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
- else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
- }
- if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
- format = AL_NONE;
- /* A matching format was not found or supported. Try 32-bit float. */
- if(format == AL_NONE)
- {
- if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
- else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
- else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
- else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
- else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
- else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
- if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
- format = AL_NONE;
- }
- /* 32-bit float not supported. Try 16-bit int. */
- if(format == AL_NONE)
- {
- if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
- else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
- else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
- else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
- else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
- else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
- if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
- format = AL_NONE;
- }
- /* 16-bit int not supported. Try 8-bit int. */
- if(format == AL_NONE)
- {
- if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
- else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
- else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
- else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
- else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
- else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
- if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
- format = AL_NONE;
- }
- return format;
- }
- /* 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_SOFT)
- {
- if(channels == AL_MONO_SOFT)
- format = AL_FORMAT_MONO8;
- else if(channels == AL_STEREO_SOFT)
- format = AL_FORMAT_STEREO8;
- else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
- {
- if(channels == AL_QUAD_SOFT)
- format = alGetEnumValue("AL_FORMAT_QUAD8");
- else if(channels == AL_5POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_51CHN8");
- else if(channels == AL_6POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_61CHN8");
- else if(channels == AL_7POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_71CHN8");
- }
- }
- else if(type == AL_SHORT_SOFT)
- {
- if(channels == AL_MONO_SOFT)
- format = AL_FORMAT_MONO16;
- else if(channels == AL_STEREO_SOFT)
- format = AL_FORMAT_STEREO16;
- else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
- {
- if(channels == AL_QUAD_SOFT)
- format = alGetEnumValue("AL_FORMAT_QUAD16");
- else if(channels == AL_5POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_51CHN16");
- else if(channels == AL_6POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_61CHN16");
- else if(channels == AL_7POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_71CHN16");
- }
- }
- else if(type == AL_FLOAT_SOFT && alIsExtensionPresent("AL_EXT_FLOAT32"))
- {
- if(channels == AL_MONO_SOFT)
- format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
- else if(channels == AL_STEREO_SOFT)
- format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
- else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
- {
- if(channels == AL_QUAD_SOFT)
- format = alGetEnumValue("AL_FORMAT_QUAD32");
- else if(channels == AL_5POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_51CHN32");
- else if(channels == AL_6POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_61CHN32");
- else if(channels == AL_7POINT1_SOFT)
- format = alGetEnumValue("AL_FORMAT_71CHN32");
- }
- }
- else if(type == AL_DOUBLE_SOFT && alIsExtensionPresent("AL_EXT_DOUBLE"))
- {
- if(channels == AL_MONO_SOFT)
- format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
- else if(channels == AL_STEREO_SOFT)
- 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;
- }
- void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
- ALenum internalformat, ALsizei samples,
- ALenum channels, ALenum type,
- const ALvoid *data)
- {
- alBufferData(buffer, internalformat, data,
- FramesToBytes(samples, channels, type),
- samplerate);
- }
- const char *ChannelsName(ALenum chans)
- {
- switch(chans)
- {
- case AL_MONO_SOFT: return "Mono";
- case AL_STEREO_SOFT: return "Stereo";
- case AL_REAR_SOFT: return "Rear";
- case AL_QUAD_SOFT: return "Quadraphonic";
- case AL_5POINT1_SOFT: return "5.1 Surround";
- case AL_6POINT1_SOFT: return "6.1 Surround";
- case AL_7POINT1_SOFT: return "7.1 Surround";
- }
- return "Unknown Channels";
- }
- const char *TypeName(ALenum type)
- {
- switch(type)
- {
- case AL_BYTE_SOFT: return "S8";
- case AL_UNSIGNED_BYTE_SOFT: return "U8";
- case AL_SHORT_SOFT: return "S16";
- case AL_UNSIGNED_SHORT_SOFT: return "U16";
- case AL_INT_SOFT: return "S32";
- case AL_UNSIGNED_INT_SOFT: return "U32";
- case AL_FLOAT_SOFT: return "Float32";
- case AL_DOUBLE_SOFT: return "Float64";
- }
- return "Unknown Type";
- }
- ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
- {
- switch(channels)
- {
- case AL_MONO_SOFT: size *= 1; break;
- case AL_STEREO_SOFT: size *= 2; break;
- case AL_REAR_SOFT: size *= 2; break;
- case AL_QUAD_SOFT: size *= 4; break;
- case AL_5POINT1_SOFT: size *= 6; break;
- case AL_6POINT1_SOFT: size *= 7; break;
- case AL_7POINT1_SOFT: size *= 8; break;
- }
- switch(type)
- {
- case AL_BYTE_SOFT: size *= sizeof(ALbyte); break;
- case AL_UNSIGNED_BYTE_SOFT: size *= sizeof(ALubyte); break;
- case AL_SHORT_SOFT: size *= sizeof(ALshort); break;
- case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
- case AL_INT_SOFT: size *= sizeof(ALint); break;
- case AL_UNSIGNED_INT_SOFT: size *= sizeof(ALuint); break;
- case AL_FLOAT_SOFT: size *= sizeof(ALfloat); break;
- case AL_DOUBLE_SOFT: size *= sizeof(ALdouble); break;
- }
- return size;
- }
- ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
- {
- return size / FramesToBytes(1, channels, type);
- }
|