OpenAL
|
OpenAL (Open Audio Library). Es una API de audio multiplataforma desarrollada por Creative Labs para el renderizado eficiente de audio posicional y multicanal en tres dimensiones. Está ideada para su uso en videojuegos y el estilo y convenciones del código es similar al de OpenGL.
Permite posicionar fuentes de sonido en espacios tridimensionales alrededor de un solo oyente, produciendo espacialización de las fuentes para un sistema de audio. OpenAL es apropiada para muchas aplicaciones de audio, pero fue diseñada fundamentalmente para su uso en videojuegos.
Introducción al OpenAL
El uso de OpenAL gira alrededor del uso de 3 objetos fundamentales, los búferes, las fuentes y el oyente. Un búfer puede ser llenado con datos de sonido, y puede ser asociado a una fuente. La fuente puede ser posicionada y reproducida en cualquier momento. Como la fuente es escuchada es determinada por la posición y orientación relativa a un oyente (solo hay uno). Creando unos números de fuentes y búferes y un solo oyente, y después actualizando la posición y orientación de las fuentes y el oyente dinámicamente pueden presentar un convincente sistema de audio de un mundo 3D.
Un objeto fuente además de contener un puntero a un búffer, cuenta con una serie de atributos como la velocidad, posición, dirección o intensidad del emisor de sonido. Un oyente contiene información sobre la velocidad, posición y orientación del sistema de referencia, además de la ganancia general aplicada a todo sonido. Los buffers contiene la información del sonido en formato PCM, bien en 8 o 16 bits, en formato mono o estéreo. El motor de renderizado se encarga de todos los cálculos necesarios como la atenuación, doppler, etc.

