Mis à jour le jeudi 19 octobre 2017
  • 40 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Jouer du son avec FMOD

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Depuis que nous avons découvert la SDL, nous avons appris à placer des images dans la fenêtre, à faire interagir l'utilisateur avec le clavier et la souris, à écrire du texte, mais il manque clairement un élément : le son !

Ce chapitre va combler ce manque. Parce que les possibilités offertes par la SDL en matière d'audio sont très limitées, nous allons découvrir ici une bibliothèque spécialisée dans le son : FMOD.

Installer FMOD

Pourquoi FMOD ?

Vous le savez maintenant : la SDL n'est pas seulement une bibliothèque graphique. Elle permet aussi de gérer le son via un module appeléSDL_audio. Alors que vient faire dans ce chapitre une bibliothèque externe qui n'a rien à voir comme FMOD ?

C'est en fait un choix que j'ai fait après de nombreux tests. J'aurais pu vous expliquer comment gérer le son en SDL mais j'ai préféré ne pas le faire.
Je m'explique.

Pourquoi j'ai évitéSDL_audio

La gestion du son en SDL est « bas niveau ». Trop à mon goût. Il faut effectuer plusieurs manipulations très précises pour jouer du son. C'est donc complexe et je ne trouve pas ça amusant. Il y a bien d'autres bibliothèques qui proposent de jouer du son simplement.

Autre détail important, la SDL ne permet de jouer que des sons au format WAV. Le format WAV est un format de son non compressé. Une musique de 3 minutes dans ce format prend plusieurs dizaines de Mo, contrairement à un format compressé comme MP3 ou Ogg qui occupe beaucoup moins d'espace (2 à 3 Mo).

En fait, si on y réfléchit bien, c'était un peu pareil avec les images. La SDL ne gère que les BMP (images non compressées) à la base. On a dû installer une bibliothèque supplémentaire (SDL_image) pour pouvoir lire d'autres images comme les JPEG, PNG, GIF, etc.

Eh bien figurez-vous qu'il y a une bibliothèque équivalente pour le son :SDL_mixer. Elle est capable de lire un grand nombre de formats audio, parmi lesquels les MP3, les Ogg, les Midi… Et pourtant, là encore j'ai évité de vous parler de cette bibliothèque. Pourquoi ?

Pourquoi j'ai évitéSDL_mixer

SDL_mixerest une bibliothèque qu'on ajoute en plus de la SDL, à la manière deSDL_image. Elle est simple à utiliser et lit beaucoup de formats audio différents. Toutefois, après mes tests, il s'est avéré que la bibliothèque comportait des bugs gênants en plus d'être relativement limitée en fonctionnalités.

C'est donc pour cela que je me suis ensuite penché sur FMOD, une bibliothèque qui n'a certes rien à voir avec la SDL, mais qui a l'avantage d'être puissante et réputée.

Télécharger FMOD

Si je vous raconte tout ça, c'est pour vous expliquer que le choix de FMOD n'est pas anodin. C'est tout simplement parce que c'est la meilleure bibliothèque gratuite que j'ai pu trouver.
Elle est aussi simple à utiliser queSDL_mixer, avec un avantage non négligeable : elle n'est pas buggée.

FMOD permet en outre de réaliser plusieurs effets intéressants queSDL_mixerne propose pas, comme des effets sonores 3D.

Il existe plusieurs versions de FMOD, en particulier celle destinée à une utilisation sous des OS dits habituels (Linux, Windows, Mac…), elle s'appelle FMOD Ex Programmers API.

Téléchargez donc la version de FMOD Ex correspondant à votre OS. Prenez la version dite « stable ».
Vérifiez en particulier si vous avez un OS 32 bits ou 64 bits (sous Windows, faites un clic droit sur « Ordinateur », puis « Propriétés » pour le savoir).

Télécharger FMOD

Installer FMOD

L'installation fonctionne sur le même principe que les autres bibliothèques, comme la SDL.

