OpenAL

OpenAL
Información sobre la plantilla
Openalp1.jpg
API multiplataforma de audio para audio posicional y multicanal en tres dimensiones.

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.

Esquema que relaciona los elementos fundamentales de la biblioteca

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.