[Zurück] Inhaltsverzeichnis [Weiter]

Verwendung der "Simple DirectMedia Layer"-API

Audio

  • Das Audio-Gerät öffnen

Es muß eine Callback-Funktion geschrieben werden, die die Audiodaten mischt und in den Audio-Strom schreibt. Danach kann das Audio-Format und die Abtastrate ausgewählt und das Audio-Gerät geöffnet werden.

Der Sound wird erst gespielt, wenn SDL_PauseAudio(0) aufgerufen wird. So kann initialisiert werden, bevor das Callback angesprungen wird. Nach dem Ende der Audio-Ausgabe sollte SDL_CloseAudio() aufgerufen werden.

Tip:
Wenn ein Programm verschiedene Audioformate unterstützt, sollte man einen zweiten Parameter an SDL_AudioSpec() übergeben, um das Audioformat der Hardware abzufragen. Ist dieser Parameter NULL, werden die Audiodaten ggf. in das Format der Hardware umgewandelt.
Beispiel:
#include "SDL.h"
#include "SDL_audio.h"
{
    extern void mixeAudio(void *nichtVerwendet, Uint8 *stream, int laenge);
    SDL_AudioSpec format;

    /* Format: 16 Bit, stereo, 22 KHz */
    format.freq = 22050;
    format.format = AUDIO_S16;
    format.channels = 2;
    format.samples = 512;        /* ein guter Wert für Spiele */
    format.callback = mixeAudio;
    format.userdata = NULL;

    /* das Audio-Gerät öffnen und das Abspielen beginnen */
    if ( SDL_OpenAudio(&format, NULL) < 0 ) {
        fprintf(stderr, "Audio-Gerät konnte nicht geöffnet werden: %s\n", SDL_GetError());
        exit(1);
    }
    SDL_PauseAudio(0);

    ...

    SDL_CloseAudio();
}
  • Audio laden und abspielen

SDL stellt eine Funktion zum Einladen und Abspielen von Audio zur Verfügung: SDL_LoadWAV(). Nach dem Laden sollten die Audiodaten mit SDL_ConvertAudio() konvertiert und der eigenen Mixer-Funktion zur Verfügung gestellt werden.

Tip:
Die Audio-Möglichkeiten von SDL sind für einen einfachen Audio-Mixer gedacht. Ein Beispiel-Mixer unter der LGPL findet sich im SDL-Demoarchiv.
Beispiel:
#define NUM_SOUNDS 2
struct sample {
    Uint8 *data;
    Uint32 dpos;
    Uint32 dlen;
} sounds[NUM_SOUNDS];

void mixeAudio(void *nichtVerwendet, Uint8 *stream, int laenge)
{
    int i;
    Uint32 menge;

    for ( i=0; i<NUM_SOUNDS; ++i ) {
        menge = (sounds[i].dlen-sounds[i].dpos);
        if ( menge > laenge ) {
            menge = laenge;
        }
        SDL_MixAudio(stream, &sounds[i].data[sounds[i].dpos], menge, SDL_MIX_MAXVOLUME);
        sounds[i].dpos += menge;
    }
}

void spieleAudio(char *datei)
{
    int index;
    SDL_AudioSpec wave;
    Uint8 *data;
    Uint32 dlen;
    SDL_AudioCVT cvt;

    /* einen leeren Audio-Slot suchen */
    for ( index=0; index<NUM_SOUNDS; ++index ) {
        if ( sounds[index].dpos == sounds[index].dlen ) {
            break;
        }
    }
    if ( index == NUM_SOUNDS )
        return;

    /* Audio-Datei laden und nach 16 Bit und 22KHz wandeln */
    if ( SDL_LoadWAV(datei, &wave, &data, &dlen) == NULL ) {
        fprintf(stderr, "Konnte '%s' nicht laden: %s\n", datei, SDL_GetError());
        return;
    }
    SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq,
                            AUDIO_S16,   2,             22050);
    cvt.buf = malloc(dlen*cvt.len_mult);
    memcpy(cvt.buf, data, dlen);
    cvt.len = dlen;
    SDL_ConvertAudio(&cvt);
    SDL_FreeWAV(data);

    /* die Audiodaten in den Slot schreiben (Abspielen startet sofort) */
    if ( sounds[index].data ) {
        free(sounds[index].data);
    }
    SDL_LockAudio();
    sounds[index].data = cvt.buf;
    sounds[index].dlen = cvt.len_cvt;
    sounds[index].dpos = 0;
    SDL_UnlockAudio();
}

[Zurück] Inhaltsverzeichnis [Weiter]