Thursday, 1 March 2007

OpenAL hello world!

OpenAL are for audio what OpenGL are for video: a cross-platform, and open source, set of API useful for creating a realistic tridimensional audio environment.

Exactly like OpenGL, they're easy to learn and well documented. They don't handle MIDI yet, therefore I used them only to play samples, triggered by the numerical pad on the wrist of powerglove.

I quit using playsound() Windows primitive for it is too cheap: no multibuffering, no pitch control, no positioning... just playing. Instead, I wanna play several alien-related noise at a time, launch drum loops and so on.

So, let's see how to play something. First, you have to download OpenAL SDK, libraries and documentations from the official site. Once installed, link libraries to your project and put the headers in your code (al.h, alc.h, alut.h).

Then, simply:

alutInit(NULL, NULL);

to erase any pending AL process. Now, we have to open a sound device and, for any device, we must define a "context" to place the sounds in. We can make this by coding:

ALCdevice* device;
ALCcontext* context;
device = alcOpenDevice(NULL);
context = alcCreateContext(device, NULL);

alGetError() returns AL_NO_ERROR if opening procedure went ok. If it happened, we have correctly initialized OpenAL. Done this, it's time to place a listener (imagine Doom - it's the spacemarine!); listener has 3 important features: a position, a velocity and an orientation. Every parameters help OpenAL to render sounds, as it happens in OpenGL environment. They're very similar as approach.

ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 0.0, 0.0 };

alListenerfv(AL_POSITION, ListenerPos);
alListenerfv(AL_VELOCITY, ListenerVel);
alListenerfv(AL_ORIENTATION, ListenerOri);

Check out documentation for the meaning of every floating-point value. Now it's time to load a wave file in memory, decant it into a buffer to be used by OpenAL routines and launch it.

ALuint Buffer;

ALenum formato;
ALsizei dimensione;
ALvoid* dati;
ALsizei frequenza;
ALboolean loop;

alGenBuffers(1, &Buffer);
alutLoadWAVFile(percorso, &formato, &dati, &dimensione, &frequenza, &loop);
alBufferData(Buffer, formato, dati, dimensione, frequenza);
alutUnloadWAV(formato, dati, dimensione, frequenza);

It's very clear what happens: we generate a buffer, load the wave into the buffer catching informations, load the wave into the generated buffer, and unload wave from memory.

Finally, we have to bind the buffer to a source and play it:

/* generate source */
alGenSources(1, &Source);

/* place it */
ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };
ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };

/* options */
alSourcei (Source, AL_BUFFER, Buffer );
alSourcef (Source, AL_PITCH, 1.0f );
alSourcef (Source, AL_GAIN, 1.0f );
alSourcefv(Source, AL_POSITION, SourcePos);
alSourcefv(Source, AL_VELOCITY, SourceVel);
alSourcei (Source, AL_LOOPING,

/* riproduco sorgente */

You're done. It's really that simple. Amazing!


Gatta Silvestre said...

La tua principessa ti ha abbandonato oh bellissimo "principe cieco"...?
...allora "ascolta" questo bacio di conforto regalato da un' "ombra ansiosa"!!!

Aresio said...

improvvisamente, la mia principessa mi manca molto meno :D

ricambio il bacione bella miciona! :*

Donna del Mare said...

hahaha MAIALI
mi tradite cos',entrambi, facendovela tra di voi?

vabe vabeh..

Aresio said...

hai ragione ma... รจ troppo bona per opporre resistenza! :D

amah :*

Gatta Silvestre said...

Ah ah ah...

La conosci la mia passione per i

:D... baciiiii, ombrosetti, ma sempre baci per voi!!

Anonymous said...

The information were very helpful for me, I've bookmarked this post, Please share more information about this