diff options
Diffstat (limited to 'examples/common')
-rw-r--r-- | examples/common/alhelpers.c | 273 | ||||
-rw-r--r-- | examples/common/alhelpers.h | 36 | ||||
-rw-r--r-- | examples/common/sdl_sound.c | 164 | ||||
-rw-r--r-- | examples/common/sdl_sound.h | 43 |
4 files changed, 36 insertions, 480 deletions
diff --git a/examples/common/alhelpers.c b/examples/common/alhelpers.c index 4582321c..fab039e9 100644 --- a/examples/common/alhelpers.c +++ b/examples/common/alhelpers.c @@ -29,6 +29,7 @@ * channel configs and sample types. */ #include <stdio.h> +#include <string.h> #include "AL/al.h" #include "AL/alc.h" @@ -37,15 +38,26 @@ #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) +/* InitAL opens a device and sets up a context using default attributes, making + * the program ready to call OpenAL functions. */ +int InitAL(char ***argv, int *argc) { + const ALCchar *name; ALCdevice *device; ALCcontext *ctx; - /* Open and initialize a device with default settings */ - device = alcOpenDevice(NULL); + /* Open and initialize a device */ + device = NULL; + if(argc && argv && *argc > 1 && strcmp((*argv)[0], "-device") == 0) + { + device = alcOpenDevice((*argv)[1]); + if(!device) + fprintf(stderr, "Failed to open \"%s\", trying default\n", (*argv)[1]); + (*argv) += 2; + (*argc) -= 2; + } + if(!device) + device = alcOpenDevice(NULL); if(!device) { fprintf(stderr, "Could not open a device!\n"); @@ -62,7 +74,13 @@ int InitAL(void) return 1; } - printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); + name = NULL; + if(alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT")) + name = alcGetString(device, ALC_ALL_DEVICES_SPECIFIER); + if(!name || alcGetError(device) != AL_NO_ERROR) + name = alcGetString(device, ALC_DEVICE_SPECIFIER); + printf("Opened \"%s\"\n", name); + return 0; } @@ -85,243 +103,14 @@ void CloseAL(void) } -/* 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) +const char *FormatName(ALenum format) { - switch(chans) + switch(format) { - 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"; + case AL_FORMAT_MONO8: return "Mono, U8"; + case AL_FORMAT_MONO16: return "Mono, S16"; + case AL_FORMAT_STEREO8: return "Stereo, U8"; + case AL_FORMAT_STEREO16: return "Stereo, S16"; } - 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); + return "Unknown Format"; } diff --git a/examples/common/alhelpers.h b/examples/common/alhelpers.h index 62ed5be2..41a7ce58 100644 --- a/examples/common/alhelpers.h +++ b/examples/common/alhelpers.h @@ -1,47 +1,21 @@ #ifndef ALHELPERS_H #define ALHELPERS_H -#ifndef _WIN32 -#include <unistd.h> -#define Sleep(x) usleep((x)*1000) -#else -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#endif - #include "AL/alc.h" #include "AL/al.h" #include "AL/alext.h" +#include "threads.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -/* Some helper functions to get the name from the channel and type enums. */ -const char *ChannelsName(ALenum chans); -const char *TypeName(ALenum type); - -/* Helpers to convert frame counts and byte lengths. */ -ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type); -ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type); - -/* Retrieves a compatible buffer format given the channel configuration 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); - -/* Loads samples into a buffer using the standard alBufferData call, but with a - * LPALBUFFERSAMPLESSOFT-compatible prototype. Assumes internalformat is valid - * for alBufferData, and that channels and type match it. */ -void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate, - ALenum internalformat, ALsizei samples, - ALenum channels, ALenum type, - const ALvoid *data); +/* Some helper functions to get the name from the format enums. */ +const char *FormatName(ALenum type); /* Easy device init/deinit functions. InitAL returns 0 on success. */ -int InitAL(void); +int InitAL(char ***argv, int *argc); void CloseAL(void); #ifdef __cplusplus diff --git a/examples/common/sdl_sound.c b/examples/common/sdl_sound.c deleted file mode 100644 index 79a5bf32..00000000 --- a/examples/common/sdl_sound.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * SDL_sound Decoder Helpers - * - * Copyright (c) 2013 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 for helping to decode audio using SDL_sound. - * There's very little OpenAL-specific code here. - */ -#include "sdl_sound.h" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <signal.h> -#include <assert.h> - -#include <SDL_sound.h> - -#include "AL/al.h" -#include "AL/alc.h" -#include "AL/alext.h" - -#include "alhelpers.h" - - -static int done_init = 0; - -FilePtr openAudioFile(const char *fname, size_t buftime_ms) -{ - FilePtr file; - ALuint rate; - Uint32 bufsize; - ALenum chans, type; - - /* We need to make sure SDL_sound is initialized. */ - if(!done_init) - { - Sound_Init(); - done_init = 1; - } - - file = Sound_NewSampleFromFile(fname, NULL, 0); - if(!file) - { - fprintf(stderr, "Failed to open %s: %s\n", fname, Sound_GetError()); - return NULL; - } - - if(getAudioInfo(file, &rate, &chans, &type) != 0) - { - Sound_FreeSample(file); - return NULL; - } - - bufsize = FramesToBytes((ALsizei)(buftime_ms/1000.0*rate), chans, type); - if(Sound_SetBufferSize(file, bufsize) == 0) - { - fprintf(stderr, "Failed to set buffer size to %u bytes: %s\n", bufsize, Sound_GetError()); - Sound_FreeSample(file); - return NULL; - } - - return file; -} - -void closeAudioFile(FilePtr file) -{ - if(file) - Sound_FreeSample(file); -} - - -int getAudioInfo(FilePtr file, ALuint *rate, ALenum *channels, ALenum *type) -{ - if(file->actual.channels == 1) - *channels = AL_MONO_SOFT; - else if(file->actual.channels == 2) - *channels = AL_STEREO_SOFT; - else - { - fprintf(stderr, "Unsupported channel count: %d\n", file->actual.channels); - return 1; - } - - if(file->actual.format == AUDIO_U8) - *type = AL_UNSIGNED_BYTE_SOFT; - else if(file->actual.format == AUDIO_S8) - *type = AL_BYTE_SOFT; - else if(file->actual.format == AUDIO_U16LSB || file->actual.format == AUDIO_U16MSB) - *type = AL_UNSIGNED_SHORT_SOFT; - else if(file->actual.format == AUDIO_S16LSB || file->actual.format == AUDIO_S16MSB) - *type = AL_SHORT_SOFT; - else - { - fprintf(stderr, "Unsupported sample format: 0x%04x\n", file->actual.format); - return 1; - } - - *rate = file->actual.rate; - - return 0; -} - - -uint8_t *getAudioData(FilePtr file, size_t *length) -{ - *length = Sound_Decode(file); - if(*length == 0) - return NULL; - if((file->actual.format == AUDIO_U16LSB && AUDIO_U16LSB != AUDIO_U16SYS) || - (file->actual.format == AUDIO_U16MSB && AUDIO_U16MSB != AUDIO_U16SYS) || - (file->actual.format == AUDIO_S16LSB && AUDIO_S16LSB != AUDIO_S16SYS) || - (file->actual.format == AUDIO_S16MSB && AUDIO_S16MSB != AUDIO_S16SYS)) - { - /* Swap bytes if the decoded endianness doesn't match the system. */ - char *buffer = file->buffer; - size_t i; - for(i = 0;i < *length;i+=2) - { - char b = buffer[i]; - buffer[i] = buffer[i+1]; - buffer[i+1] = b; - } - } - return file->buffer; -} - -void *decodeAudioStream(FilePtr file, size_t *length) -{ - Uint32 got; - char *mem; - - got = Sound_DecodeAll(file); - if(got == 0) - { - *length = 0; - return NULL; - } - - mem = malloc(got); - memcpy(mem, file->buffer, got); - - *length = got; - return mem; -} diff --git a/examples/common/sdl_sound.h b/examples/common/sdl_sound.h deleted file mode 100644 index e93ab92b..00000000 --- a/examples/common/sdl_sound.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef EXAMPLES_SDL_SOUND_H -#define EXAMPLES_SDL_SOUND_H - -#include "AL/al.h" - -#include <SDL_sound.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Opaque handles to files and streams. Apps don't need to concern themselves - * with the internals */ -typedef Sound_Sample *FilePtr; - -/* Opens a file with SDL_sound, and specifies the size of the sample buffer in - * milliseconds. */ -FilePtr openAudioFile(const char *fname, size_t buftime_ms); - -/* Closes/frees an opened file */ -void closeAudioFile(FilePtr file); - -/* Returns information about the given audio stream. Returns 0 on success. */ -int getAudioInfo(FilePtr file, ALuint *rate, ALenum *channels, ALenum *type); - -/* Returns a pointer to the next available chunk of decoded audio. The size (in - * bytes) of the returned data buffer is stored in 'length', and the returned - * pointer is only valid until the next call to getAudioData. */ -uint8_t *getAudioData(FilePtr file, size_t *length); - -/* Decodes all remaining data from the stream and returns a buffer containing - * the audio data, with the size stored in 'length'. The returned pointer must - * be freed with a call to free(). Note that since this decodes the whole - * stream, using it on lengthy streams (eg, music) will use a lot of memory. - * Such streams are better handled using getAudioData to keep smaller chunks in - * memory at any given time. */ -void *decodeAudioStream(FilePtr, size_t *length); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* EXAMPLES_SDL_SOUND_H */ |