Le fichier que vous avez téléchargé est normalement un exécutable (sous Windows), ou une archive (.dmg sous Mac, .tar.gz sous Linux). Je vais détailler ici la procédure sous Windows, mais cela fonctionne sur le même principe sous Mac OS X et Linux.

  1. Installez FMOD Ex sur votre disque. Les fichiers dont nous avons besoin seront placés dans un répertoire similaire à celui-ci :C:\Program Files\FMOD SoundSystem\FMOD Programmers API Win32\api.

  2. Dans ce dossier, vous trouverez la DLL de FMOD Ex (fmodex.dll) à placer dans le répertoire de votre projet. L'autre DLL,fmodexL.dll, sert à effectuer du débogage. Nous n'en ferons pas ici. Retenez surtout que c'est le fichierfmodex.dllque vous devrez livrer avec votre programme.

  3. Dans le dossierapi/inc, vous trouverez les.h. Placez-les à côté des autres.hdans le dossier de votre IDE. Par exempleCode Blocks/mingw32/include/fmodex(j'ai créé un dossier spécial pour FMOD comme pour SDL).

  4. Dans le dossierapi/lib, récupérez le fichier qui correspond à votre compilateur. Un fichier texte doit vous indiquer quel fichier vous devez prendre :

      • Si vous utilisez Code Blocks, donc le compilateur mingw, copiezlibfmodex.adans le dossierlibde votre IDE.

    Dans le cas de Code Blocks, c'est le dossierCodeBlocks/mingw32/lib;

    • Si vous utilisez Visual C++, récupérez le fichierfmodex_vc.lib.

  5. Enfin, et c'est peut-être le plus important, il y a un dossierdocumentationdans le répertoire de FMOD Ex. Normalement, des raccourcis ont été créés dans le menuDémarrervers cette documentation. Gardez un œil dessus, car nous ne pourrons pas découvrir toutes les fonctionnalités de FMOD Ex dans ce cours. Vous en aurez très certainement besoin dans peu de temps.

Il reste à configurer notre projet. Là encore, c'est comme les autres fois : vous ouvrez votre projet avec votre IDE favori et vous ajoutez le fichier.a(ou.lib) à la liste des fichiers que le linker doit récupérer.
Sous Code Blocks (j'ai l'impression de me répéter), menuProject > Build Options, ongletLinker, cliquez surAddet indiquez où se trouve le fichier.a. Si on vous demande « Keep as a relative path ? », je vous conseille de répondre non, mais de toute manière cela devrait fonctionner dans les deux cas.

FMOD Ex est installé, voyons rapidement de quoi il est constitué.

Initialiser et libérer un objet système

La librairie FMOD Ex est disponible pour les deux langages C et C++.
Sa particularité c'est que les développeurs de cette librairie ont gardé une certaine cohérence de syntaxe dans les deux langages. Le premier avantage est que si vous apprenez à manipuler FMOD Ex en C, vous savez le faire en C++ à 95%.

Inclure le header

Avant toute chose, vous avez dû le faire instinctivement maintenant mais ça ne coûte rien de le préciser, il faut inclure le fichier.hde FMOD.

#include <fmodex/fmod.h>

J'ai placé ce fichier dans un sous-dossierfmodex. Adaptez cette ligne en fonction de la position du fichier si c'est différent chez vous.
Si vous êtes sous Linux, l'installation se fait automatiquement dans le dossierfmodex.

Créer et initialiser un objet système

Un objet système est une variable qui nous servira tout au long du programme à définir des paramètres de la librairie.
Rappelez-vous qu'avec SDL par exemple, il fallait initialiser la lib explicitement avec une fonction. Ici, le mode d'emploi est un petit peu différent : au lieu d'initialiser toute la librairie, on travaille avec un objet dont le rôle est de définir le comportement de celle-ci.

Pour créer un objet système, il suffit de déclarer un pointeur sur le typeFMOD_SYSTEM. Par exemple :

FMOD_SYSTEM *system;

Pour allouer dans la mémoire cet objet système, on utilise la fonctionFMOD_System_Createdont voici le prototype :

FMOD_RESULT FMOD_System_Create(
  FMOD_SYSTEM **  system
);

Remarquons que cette fonction prend en paramètre un pointeur sur un pointeur deFMOD_SYSTEM.
Les plus agiles d'entre vous auront remarqué que lors de la déclaration du pointeur surFMOD_SYSTEM, il n'a pas été alloué avecmalloc()ou une autre fonction. C'est justement la raison pour laquelle la fonctionFMOD_System_Createprend un tel paramètre pour, entre autres, allouer le pointeur system.

Concrètement, après avoir déclaré notre objet système, il suffit de faire :

FMOD_SYSTEM *system;
FMOD_System_Create(&system);

Voilà, maintenant on dispose d'un objet système alloué, il ne reste plus qu'à l'initialiser. Pour ce faire, on utilise la fonctionFMOD_System_Initdont le prototype est :

FMOD_RESULT FMOD_System_Init(
  FMOD_SYSTEM *  system,
  int  maxchannels, 
  FMOD_INITFLAGS  flags, 
  void *  extradriverdata
);
  • Le paramètresystemest le paramètre qui nous intéresse le plus, car c'est le pointeur qu'on veut initialiser.

  • Le paramètremaxchannelsest le nombre maximum de canaux que devra gérer FMOD. En d'autres termes, c'est le nombre maximal de sons qui pourront être joués en même temps. Tout dépend de la puissance de votre carte son ; on conseille généralement une valeur de 32 (ce sera suffisant pour la plupart des petits jeux). Pour info, FMOD peut théoriquement gérer jusqu'à 1024 canaux différents, mais à ce niveau ça risque de beaucoup faire travailler votre ordinateur !

  • Le paramètreflagne nous intéressera pas énormément dans ce cours ; on se contentera de lui donner la valeurFMOD_INIT_NORMAL.

  • Le paramètreextradriverdatane nous intéressera pas non plus, et on lui donnera comme valeurNULL.

Par exemple, pour déclarer, allouer et initialiser un objet système, on fera comme suit :

FMOD_SYSTEM *system;
FMOD_System_Create(&system);
FMOD_System_Init(system, 2, FMOD_INIT_NORMAL, NULL);

Maintenant, nous disposons d'un objet système prêt à l'emploi.

Fermer et libérer un objet système

On ferme puis on libère un objet système avec deux fonctions :

FMOD_System_Close(system);
FMOD_System_Release(system);

Ai-je vraiment besoin de commenter ce code ?

Les sons courts

Nous commencerons par étudier les sons courts.
Un « son court », comme je l'appelle, est un son qui dure généralement quelques secondes (parfois moins d'une seconde) et qui est généralement destiné à être joué régulièrement.

