Theorie

Um generell zu verstehen, wie OpenAL funktioniert beginne ich hier mit etwas Theorie (im folgenden Kapitel wird das Wissen dann angewendet):

OpenAL Gerätekontext öffnen

Um OpenAL nutzen zu können, müssen Sie OpenAL initialisieren. Folgender Code übernimmt das für Sie:

alutInit(0, NULL);  // initialisiert OpenAL
alGetError();       // leert den Fehlerpuffer, damit wir neue Fehlercodes abfangen können

Wenn Ihr Programm beendet wird, dürfen Sie nicht vergessen OpenAL zu beenden. Dazu können Sie die Funktion atexit() benutzen. Schreiben Sie sich dazu eine Funktion, die alle Buffer und Sources löscht (dazu kommen wir gleich noch) und den Gerätekontext schließt:

void CloseOpenAL()
{
    alDeleteSources(1, source);    // löscht die Source
    alDeleteBuffers(1, buffers);   // löscht den Buffer
    alutExit();                    // Schließt den Gerätekontext
}

Damit der Code am Ende des Programms ausgeführt wird, fügen Sie in Ihr Hauptprogramm folgende Zeile ein:

atexit(&CloseOpenAL);

Buffers und Sources

OpenAL unterscheidet Prinzipiell zwei Dinge: Buffers und Sources. Ein Buffer bezeichnet einen Puffer, der die eigentlichen Audiodaten enthält, ein Source ist an einen Buffer geknüpft. Der Buffer kann nicht direkt abgespielt werden, sondern Sie können lediglich die Source abspielen. Es ist generell möglich mehrere Sources und Buffer zu haben, und es ist sogar üblich mehr Sources als Buffer zu haben. Hier werde ich jeweils nur einen Buffer und eine Source anlegen.

Das heißt wir laden jetzt die WAV-Datei, die wir abspielen wollen, in einen Buffer und knüpfen daran eine Source, die wir abspielen können.

Als Erstes generieren wir einen Buffer. Das geschieht mit der Funktion alGenBuffers:

ALuint buffer;
alGenBuffers(1, buffers);

Es ist generell sicherer, wenn Sie nach jeder Aktion auf Fehler prüfen. Ich werde das Ganze aber nur einmal zeigen:

int error=0;
if ((error=alGetError()) != AL_NO_ERROR)
{
    printf("Fehler: %d\n", error);
}

Anhand des Fehlercodes können Sie auf die Ursache für den Fehler schließen.

Beginnen wir nun mit dem Laden der eigentlichen WAV-Datei. Die Datei heißt hier example.wav. Beim Laden der Datei müssen wir nicht nur die Daten der Datei abfangen, sondern auch andere Informationen, die wir im Weiteren benötigen.

ALvoid* data;
ALenum format;
ALsizei size;
ALfloat freq;
 
data=alutLoadMemoryFromFile("example.wav", &format, &size, &freq);
    // Lädt die WAV-Datei in den Speicher, reserviert den Speicher und gibt
    // einen Zeiger auf den Sound im Speicher zurück
alBufferData(buffer, format, data, size, freq);
    // befüllt den oben generierten Buffer.
free (data);
    // entlädt die Daten aus dem Hauptspeicher. 

alutLoadMemoryFromFile lädt die Datei, reserviert Speicher, gibt einen Zeiger auf das Speicherelement zurück und gibt Ihnen außerdem noch Informationen über Format, Größe und Frequenz des Sounds an. Diese Übergeben Sie alBufferData. Die geladenen Daten werden nun nicht mehr benötigt und können mit free entladen werden.

Nun generieren wir die Source, nach dem gleichen Prinzip wie wir oben den Buffer generiert haben:

ALuint source;
 
alGenSources(1, source);
    // generiert die Source

Nun verwenden wir die Funktion alSourcei um die Quelle mit einem Buffer zu verknüpfen. alSourcei verlangt einen Integerwert.

alSourcei(source, AL_BUFFER, buffer);

Jetzt können wir der Source Attribute wie Position, Geschwindigkeit und Richtung geben. Dazu benutzen wir die Funktion alSourcefv (die einen Float-Vektor, also ein Float-Array, verlangt):

float def_pos[3]={0,0,1};
float def_velocity[3]={0,0,0};
float def_orientation[6]={0,0,-1};
 
alSourcefv (source, AL_POSITION, def_pos);
alSourcefv (source, AL_VELOCITY, def_velocity);
alSourcefv (source, AL_DIRECTION, def_orientation);

Listener

Ein Listener ist der Hörer. Sie können sich den Hörer wie ein paar Ohren vorstellen, die sich durch den Raum bewegen können. Übergeben Sie auch dem Listener Werte für die Position, Geschwindigkeit und Richtung (die Richtung ist ein Array mit 6 Elementen, die ersten drei geben die Richtung an, die letzten drei geben den Vektor (der angibt wo Oben ist) an). Hier im Beispiel übergebe ich dem Hörer die gleichen Werte wie oben der Source:

alListenerfv(AL_POSITION, def_pos);
alListenerfv(AL_VELOCITY, def_velocity);
float def_ori[6]={0,0,0,0,1,0};
alListenerfv(AL_ORIENTATION, def_ori);

Beachten Sie, dass das ALenum-Element für die Richtung hier nicht AL_DIRECTION heißt, sondern AL_ORIENTATION.

Sounds abspielen und stoppen

OpenAL ist nun bereit zum Abspielen des Sounds. Verwenden Sie dazu die Funktion alSourcePlay:

alSourcePlay(source);

Wenn Sie die Source pausieren oder stoppen wollen, verwenden Sie die entsprechende Funktion:

alSourcePause(source);  // Pausieren der Source
alSourceStop(source);   // Stoppen der Source

Sollten Sie Sounds im Schleife laufen lassen wollen, können Sie die Eigenschaft LOOPING mithilfe von alSourcei setzen:

alSourcei(source, AL_LOOPING, true);

Für Weitere sinnvolle Funktionen sollten Sie das Programmierer-Handbuch zu OpenAL bzw. alut (AL Utility Toolkit) konsultieren.