summaryrefslogtreecommitdiff
path: root/src/libs/sound/openal/audiodrv_openal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/sound/openal/audiodrv_openal.c')
-rw-r--r--src/libs/sound/openal/audiodrv_openal.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/src/libs/sound/openal/audiodrv_openal.c b/src/libs/sound/openal/audiodrv_openal.c
new file mode 100644
index 0000000..eee1cd1
--- /dev/null
+++ b/src/libs/sound/openal/audiodrv_openal.c
@@ -0,0 +1,420 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* OpenAL audio driver
+ */
+
+#ifdef HAVE_OPENAL
+
+
+#include "audiodrv_openal.h"
+#include "../sndintrn.h"
+#include "libs/log.h"
+#include "libs/memlib.h"
+#include <stdlib.h>
+
+
+ALCcontext *alcContext = NULL;
+ALCdevice *alcDevice = NULL;
+ALfloat defaultPos[] = {0.0f, 0.0f, -1.0f};
+ALfloat listenerPos[] = {0.0f, 0.0f, 0.0f};
+ALfloat listenerVel[] = {0.0f, 0.0f, 0.0f};
+ALfloat listenerOri[] = {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f};
+
+static const audio_Driver openAL_Driver =
+{
+ openAL_Uninit,
+ openAL_GetError,
+ audio_DRIVER_OPENAL,
+ {
+ /* Errors */
+ AL_FALSE,
+ AL_INVALID_NAME,
+ AL_INVALID_ENUM,
+ AL_INVALID_VALUE,
+ AL_INVALID_OPERATION,
+ AL_OUT_OF_MEMORY,
+ audio_DRIVER_FAILURE,
+
+ /* Source properties */
+ AL_POSITION,
+ AL_LOOPING,
+ AL_BUFFER,
+ AL_GAIN,
+ AL_SOURCE_STATE,
+ AL_BUFFERS_QUEUED,
+ AL_BUFFERS_PROCESSED,
+
+ /* Source state information */
+ AL_INITIAL,
+ AL_STOPPED,
+ AL_PLAYING,
+ AL_PAUSED,
+
+ /* Sound buffer properties */
+ AL_FREQUENCY,
+ AL_BITS,
+ AL_CHANNELS,
+ AL_SIZE,
+ AL_FORMAT_MONO16,
+ AL_FORMAT_STEREO16,
+ AL_FORMAT_MONO8,
+ AL_FORMAT_STEREO8
+ },
+
+ /* Sources */
+ openAL_GenSources,
+ openAL_DeleteSources,
+ openAL_IsSource,
+ openAL_Sourcei,
+ openAL_Sourcef,
+ openAL_Sourcefv,
+ openAL_GetSourcei,
+ openAL_GetSourcef,
+ openAL_SourceRewind,
+ openAL_SourcePlay,
+ openAL_SourcePause,
+ openAL_SourceStop,
+ openAL_SourceQueueBuffers,
+ openAL_SourceUnqueueBuffers,
+
+ /* Buffers */
+ openAL_GenBuffers,
+ openAL_DeleteBuffers,
+ openAL_IsBuffer,
+ openAL_GetBufferi,
+ openAL_BufferData
+};
+
+
+/*
+ * Initialization
+ */
+
+sint32
+openAL_Init (audio_Driver *driver, sint32 flags)
+{
+ int i;
+ TFB_DecoderFormats formats =
+ {
+ MIX_IS_BIG_ENDIAN, MIX_WANT_BIG_ENDIAN,
+ audio_FORMAT_MONO8, audio_FORMAT_STEREO8,
+ audio_FORMAT_MONO16, audio_FORMAT_STEREO16
+ };
+
+ log_add (log_Info, "Initializing OpenAL.");
+ alcDevice = alcOpenDevice (NULL);
+
+ if (!alcDevice)
+ {
+ log_add (log_Error, "Couldn't initialize OpenAL: %d",
+ alcGetError (NULL));
+ return -1;
+ }
+
+ *driver = openAL_Driver;
+
+ alcContext = alcCreateContext (alcDevice, NULL);
+ if (!alcContext)
+ {
+ log_add (log_Error, "Couldn't create OpenAL context: %d",
+ alcGetError (alcDevice));
+ alcCloseDevice (alcDevice);
+ alcDevice = NULL;
+ return -1;
+ }
+
+ alcMakeContextCurrent (alcContext);
+
+ log_add (log_Info, "OpenAL initialized.\n"
+ " version: %s\n"
+ " vendor: %s\n"
+ " renderer: %s\n"
+ " device: %s",
+ alGetString (AL_VERSION), alGetString (AL_VENDOR),
+ alGetString (AL_RENDERER),
+ alcGetString (alcDevice, ALC_DEFAULT_DEVICE_SPECIFIER));
+ //log_add (log_Info, " extensions: %s", alGetString (AL_EXTENSIONS));
+
+ log_add (log_Info, "Initializing sound decoders.");
+ if (SoundDecoder_Init (flags, &formats))
+ {
+ log_add (log_Error, "Sound decoders initialization failed.");
+ alcMakeContextCurrent (NULL);
+ alcDestroyContext (alcContext);
+ alcContext = NULL;
+ alcCloseDevice (alcDevice);
+ alcDevice = NULL;
+ return -1;
+ }
+ log_add (log_Error, "Sound decoders initialized.");
+
+ alListenerfv (AL_POSITION, listenerPos);
+ alListenerfv (AL_VELOCITY, listenerVel);
+ alListenerfv (AL_ORIENTATION, listenerOri);
+
+ for (i = 0; i < NUM_SOUNDSOURCES; ++i)
+ {
+ float zero[3] = {0.0f, 0.0f, 0.0f};
+
+ alGenSources (1, &soundSource[i].handle);
+ alSourcei (soundSource[i].handle, AL_LOOPING, AL_FALSE);
+ alSourcefv (soundSource[i].handle, AL_POSITION, defaultPos);
+ alSourcefv (soundSource[i].handle, AL_VELOCITY, zero);
+ alSourcefv (soundSource[i].handle, AL_DIRECTION, zero);
+
+ soundSource[i].stream_mutex = CreateMutex ("OpenAL stream mutex", SYNC_CLASS_AUDIO);
+ }
+
+ if (InitStreamDecoder ())
+ {
+ log_add (log_Error, "Stream decoder initialization failed.");
+ // TODO: cleanup source mutexes [or is it "muti"? :) ]
+ SoundDecoder_Uninit ();
+ alcMakeContextCurrent (NULL);
+ alcDestroyContext (alcContext);
+ alcContext = NULL;
+ alcCloseDevice (alcDevice);
+ alcDevice = NULL;
+ return -1;
+ }
+
+ alDistanceModel (AL_INVERSE_DISTANCE);
+
+ (void) driver; // eat compiler warning
+
+ return 0;
+}
+
+void
+openAL_Uninit (void)
+{
+ int i;
+
+ UninitStreamDecoder ();
+
+ for (i = 0; i < NUM_SOUNDSOURCES; ++i)
+ {
+ if (soundSource[i].sample && soundSource[i].sample->decoder)
+ {
+ StopStream (i);
+ }
+ if (soundSource[i].sbuffer)
+ {
+ void *sbuffer = soundSource[i].sbuffer;
+ soundSource[i].sbuffer = NULL;
+ HFree (sbuffer);
+ }
+ DestroyMutex (soundSource[i].stream_mutex);
+ }
+
+ alcMakeContextCurrent (NULL);
+ alcDestroyContext (alcContext);
+ alcContext = NULL;
+ alcCloseDevice (alcDevice);
+ alcDevice = NULL;
+
+ SoundDecoder_Uninit ();
+}
+
+
+/*
+ * General
+ */
+
+sint32
+openAL_GetError (void)
+{
+ ALint value = alGetError ();
+ switch (value)
+ {
+ case AL_FALSE:
+ return audio_NO_ERROR;
+ case AL_INVALID_NAME:
+ return audio_INVALID_NAME;
+ case AL_INVALID_ENUM:
+ return audio_INVALID_ENUM;
+ case AL_INVALID_VALUE:
+ return audio_INVALID_VALUE;
+ case AL_INVALID_OPERATION:
+ return audio_INVALID_OPERATION;
+ case AL_OUT_OF_MEMORY:
+ return audio_OUT_OF_MEMORY;
+ default:
+ log_add (log_Debug, "openAL_GetError: unknown value %x", value);
+ return audio_DRIVER_FAILURE;
+ break;
+ }
+}
+
+
+/*
+ * Sources
+ */
+
+void
+openAL_GenSources (uint32 n, audio_Object *psrcobj)
+{
+ alGenSources ((ALsizei) n, (ALuint *) psrcobj);
+}
+
+void
+openAL_DeleteSources (uint32 n, audio_Object *psrcobj)
+{
+ alDeleteSources ((ALsizei) n, (ALuint *) psrcobj);
+}
+
+bool
+openAL_IsSource (audio_Object srcobj)
+{
+ return alIsSource ((ALuint) srcobj);
+}
+
+void
+openAL_Sourcei (audio_Object srcobj, audio_SourceProp pname,
+ audio_IntVal value)
+
+{
+ alSourcei ((ALuint) srcobj, (ALenum) pname, (ALint) value);
+}
+
+void
+openAL_Sourcef (audio_Object srcobj, audio_SourceProp pname,
+ float value)
+{
+ alSourcef ((ALuint) srcobj, (ALenum) pname, (ALfloat) value);
+}
+
+void
+openAL_Sourcefv (audio_Object srcobj, audio_SourceProp pname,
+ float *value)
+{
+ alSourcefv ((ALuint) srcobj, (ALenum) pname, (ALfloat *) value);
+}
+
+void
+openAL_GetSourcei (audio_Object srcobj, audio_SourceProp pname,
+ audio_IntVal *value)
+{
+ alGetSourcei ((ALuint) srcobj, (ALenum) pname, (ALint *) value);
+ if (pname == AL_SOURCE_STATE)
+ {
+ switch (*value)
+ {
+ case AL_INITIAL:
+ *value = audio_INITIAL;
+ break;
+ case AL_STOPPED:
+ *value = audio_STOPPED;
+ break;
+ case AL_PLAYING:
+ *value = audio_PLAYING;
+ break;
+ case AL_PAUSED:
+ *value = audio_PAUSED;
+ break;
+ default:
+ log_add (log_Debug, "openAL_GetSourcei(): unknown value %x",
+ *value);
+ *value = audio_DRIVER_FAILURE;
+ }
+ }
+}
+
+void
+openAL_GetSourcef (audio_Object srcobj, audio_SourceProp pname,
+ float *value)
+{
+ alGetSourcef ((ALuint) srcobj, (ALenum) pname, (ALfloat *) value);
+}
+
+void
+openAL_SourceRewind (audio_Object srcobj)
+{
+ alSourceRewind ((ALuint) srcobj);
+}
+
+void
+openAL_SourcePlay (audio_Object srcobj)
+{
+ alSourcePlay ((ALuint) srcobj);
+}
+
+void
+openAL_SourcePause (audio_Object srcobj)
+{
+ alSourcePause ((ALuint) srcobj);
+}
+
+void
+openAL_SourceStop (audio_Object srcobj)
+{
+ alSourceStop ((ALuint) srcobj);
+}
+
+void
+openAL_SourceQueueBuffers (audio_Object srcobj, uint32 n,
+ audio_Object* pbufobj)
+{
+ alSourceQueueBuffers ((ALuint) srcobj, (ALsizei) n, (ALuint *) pbufobj);
+}
+
+void
+openAL_SourceUnqueueBuffers (audio_Object srcobj, uint32 n,
+ audio_Object* pbufobj)
+{
+ alSourceUnqueueBuffers ((ALuint) srcobj, (ALsizei) n, (ALuint *) pbufobj);
+}
+
+
+/*
+ * Buffers
+ */
+
+void
+openAL_GenBuffers (uint32 n, audio_Object *pbufobj)
+{
+ alGenBuffers ((ALsizei) n, (ALuint *) pbufobj);
+}
+
+void
+openAL_DeleteBuffers (uint32 n, audio_Object *pbufobj)
+{
+ alDeleteBuffers ((ALsizei) n, (ALuint *) pbufobj);
+}
+
+bool
+openAL_IsBuffer (audio_Object bufobj)
+{
+ return alIsBuffer ((ALuint) bufobj);
+}
+
+void
+openAL_GetBufferi (audio_Object bufobj, audio_BufferProp pname,
+ audio_IntVal *value)
+{
+ alGetBufferi ((ALuint) bufobj, (ALenum) pname, (ALint *) value);
+}
+
+void
+openAL_BufferData (audio_Object bufobj, uint32 format, void* data,
+ uint32 size, uint32 freq)
+{
+ alBufferData ((ALuint) bufobj, (ALenum) format, (ALvoid *) data,
+ (ALsizei) size, (ALsizei) freq);
+}
+
+#endif