Quelques exemples de sons courts :

  • un bruit de balle ;

  • un bruit de pas ;

  • un tic-tac (pour faire stresser le joueur avant la fin d'un compte à rebours) ;

  • des applaudissements ;

  • etc.

Bref, ça correspond à tous les sons qui ne sont pas des musiques.
Généralement, ces sons sont tellement courts qu'on ne prend pas la peine de les compresser. On les trouve donc le plus souvent sous le format WAV non compressé.

Trouver des sons courts

Avant de commencer, il serait bien de connaître quelques sites qui proposent des banques de sons. En effet, tout le monde ne veut pas forcément enregistrer les sons chez soi.

Ça tombe bien, le net regorge de sons courts, généralement au format WAV.
Où les trouver ? Ça peut paraître bête, on n'y pense pas forcément (et pourtant on devrait), mais Google est notre ami. Au hasard, je tape « Free Sounds », ce qui signifie « sons gratuits » en anglais, et boum… des centaines de millions de résultats !

Rien qu'avec les sites de la première page, vous devriez trouver votre bonheur.
Personnellement, j'ai retenuFindSounds.com, un moteur de recherche pour sons. Je ne sais pas si c'est le meilleur, mais en tout cas il est bien complet.

En recherchant « gun », on trouve des tonnes de sons de tir de fusil ; en tapant « door » on trouve des bruits de porte (figure suivante), etc.

FindSounds.com propose des sons de porte

Les étapes à suivre pour jouer un son

La première étape consiste à charger en mémoire le son que vous voulez jouer.
Il est conseillé de charger tous les sons qui seront fréquemment utilisés dans le jeu dès le début du programme. Vous les libérerez à la fin. En effet, une fois que le son est chargé en mémoire, sa lecture est très rapide.

Le pointeur

Première étape : créer un pointeur de typeFMOD_SOUNDqui représentera notre son.

FMOD_SOUND *tir = NULL;
Charger le son

Deuxième étape : charger le son avec la fonctionFMOD_System_CreateSound. Elle prend… 5 paramètres :

    • Un objet système dont on a parlé précédemment.

Bien sûr cet objet doit être prêt à l'emploi (déclaré, alloué et initialisé).

    • Le nom du fichier son à charger. Il peut être de format WAV, MP3, OGG, etc. Toutefois, il vaut mieux charger des sons courts (quelques secondes maximum) plutôt que des sons longs. En effet, la fonction chargera et décodera tout le son en mémoire, ce qui peut prendre de la place si le son est une musique !

    • Le troisième paramètre est un paramètreflag.

Il nous intéresse particulièrement ici, car c'est grâce à lui qu'on pourra dire à FMOD que le son qu'on veut jouer est un son court. Pour ceci, on utilisera la valeurFMOD_CREATESAMPLE.

    • Le quatrième paramètre ne nous intéresse pas, et on mettraNULLcomme valeur.

    • Le dernier paramètre est du typeFMOD_SOUND ** sound, et c'est ce pointeur-là qu'on utilisera par la suite pour jouer notre son.

En quelque sorte, on peut considérer que ce pointeur pointera à l'avenir vers notre son.

Voici un exemple de chargement :

FMOD_System_CreateSound(system, "pan.wav", FMOD_CREATESAMPLE, 0, &tir);

Ici, je charge le sonpan.wav. Le pointeurtirfera référence à ce son par la suite.

Si tout se passe bien, la fonction renvoie la valeurFMOD_OK. Sinon, c'est qu'il y a eu un problème lors de l'ouverture du fichier audio (fichier corrompu ou inexistant par exemple).

Jouer le son

Vous voulez jouer le son ? Pas de problème avec la fonctionFMOD_System_PlaySound!
Il suffit de lui donner un objet système prêt à l'emploi, un numéro de canal sur lequel jouer ainsi que le pointeur sur le son, et d'autres paramètres qui ne nous intéressent pas et qu'on mettra àNULLou à0. Pour le numéro de canal, ne vous prenez pas la tête et envoyezFMOD_CHANNEL_FREEpour laisser FMOD gérer ça.

FMOD_System_PlaySound(system, FMOD_CHANNEL_FREE, tir, 0, NULL);
Libérer le son de la mémoire

Lorsque vous n'avez plus besoin du son, vous devez le libérer de la mémoire.
Il n'y a rien de plus simple, il suffit d'indiquer le pointeur à libérer avec la fonctionFMOD_Sound_Release

FMOD_Sound_Release(tir);

Exemple : un jeu de tir

Le mieux maintenant est de résumer tout ce qu'on a vu dans un cas concret de programme écrit en SDL.
Il n'y avait rien de compliqué et, normalement, vous ne devriez avoir aucune difficulté à réaliser cet exercice.

Le sujet

Votre mission est simple : créer un jeu de tir.
Bon, on ne va pas réaliser un jeu complet ici, mais juste la gestion du viseur. Je vous ai justement fait un petit viseur sous Paint (figure suivante).

Le viseur

Bref, voilà les objectifs :

  • Fond de fenêtre : noir.

  • Pointeur de la souris : invisible.

  • L'image du viseur est blittée à la position de la souris lorsqu'on la déplace. Attention : il faut que le CENTRE de l'image soit placé au niveau du pointeur de la souris.

  • Quand on clique, le sonpan.wavdoit être joué.

Ça peut être le début d'un jeu de tir.
Trop facile ? Ok, alors à vous de jouer !

La correction

Voici le code complet :

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <fmodex/fmod.h>

int main(int argc, char *argv[])
{
    SDL_Surface *ecran = NULL, *viseur = NULL;
    SDL_Event event;
    SDL_Rect position;
    int continuer = 1;


    FMOD_SYSTEM *system;
    FMOD_SOUND *tir;
    
    FMOD_RESULT resultat;

    /* Création et initialisation d'un objet système */
    FMOD_System_Create(&system);
    FMOD_System_Init(system, 1, FMOD_INIT_NORMAL, NULL);

    /* Chargement du son et vérification du chargement */
    resultat = FMOD_System_CreateSound(system, "pan.wav", FMOD_CREATESAMPLE, 0, &tir);
    if (resultat != FMOD_OK)
    {
        fprintf(stderr, "Impossible de lire pan.wav\n");
        exit(EXIT_FAILURE);
    }

    /* Initialisation de la SDL */
    SDL_Init(SDL_INIT_VIDEO);

    SDL_ShowCursor(SDL_DISABLE);
    ecran = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    SDL_WM_SetCaption("Gestion du son avec FMOD", NULL);

    viseur = IMG_Load("viseur.png");

    while (continuer)
    {
        SDL_WaitEvent(&event);

        switch(event.type)
        {
        case SDL_QUIT:
            continuer = 0;
            break;
        case SDL_MOUSEBUTTONDOWN:
            /* Lorqu'on clique, on joue le son */
            FMOD_System_PlaySound(system, FMOD_CHANNEL_FREE, tir, 0, NULL);
            break;
        case SDL_MOUSEMOTION:
            /* Lorsqu'on déplace la souris, on place le centre du viseur à la position de la souris
               ... D'où notamment le "viseur->w / 2" pour réussir à faire cela */
            position.x = event.motion.x - (viseur->w / 2);
            position.y = event.motion.y - (viseur->h / 2);
            break;
        }

        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));
        SDL_BlitSurface(viseur, NULL, ecran, &position);
        SDL_Flip(ecran);
    }

    /* On ferme la SDL */
    SDL_FreeSurface(viseur);
    SDL_Quit();

    /* On libère le son et on ferme et libère l'objet système */
    FMOD_Sound_Release(tir);
    FMOD_System_Close(system);
    FMOD_System_Release(system);

    return EXIT_SUCCESS;
}

