FAQ SDLConsultez toutes les FAQ

Nombre d'auteurs : 6, nombre de questions : 67, création le 10 mai 2013 

 
OuvrirSommaireAudio

Si vous voulez juste jouer quelques fichiers, vous pouvez simplement utiliser les fonctions définies dans SDL_audio.h.

Ce module ne permet par contre que de manipuler le format WAV, ce qui peut être ennuyeux si vous avez un problème d'utilisation disque (voir http://jeux.developpez.com/faq/sdl/?page=audio#AUDIO_formats).

Créé le 16 mars 2006  par fearyourself

La bibliothèque de base SDL permet de lire facilement les fichiers au format WAV, mais uniquement ceux-ci. Cependant, il faut travailler un peu pour faire jouer plusieurs morceaux en même temps.

Afin d'accéder à d'autres formats et à d'autres fonctionnalités, on peut utiliser les bibliothèques auxiliaires de la SDL. Les deux possibles sont :

  • SDL_sound ;
  • SDL_mixer.

Les deux permettent de lire la plupart des formats (WAV, MP3, OGG…). Ensuite, l'avantage de SDL_mixer est la possibilité de facilement faire jouer plusieurs sons en même temps (c'est possible avec SDL_sound, mais cela demande un peu plus de boulot).

Créé le 16 mars 2006  par fearyourself

Lien : Documentation de référence de SDL_mixer
Lien : Documentation de référence de SDL_sound

Lorsque nous utilisons les fonctions de base SDL pour le son, nous devons définir une fonction qui sera appelée pour jouer les sons (ou mixer). Son prototype est le suivant :

 
Sélectionnez
void joue_audio(void *udata, Uint8 *stream, int len);

Le premier argument est utilisé par le programmeur pour donner des informations diverses ou pour donner les différents flux utilisés. Il s'agit généralement d'un pointeur vers une structure/classe globale qui contient tous les flux audio en cours d'utilisation.

Dire à SDL d'appeler cette fonction se fait avec la fonction suivante :

 
Sélectionnez
extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec *desired, SDL_AudioSpec *obtained);

Le premier argument représente ce que nous voudrions comme flux, on définit généralement ces éléments de la structure SDL_AudioSpec :

 
Sélectionnez
/* Définir le format audio*/
flux.freq = 22050;
flux.format = AUDIO_S16;
flux.channels = 2;    /* 1 = mono, 2 = stéréo */
flux.samples = 1024;  /* Une bonne valeur pour le temps entre appels */
flux.callback = joue_audio; /* Mise en place de l'appel vers notre fonction */
flux.userdata = nosmusique; /* On utilisera un pointeur vers nos musiques */
Créé le 16 mars 2006  par fearyourself

On commence par définir une structure permettant d'avoir le flux audio, la position courante dans le flux audio ainsi que sa longueur :

 
Sélectionnez
struct sample
{
    Uint8 *data;
    Uint32 dpos;
    Uint32 dlen;
};

Il faut maintenant la remplir. Nous avons besoin pour cela de quatre variables locales :

 
Sélectionnez
void PlaySound(const char *fichier, struct sample *son)
{
    SDL_AudioSpec wav;    /* La structure qui contiendra les informations du fichier */
    Uint8 *donnees;       /* Le pointeur vers les données audio */
    Uint32 dlong;         /* La longueur du flux audio */
    SDL_AudioCVT cvt;     /* La structure de conversion utilisée par SDL */

Ensuite, on charge le fichier audio :

 
Sélectionnez
    /* Charger le son en utilisant en SDL_LoadWave */
    if ( SDL_LoadWAV(fichier, &wav, &donnees, &dlong) == NULL )
    {
        fprintf(stderr, "Erreur chargeant %s: %s\n", fichier, SDL_GetError());
        return;
    }

Nous avons maintenant un flux wav, mais nous devons le convertir afin que SDL puisse s'en servir. Ceci se fait avec la fonction SDL_BuildAudioCVT. Les trois derniers paramètres doivent être les mêmes que ce qui a été passé à SDL_OpenAudio (voir http://jeux.developpez.com/faq/sdl/?page=audio#AUDIO_ouvrir_flux).

 
Sélectionnez
    SDL_BuildAudioCVT(&cvt, wav.format, wav.channels, wav.freq, AUDIO_S16, 2, 22050);

    /* Mise en place de la structure cvs */
    cvt.buf = malloc(dlong*cvt.len_mult); 
    memcpy(cvt.buf, donnees, dlong);
    cvt.len = dlong;

    /* On convertit */
    SDL_ConvertAudio(&cvt);

    /* On libère la mémoire */
    SDL_FreeWAV(donnees);

Ensuite on va mettre à jour notre variable qui va contenir le son. Il se peut que ce son soit en cours d'utilisation. Visiblement, le programme veut utiliser cette zone mémoire, donc on arrête le son pour mettre à jour l'information. Ceci est fait en utilisant les fonctions SDL_LockAudio et SDL_UnlockAudio.

 
Sélectionnez
    /* Pour arrêter le son pendant qu'on change le pointeur son ; cela arrête le callback */
    SDL_LockAudio();

    son->donnees = cvt.buf;
    son->dlong = cvt.len_cvt;
    son->dpos = 0;

    /* Pour remettre en place le callback */
    SDL_UnlockAudio();
}
Créé le 16 mars 2006  par fearyourself

Cette fonction est appelée lorsque SDL a terminé de jouer le flux audio courant. Il faut donc mettre dans le flux le reste du son à jouer. Nous pouvons aussi mélanger plusieurs flux audio provenant de différentes sources pour jouer plusieurs morceaux en même temps.

Rappelons que cette fonction prend trois arguments. Le premier est un pointeur vers nos flux audio et, peut-être, d'autres informations nécessaires. Nous définissons ce pointeur lors de l'appel à SDL_OpenAudio.

Dans mon exemple, c'est un pointeur vers un tableau de flux (voir http://jeux.developpez.com/faq/sdl/?page=audio#AUDIO_ouvrir_flux pour l'utilisation de SDL_OpenAudio et la définition de la structure).

Le deuxième paramètre est le flux que SDL va jouer à la sortie de cette fonction. Ce flux a une longueur len. Pour chaque morceau que nous voulons jouer, nous regardons combien d'octets il y a encore à jouer et nous comparons cette longueur avec la longueur du flux à jouer. De façon évidente, nous prenons le minimum des deux.

 
Sélectionnez
void fill_audio(void *udata, Uint8 *stream, int len)
{
    int i; Uint32 amount;
    struct sample *ptr = udata;

    /* On parcourt chaque son, s'il n'y en a pas dans la case, amount sera égale à 0 */
    for ( i=0; i<NUM_SOUNDS; ++i )
    {
        /* On regarde ce qui reste à jouer */
       amount = (ptr[i].dlen-ptr[i].dpos);

       /* On regarde la taille du flux qu'on va à présent jouer */
       if ( amount > len )
           amount = len;

       /* On mixe le son */
       SDL_MixAudio(stream, &ptr[i].data[ptr[i].dpos], amount, SDL_MIX_MAXVOLUME);

       /* On met à jour la position du flux audio */
       ptr[i].dpos += amount;
   }
}
Créé le 16 mars 2006  par fearyourself
  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006-2012 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.