Enumeración de dispositivos
La función llamada para abrir un dispositivo es alcOpenDevice, toma una cadena como entrada. La cadena debe contener el nombre de un dispositivo valido de OpenAL, o NULL para utilizar un dispositivo por defecto.
Inicio y salida.
Como se describió anteriormente, el primer paso para inicializar OpenAL es abrir un dispositivo. Una vez hecho correctamente, entonces el contexto es abierto en ese dispositivo. Ahora los objetos fundamentales pueden ser manejados: el oyente, las fuentes y los búferes.
Para generar un conjunto de búferes, se debe usar primero la función alGetError para resetear el estado de error, llamar la función alGenBuffers para generar el número de búferes deseados, y el uso de alGetError de nuevo para detectar si hubo un error.
Para generar el conjunto de las Fuentes, utilizar alGetError para reiniciar el estado de error, llamar la función alGenSources para generar el numero deseado de fuentes, y después utilizar de nuevo alGetError para detectar algún error.
Los búferes pueden ser asociados a las fuentes utilizando alSourcei. Una vez realizado esto la fuente puede reproducir el búfer utilizando alSourcePlay. Las propiedades de la fuente y el oyente pueden ser actualizadas dinámicamente usando las conocidas funciones set y get, tales como alGetListenerfv, alListener3f, alSourcei, y alGetSource3f. Ejemplo de inicialización de OpenAL.
// Initialization Device = alcOpenDevice(NULL); // select the "preferred device" if (Device) { Context=alcCreateContext(Device,NULL); alcMakeContextCurrent(Context); } // Check for EAX 2.0 support g_bEAX = alIsExtensionPresent("EAX2.0"); // Generate Buffers alGetError(); // clear error code alGenBuffers(NUM_BUFFERS, g_Buffers); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alGenBuffers :", error); return; } // Load test.wav loadWAVFile("test.wav",&format,&data,&size,&freq,&loop); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alutLoadWAVFile test.wav : ", error); alDeleteBuffers(NUM_BUFFERS, g_Buffers); return; } // Copy test.wav data into AL Buffer 0 alBufferData(g_Buffers[0],format,data,size,freq); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alBufferData buffer 0 : ", error); alDeleteBuffers(NUM_BUFFERS, g_Buffers); return; } // Unload test.wav unloadWAV(format,data,size,freq); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alutUnloadWAV : ", error); alDeleteBuffers(NUM_BUFFERS, g_Buffers); return; } // Generate Sources alGenSources(1,source); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alGenSources 1 : ", error); return; } // Attach buffer 0 to source alSourcei(source[0], AL_BUFFER, g_Buffers[0]); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alSourcei AL_BUFFER 0 : ", error); } // Exit Context=alcGetCurrentContext(); Device=alcGetContextsDevice(Context); alcMakeContextCurrent(NULL); alcDestroyContext(Context); alcCloseDevice(Device);
Todas las propiedades de la fuente y del oyente se pueden encontrar OpenAL Programmer's Guide, así como códigos de ejemplo, cada una de ellas detallada y con ejemplos.
Otras características.
La API está disponible para las siguientes plataformas: Mac OS, Linux (tanto para OSS como para ALSA), *BSD, Solaris, Irix, Microsoft Windows, Sony PlayStation 2, Microsoft Xbox y Nintendo GameCube.
Con la intención de agregar funcionalidades extra en el futuro, OpenAL utiliza un mecanismo basado en extensiones. Cada cual puede incluir sus propias extensiones en la distribución de OpenAL, algo frecuente para enseñar o agregar funcionalidades de hardware propietario.
Las extensiones pueden ser promocionadas a un status ARB (Architecture Review Board), indicando una extensión estándar que será mantenida con compatibilidad hacia atrás. Las extensiones ARB pueden ser agregadas al núcleo de la API tras un cierto período.
Videojuegos que utilizan OpenAL
- Doom 3.
- Jedi Knight II: Jedi Outcast.
- Jedi Knight: Jedi Academy.
- Quake 4.
- Prey.
- Tremulous.
- Tremulous.
- Unreal 2.
- Unreal Tournament 2003.
- Unreal Tournament 2004.
- Unreal Tournament 3.
- Postal 2.
- America's Army.
- Hitman 2.
- Battlefield 2.
- Freedom Fighters.
- Psychonauts.
- Armed Assault.
- Race Driver GRID.
- Regnum Online.
- SuperTux 0.3.x.
- SuperTuxKart.
Ejemplo de código final
// Almacenador intermediario. ALuint Buffer[1]; // Fuente, punto emisor. ALuint Source[1]; // Posición de la fuente. ALfloat SourcePos[] = { 0.0, 0.0, 0.0 }; // Velocidad de la fuente. ALfloat SourceVel[] = { 0.0, 0.0, 0.0 }; // Posición del oyente. ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 }; // Velocidad del oyente. ALfloat ListenerVel[] = { 1.0, 0.0, 0.0 }; // Orientacion del oyente. (los primers 3 elementos son la del vector direccion "at" y los otros 3 son del vector superior "up") ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 }; int main(int argc, char* argv[]) { alutInit(&argc,argv); alGenBuffers(1, Buffer); if (alGetError() != AL_NO_ERROR) return AL_FALSE; ALenum format; ALsizei size; ALvoid* data; ALsizei freq; ALboolean loop; alutLoadWAVFile("sonido.wav", &format, &data, &size, &freq, &loop); alBufferData(Buffer[0], format, data, size, freq); alutUnloadWAV(format, data, size, freq); alGenSources(1, Source); if (alGetError() != AL_NO_ERROR) return AL_FALSE; alSourcei (Source[0], AL_BUFFER, Buffer[0] ); alSourcef (Source[0], AL_PITCH, 1.0f ); alSourcef (Source[0], AL_GAIN, 1.0f ); alSourcefv(Source[0], AL_POSITION, SourcePos); alSourcefv(Source[0], AL_VELOCITY, SourceVel); alSourcei (Source[0], AL_LOOPING, AL_FALSE ); alListenerfv(AL_POSITION, ListenerPos); alListenerfv(AL_VELOCITY, ListenerVel); alListenerfv(AL_ORIENTATION, ListenerOri); alSourcePlay(Source[0]); // alDeleteBuffers(1, &Buffer); // alDeleteSources(1, &Source); // alutExit(); system("pause"); return 0; }
Enlaces externos
Fuente
- OpenAL Programmer's Guide. 2007 By Creative Technology Limited.