La figure suivante vous donne un aperçu du mini-jeu, mais le mieux est encore de voir le résultat en vidéo avec le son sur le web !

Aperçu du mini-jeu du viseur

Voir la vidéo de la gestion du son avec FMOD : le viseur (111 Ko)

Ici, j'ai chargé FMOD avant la SDL et je l'ai libéré après la SDL. Il n'y a pas de règles au niveau de l'ordre (j'aurais tout aussi bien pu faire l'inverse). J'ai choisi de charger la SDL et d'ouvrir la fenêtre après le chargement de FMOD pour que le jeu soit prêt à être utilisé dès que la fenêtre s'ouvre (sinon il aurait peut-être fallu attendre quelques millisecondes le temps que FMOD se charge).
Ceci étant, libre à vous de choisir l'ordre que vous voulez ; c'est un détail.

Le code est, je pense, suffisamment commenté. Il n'y a pas de piège particulier, pas de nouveauté fracassante.

On notera la « petite » difficulté qui consistait à blitter le centre du viseur au niveau du pointeur de la souris. Le calcul de la position de l'image est fait en fonction.

Pour ceux qui n'auraient pas encore compris la différence, voici de quoi il retourne. Pour l'occasion, j'ai réactivé l'affichage du pointeur de la souris pour qu'on voie comment est placé le viseur par rapport au pointeur.

Code incorrect
(viseur mal placé)

Image utilisateurImage utilisateurImage utilisateurImage utilisateur
position.x = event.motion.x;
position.y = event.motion.y;

Code correct
(viseur bien placé)

Image utilisateurImage utilisateurImage utilisateurImage utilisateur
position.x = event.motion.x - (viseur->w / 2);
position.y = event.motion.y - (viseur->h / 2);
Idées d'amélioration

Ce code est la base d'un jeu de shoot. Vous avez le viseur, le bruit de tir, il ne vous reste plus qu'à faire apparaître ou défiler des ennemis et à marquer le score du joueur. Comme d'habitude, c'est à vous de jouer. Vous vouliez faire un jeu ? Qu'à cela ne tienne, vous avez le niveau maintenant, et même un code de base pour démarrer un jeu de tir ! Qu'est-ce que vous attendez, franchement ?

Les musiques (MP3, OGG, WMA…)

En théorie, le flagFMOD_CREATESAMPLEpermet de charger n'importe quel type de son, y compris les formats compressés MP3, OGG, WMA. Le problème concerne les sons « longs », c'est-à-dire les musiques.

En effet, une musique dure en moyenne 3 à 4 minutes. Or, avec ce flag, la fonctionFMOD_System_CreateSoundcharge tout le fichier en mémoire (et c'est la version décompressée qui est mise en mémoire, donc ça prend beaucoup de place !).

Si vous avez un son long (on va parler de « musique » dorénavant), il est préférable de le charger en streaming, c'est-à-dire d'en charger de petits bouts au fur et à mesure de la lecture ; c'est d'ailleurs ce que font tous les lecteurs audio.

Trouver des musiques

Là, on rentre en terrain miné, épineux, explosif (comme vous préférez).
En effet, la plupart des musiques et chansons que l'on connaît sont soumises au droit d'auteur. Même si vous ne faites qu'un petit programme, il faut verser une redevance à la SACEM (en France du moins).

Donc, mis à part les MP3 soumis à droit d'auteur, que nous reste-t-il ?
Heureusement, il y a des chansons libres de droit ! Les auteurs vous autorisent à diffuser librement leurs chansons, il n'y a donc aucun problème pour que vous les utilisiez dans vos programmes.

Bon, la question maintenant est : « où trouver des musiques libres de droit ? ». On pourrait faire une recherche de « Free Music » sur Google, mais là pour le coup il n'est pas notre ami. En effet, allez savoir pourquoi, on a beau taper le mot « Free », on tombe quand même sur des sites qui nous proposent d'acheter des musiques !

Il existe heureusement des sites qui sont dédiés à la musique libre de droit. Là, je vous recommande Jamendo qui est un très bon site, mais ce n'est pas le seul qui existe dans le domaine.

Les chansons sont classées par style. Vous avez beaucoup de choix. On y trouve du bon, du moins bon, du très très bon, du très très nul… En fait, tout dépend de vos goûts et de votre réceptivité aux différents styles de musique. De préférence, prenez une chanson qui peut servir de musique de fond et qui correspond bien à l'univers de votre jeu.

Pour information, cette chanson provient de l'album « Lies and Speeches » du groupe français « Hype ». Pour en savoir plus sur « Hype », vous pouvez visiter leur page MySpace.

J'ai donc téléchargé l'album et je vais utiliser la chanson « Home » au format MP3.
Vous pouvez la télécharger directement si vous voulez faire des tests en même temps que moi. C'est un des avantages de la musique libre : on peut la copier / distribuer librement, donc ne nous gênons pas.

Les étapes à suivre pour jouer une musique

La seule différence est le flag donné à la fonctionFMOD_System_CreateSound.
Au lieu de lui donner le flagFMOD_CREATESAMPLE, on lui donnera les flags suivants :FMOD_SOFTWARE,FMOD_2DetFMOD_CREATESTREAM.
Ne vous attardez pas trop sur la signification de ces flags ; celui qui nous intéresse le plus estFMOD_CREATESTREAM, car c'est lui qui dira à FMOD de charger la musique bout par bout.

Pour utiliser tous ces flags en même temps, on utilisera l'opérateur logique|de cette façon :

FMOD_System_CreateSound(system, "ma_musique.mp3", FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM, 0, &sound);

Et voilà le travail !
Mais ce n'est pas tout. Dans le cas d'une musique, il peut être bien de savoir modifier le volume, gérer les répétitions de la chanson, la mettre en pause ou même l'arrêter. C'est ce genre de choses que nous allons voir maintenant.
Mais avant ça, nous aurons besoin de travailler sur les canaux directement.

Récupérer un canal ou un groupe de canaux

Dans des versions précédentes de la librairie FMOD, le simple numéro d'identification d'un canal suffisait pour pouvoir modifier le volume ou bien mettre en pause une chanson.
Depuis FMOD Ex, il y a eu un petit changement : à partir du numéro de canal, on utilise une fonction qui fournit un pointeur vers ce canal. L'idée est restée la même, seule l'implémentation a changé.
Un canal est défini comme étant du typeFMOD_CHANNEL, et la fonction qui permet de récupérer un canal à partir d'un numéro id estFMOD_System_GetChannel.
Par exemple, si j'ai un objet systèmesystemet que je veux récupérer le canal n°9, il faut faire :

FMOD_CHANNEL *channel;
FMOD_System_GetChannel(system, 9, &channel);

Rien de plus simple !

  • Le premier paramètre est l'objet système.

  • Le deuxième est le numéro id du canal.

  • Le troisième est l'adresse du pointeur où l'on veut stocker l'information voulue.

Une fois qu'on aura notre pointeur de canal, on pourra facilement manipuler la musique (modifier le volume, mettre en pause…).

Notez qu'on peut aussi récupérer tout un groupe de canaux en un seul pointeur ; ça évite de refaire la même manipulation pour chaque canal distinct.
Le type d'un groupe de canaux estFMOD_CHANNELGROUP, et une des fonctions qui nous intéresse le plus estFMOD_System_GetMasterChannelGroup, car elle permet d'obtenir un pointeur vers la totalité des canaux utilisés par un objet système.
Le mode de fonctionnement de cette fonction est identique à la précédente.

Modifier le volume

Pour modifier le volume, on peut le faire soit pour un canal précis, soit pour tous les canaux.
Par exemple, pour le faire pour tous les canaux, il faut d'abord récupérer un pointeur vers le groupe de canaux, puis utiliser la fonctionFMOD_ChannelGroup_SetVolumedont le prototype est :

FMOD_RESULT FMOD_ChannelGroup_SetVolume(
  FMOD_CHANNELGROUP *  channelgroup,
  float  volume
);

Le paramètrechannelgroupest celui qu'on vient de récupérer.
Le paramètrevolumeest du typefloat, tel que 0.0 correspond au silence, et 1.0 correspond à une lecture pleine puissance (c'est cette valeur qui est par défaut).

Répétition de la chanson

On a souvent besoin de répéter la musique de fond. C'est justement ce que propose la fonctionFMOD_Sound_SetLoopCount. Elle prend 2 paramètres :

  • Le pointeur vers la chanson.

  • Le nombre de fois qu'elle doit être répétée. Si vous mettez 1, la chanson sera donc lue deux fois. Si vous mettez un nombre négatif (comme -1), la chanson sera répétée à l'infini.

Avec ce code source, notre musique sera donc répétée à l'infini :

FMOD_Sound_SetLoopCount(musique, -1);
Mettre en pause la chanson

Il y a ici 2 fonctions à connaître :

  • FMOD_Channel_GetPaused(canal, &etat): indique si la chanson jouée sur le canal indiqué est en pause ou pas. Elle met vrai dansetatsi la chanson est en pause, faux si elle est en train d'être jouée.

  • FMOD_Channel_SetPaused(canal, etat): met en pause ou réactive la lecture de la chanson sur le canal indiqué. Envoyez 1 (vrai) pour mettre en pause, 0 (faux) pour réactiver la lecture.

Ce bout de code de fenêtre SDL met en pause la chanson si on appuie sur la touchePdu clavier, et la réactive si on appuie à nouveau surP.

case SDL_KEYDOWN:
    if (event.key.keysym.sym == SDLK_p) // Si on appuie sur P
    {
        FMOD_BOOL etat;
        FMOD_Channel_GetPaused(canal, &etat);

        if (etat == 1) // Si la chanson est en pause
            FMOD_Channel_SetPaused(canal, 0); // On enlève la pause
        else // Sinon, elle est en cours de lecture
            FMOD_Channel_SetPaused(canal, 1); // On met en pause
    }
    break;

Si on veut appliquer le même traitement à tous les canaux réunis, on utilisera les fonctionsFMOD_ChannelGroup_GetPausedetFMOD_ChannelGroup_SetPaused, à la seule différence qu'il faut faire passer comme paramètre unFMOD_CHANNELGROUPau lieu d'unFMOD_CHANNEL.

Stopper la lecture

Il suffit d'appelerFMOD_Channel_Stoppour stopper une musique sur un canal, ou bienFMOD_ChannelGroup_Stoppour un ensemble de canaux. On leur envoie respectivement le pointeur vers le canal ou bien le pointeur vers le groupe de canaux.

Et bien d'autres choses

On peut faire beaucoup d'autres choses, mais je ne vais pas vous les énumérer toutes ici, autant lire la doc ! Je vous invite donc à y jeter un œil si vous cherchez des fonctions supplémentaires.

Libérer la mémoire

Pour décharger la musique de la mémoire, appelezFMOD_Sound_Releaseet donnez-lui le pointeur.

FMOD_Sound_Release(musique);

Code complet de lecture du MP3

Le code ci-dessous vous montre un programme jouant la musique « Home » qu'on a récupérée sur Jamendo.
La musique est jouée dès le début du programme. On peut la mettre en pause en appuyant surP.

#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <fmodex/fmod.h>

int main(int argc, char *argv[])
{
    SDL_Surface *ecran = NULL, *pochette = NULL;
    SDL_Event event;
    SDL_Rect position;
    int continuer = 1;

    FMOD_SYSTEM *system;
    FMOD_SOUND *musique;
    FMOD_RESULT resultat;

    
    FMOD_System_Create(&system);
    FMOD_System_Init(system, 1, FMOD_INIT_NORMAL, NULL);

    /* On ouvre la musique */
    resultat = FMOD_System_CreateSound(system, "hype_home.mp3", FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM, 0, &musique);

    /* On vérifie si elle a bien été ouverte (IMPORTANT) */
    if (resultat != FMOD_OK)
    {
        fprintf(stderr, "Impossible de lire le fichier mp3\n");
        exit(EXIT_FAILURE);
    }

    /* On active la répétition de la musique à l'infini */
    FMOD_Sound_SetLoopCount(musique, -1);

    /* On joue la musique */
    FMOD_System_PlaySound(system, FMOD_CHANNEL_FREE, musique, 0, NULL);

    SDL_Init(SDL_INIT_VIDEO);

    ecran = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    SDL_WM_SetCaption("Gestion du son avec FMOD", NULL);
    pochette = IMG_Load("hype_liesandspeeches.jpg");
    position.x = 0;
    position.y = 0;

    while (continuer)
    {
        SDL_WaitEvent(&event);
        switch(event.type)
        {
        case SDL_QUIT:
            continuer = 0;
            break;
        case SDL_KEYDOWN:
            if (event.key.keysym.sym == SDLK_p) //Si on appuie sur P
            {
                FMOD_CHANNELGROUP *canal;
                FMOD_BOOL etat;
                FMOD_System_GetMasterChannelGroup(system, &canal);
                FMOD_ChannelGroup_GetPaused(canal, &etat);
            
                if (etat) // Si la chanson est en pause
                    FMOD_ChannelGroup_SetPaused(canal, 0); // On enlève la pause
                else // Sinon, elle est en cours de lecture
                    FMOD_ChannelGroup_SetPaused(canal, 1); // On active la pause
            }
            break;
        }

        SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0));
        SDL_BlitSurface(pochette, NULL, ecran, &position);
        SDL_Flip(ecran);
    }

    FMOD_Sound_Release(musique);
    FMOD_System_Close(system);
    FMOD_System_Release(system);

    SDL_FreeSurface(pochette);
    SDL_Quit();

    return EXIT_SUCCESS;
}

Histoire d'avoir autre chose qu'une fenêtre noire, j'ai mis la pochette de l'album en image de fond.

Pour apprécier pleinement le résultat, je vous invite à regarder la vidéo du programme en cours d'exécution.

Voir la vidéo d'une musique jouée avec FMOD (730 Ko)

En résumé

  • La SDL possède des fonctionnalités audio limitées et il est plutôt conseillé de se pencher sur une bibliothèque dédiée au son, comme FMOD.

  • On distingue 2 types de sons avec FMOD : des sons courts (un bruit de pas par exemple) et des sons longs (une musique par exemple).

  • Chacun de ces types se lit avec la même fonction mais avec des flags différents en option.

  • FMOD permet de jouer simultanément plusieurs sons différents à l'aide de plusieurs canaux.

Exemple de certificat de réussite
Exemple de certificat de réussite