LA GESTION DE L'AUDIO EN SDL2
Introduction
Salutation ! après de longs jours/mois d'absence je vous annonce ce nouveau
chapitre, ou nous allons pouvoir jouer des sons/musiques dans nos programmes SDL.
Souvenez-vous de la fonction SDL_Init() , vous savez maintenant qu'elle prend un
paramètre de type Uint32 qui est un flag qui va nous permettre d'utiliser telle ou
telle fonction de la bibliothèque SDL.
Et pour pouvoir utiliser le module AUDIO de la SDL, il faudra dans ce cas utiliser le
flag SDL_INIT_AUDIO !
Dans ce chapitre, nous verrons donc :
La théorie (Signal périodique, Fréquence, Période, Fourier)
La mise en pratique en SDL
la bibliothèque SDL_Mixer
La théorie
Reprenons de zéro
Cette partie théorie, peut-être un peu compliquée à comprendre mais sachez juste
qu'elle n'est en aucun nécessaire pour pouvoir jouer des sons avec SDL_Mixer ,
cependant si vous souhaitez jouer/créer des sons en SDL, il faut au préalable
comprendre la partie théorique.
Appartient à [Link] - lien original ici
Maintenant votre question légitime est "Comment jouer un son ou une musique ?". Déjà,
avant de commencer à coder je vous invite à utiliser le logiciel libre Audacity et de
produire un son avec votre microphone ! Si vous ne pouviez pas vous enregistrer,
alors téléchargez le fichier [Link] et ouvrez le avec le logiciel audacity. Une
fois ouvert vous tombez sur le résultat suivant :
Ceci peut vous faire peur, ça ressemble un peu à rien, mais essayons de comprendre
cela. Nous avons déjà en notre présence un dessin bleu et nous ne savons pas trop à
quoi cela peut correspondre.
Appartient à [Link] - lien original ici
Alors regardez bien, la première chose qu'on peut dire c'est que nous avons un son
qui se joue lorsqu'on appuie sur le bouton "play" d'audacity. On peut remarquer que
notre son dure un certain temps (ici 4 secondes). Puis nous percevons aussi des
indicateurs allant de -1 à 1.
Dorénavant, je vais apporter une approche plus scientifique :
Sur l'axe des ordonnées nous avons le temps.
Sur l'axe des abscisses nous avons l'amplitude.
Enfin, la courbe représente un signal.
Mon professeur de mathématiques aime différencier une fonction d'un signal. En
effet, un signal est censé représenter quelque chose de physique.
Définition
(Adjectif) Du latin physicus (« physique, naturel, des sciences naturelles ») tiré du
grec ancien ???????, phusikós (« physique, naturel »). (Nom 1) Du latin physica («
physique, science de la nature »), du grec ancien ??????, phusik? (« science de la
nature ») dérivé de ?????, phúsis (« nature »)
Wikipedia
Nous avons ici le mot physique qui désigne science de la nature, ce qui est le cas de
mon sifflement car c'est un son sorti de ma bouche et je vous rassure il est bien
naturel ��.
Tandis que la fonction
Appartient à [Link] - lien original ici
décrit à ma connaissance aucun phénomène physique dans la nature. Si vous
effectuez un zoom à partir de 0.5 secondes, vous apercevrez quelque chose de
stupéfiant ! Soit :
Information
Par chance j'ai sifflet dans mon micro et j'ai constaté que ça a formé une
sinusoïde (sans doute Fourier qui se cache derrière, nous allons parler de lui plus
tard)
Appartient à [Link] - lien original ici
Vous avez une courbe qui est une sinusoïde qui semble être périodique de période
T et de fréquence F.
Qu'est-ce la fréquence et la période ? La fréquence est le nombre de répétitions du
motif élémentaire en une seconde. La période c'est le temps que met votre motif
élémentaire à être répété. Je vous donne
. Voici donc une courbe qui reprend notre signal à la forme sinusoïde afin de mieux
le décrire : Vous aurez alors la courbe suivante :
En vert foncé c'est votre motif élémentaire. Vous constater qu'il est périodique car il (le
motif élémentaire) se répète tous les 2π, donc une fois que nous avons lapériode,
nous pouvons alors calculer la fréquence de ce signal qui est donc de
Appartient à [Link] - lien original ici
.
L'amplitude est donc de sin(π/2), ici ça vous donnera approximativement 1 (dédicace
à mon professeur de physique de BTS SNIR) 1 �� comme sur le schéma que je vous ai
fourni.
Bon la question légitime est "pourquoi je vous parle de tout ça ?" C'est juste pour votre
culture générale ! Car quand vous allez utiliser SDL_Mixer la plupart du temps vous
utiliserez un fichier son déjà fait par un musicien qui s'est enregistré. Cependant si
vous souhaitez par exemple réaliser vos propres sons comme un synthétiseur vocal,
il vous saura indispensable de reconnaître les notions que nous aborderons dans un
instant.
De plus la gestion de l'audio en SDL est assez difficile à gérer. C'est pour cela qu'on
utilisera plus tard SDL_Mixer . Cependant, je souhaite tout de même vous montrer
au début comment gérer l'audio sans la bibliothèque SDL_Mixer, afin de
comprendre en profondeur la gestion du son, et de me différencier aussi des autres
tutos disponibles dans le web.
Appartient à [Link] - lien original ici
Maintenant vous savez à quoi ressemble un son en réalité. Pour information vous
pouvez même produire votre propre son en programmation, nous coderons cette
partie en SDL plus loin dans cet article.
Déjà, physiquement un son n'est rien d'autre qu'une onde caractérisée par son
signal propre, qui est en fait une vibration de l'air.
Information
Les sons ne sont pas tous sinusoïdale (heureusement).
La série de fourier
La série de Fourier est une somme de sinusoïdes de fréquences et d’amplitudes,
sous la formule suivante :
Appartient à [Link] - lien original ici
Le polynôme de Fourier permet de faire des approximations de courbe périodique
mais nous utiliserons aussi pour mettre des fréquences et des amplitudes
différentes. Plus simplement l'approximation va nous servir à avoir un signal proche
du signal original qu'on souhaite reproduire et dans le cas d'utilisation de
fréquences différentes cela nous permettra de produire des sons différents, on
utilisera aussi des amplitudes différentes pour avoir un volume différent.
Appartient à [Link] - lien original ici
Plus la valeur de est grande plus l'approximation est proche du correcte. Nous
remarquons aussi le signe ? cela signifie la pulsation du signal
Appartient à [Link] - lien original ici
Fonction paire et fonction impaire
Je tiens à parler un peu des fonctions paires et impaires pour votre culture générale.
Vous avez sûrement connu, cette façon de vérifier un nombre pair ou impair :
int a = 32;
bool estImpair = ((a % 2) == 0);
Oubliez là, car ici on parle de fonction paire et impaire, une fonction est dite paire si
Par exemple, pour x = 4, dans le cas d'une fonction paire, on obtiendra le même
résultat que ça soit pour f(4) ou f(-4). On dit qu'ils ont a les mêmes images.
Information
L'image d'une fonction est le résultat produit par cette fonction.
Une fonction est dite impaire si
Toujours dans l'exemple x = 4 mais dans le cas d'une fonction impaire, nous
obtiendrons f(-4)=-7 et f(4)=7. On dira alors qu'ils possèdent des images opposées.
Appartient à [Link] - lien original ici
Conclusion
La parité, d'une fonction permet de simplifier les calculs de la série de Fourier.
Dans une fonction qui n'est pas paire ni impaire, vous serez alors obligé de
calculer an et bn dans la série de fourier.
Une fonction qui est paire (symétrique par rapport à l'axe des ordonnées), vous
aurez alors tous vos bn (b1, b2, ..., bn) à nul !
Une fonction qui est impaire (symétrique par rapport a l'origine), vous aurez
alors tous vos an (a1, a2, ..., an) à nul !
Si vous prenez sin(x) sachant qu'on sait que cette fonction est impaire donc
symétrique par rapport à l'origine ! (Rappel de la propriété : -sin(4) = sin(-4)). vous
aurez donc vos an tous à 0 donc il n'y aura pas besoin de calculer an !
La mise en pratique en SDL
Pour cette section, nous allons charger que le module audio de la SDL.
SDL_Init(SDL_INIT_AUDIO);
Ensuite, nous devons créer une structure SDL_AudioSpec , voici les différents
champs de notre structure :
Appartient à [Link] - lien original ici
freq : correspond la fréquence d'échantillonnage du signal, en effet plus le
signal est grand plus, plus la qualité du son est précise.
format : C'est le format de notre son en type int ou float qui représente le
nombre de bits pour une donnée de notre son et le le endianness c'est-à-dire
l'ordre dans lequel ces octets sont organisés en mémoire. Nous verrons les
flags possibles.
channels : Nombre de canaux audio où l'on envoie le son. 1 (mono), 2 (stéréo), 4
(quad) et 6 (5.1).
samples : la taille du buffer qui stockera les valeurs du son. Cette valeur doit
être une puissance de 2.
callback : on précisera ici la fonction afin de jouer les données de notre audio,
depuis cette fonction. Le callback doit avoir cette forme void
SDL_AudioCallback(void* user data, Uint8* stream, int Len) .
Appartient à [Link] - lien original ici
endianness (big-endian vs little-endian)
Ce sont les seuls champs qui nous intéressent, on peut ignorer le reste. Le champ
silence et size sont automatiquement calculés et userdata peut-être à nullptr ,
ou this si vous l'utilisez dans une class par exemple.
Pour le champ format voici les valeurs possibles :
Appartient à [Link] - lien original ici
En gros vous avez un buffer qui peut être soit sur : 8 bits, 16 bits des 32 bits. Dans le
cas des 16 bits et des 32 bit, vous avez le choix de choisir le type entier ou flottant.
Vous avez aussi LSB (little-endian) et MSB (big-endian) qui correspond à
endianness. Nous allons choisir le format de buffer en utilisant le flag
AUDIO_F32SYS et le flag AUDIO_F32SYS afin que notre endianness soit
Appartient à [Link] - lien original ici
automatiquement choisi par notre machine.
Remplir la structure
SDL_AudioSpec spec;
SDL_memset(&spec, 0, sizeof(spec));
[Link] = 96000; // 4 100 Hz, 48 000 Hz, 96 000 Hz, 192 000 Hz (standard)
[Link] = AUDIO_F32SYS;
[Link] = 1; // mono
[Link] = 4096; // Oublier pas que ce sa doit être en puissance de deux 2^n
[Link] = [](void* param, Uint8* stream, int len)
{
// Envoyez les données dans notre buffer...
};
Ensuite nous devons sélectionner la carte son que nous allons utiliser, pour cela on
utilisera la fonction suivante :
SDL_AudioDeviceID SDL_OpenAudioDevice(const char* device,
int iscapture,
const SDL_AudioSpec* desired,
SDL_AudioSpec* obtained,
int allowed_changes)
Le premier paramètre est le nom de la carte son.
Le deuxième paramètre autorise ou non l'enregistrement d'un son.
Le troisième définit les caractéristiques du son désiré.
Le quatrième définit la caractéristique du son final. La différence avec le
champ desired est que, lorsque nous désirons une configuration audio que
votre carte son ne peut pas gérer (comme l'échantillonnage ou la fréquence),
SDL va automatiquement vous renvoyer la configuration possible dans le
champ obtained .
Appartient à [Link] - lien original ici
Le cinquième paramètre définit la fonctionnalité qu'on souhaite effectuer sur
la carte son pour modifier par exemple une voix et la rendre de plus en plus
grave. Voici les valeurs possibles :
Voici un exemple d'utilisation :
SDL_AudioDeviceID dev = SDL_OpenAudioDevice(nullptr, 0, &spec, &spec, SDL_AUDIO_ALLOW_FREQUENC
Mettre nullptr au premier paramètre va choisir tout seul le périphérique. Ensuite
effectuer une boucle infinie :
Ensuite nous devons mettre en lecture notre périphérique audio. En utilisant :
void SDL_PauseAudioDevice(SDL_AudioDeviceID dev,
int pause_on)
Le premier paramètre donné est l'identifiant de notre périphérique.
Le deuxième peut prendre deux valeurs soit : SDL_FALSE (ou 0) pour ne pas
mettre en pause SDL_TRUE (ou 1) pour mettre en pause.
Vous aurez ainsi le code suivant :
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_AUDIO) < 0)
Appartient à [Link] - lien original ici
return -1;
SDL_AudioSpec spec;
SDL_memset(&spec, 0, sizeof(spec));
[Link] = 96000; // 4 100 Hz, 48 000 Hz, 96 000 Hz, 192 000 Hz (standard)
[Link] = AUDIO_F32SYS;
[Link] = 1;
[Link] = 4096; // Oublier pas que ce sa doit être en puissance de deux 2^n
[Link] = [](void* param, Uint8* stream, int len)
{
// Envoyez les données dans notre buffer...
};
SDL_AudioDeviceID dev = SDL_OpenAudioDevice(nullptr, 0, &spec, &spec, SDL_AUDIO_ALLOW_FREQ
SDL_PauseAudioDevice(dev, SDL_FALSE);
for (;;); // boucle infinie
SDL_Quit();
return 0;
}
Ensuite si vous lancez votre programme, il n'y aura rien qui se passe car on n'a pas
encore envoyé de données à notre buffer stream ! Pour ce faire, voici ce que vous
devez rentrer dans votre callback :
[Link] = [](void* param, Uint8* stream, int len)
{
// Envoyez les données dans notre buffer...
int samples = len / sizeof(float); // 4096
for (auto i = 0; i < samples; i++)
{
reinterpret_cast<float*>(stream)[i] = 0.5 * SDL_sinf(2 * M_PI * i / 1000);
}
};
Si vous exécutez maintenant votre programme vous entendrez un son. Vous pouvez
utiliser soit la fréquence soit la période, soit :
Asin(2 * pi * x/T) => utilise la période
Appartient à [Link] - lien original ici
Asin(2 * pi * f*x) => utilise la fréquence
Vous pouvez vous amuser à faire des do-ré-mi-fa-so-la-si-do en utilisant leur
fréquence si vous êtes doué en musique et donc composez votre propre musique.
SDL_Mixer
Bon, on a vu une partie de la théorie d'un son via par exemple la série de Fourier,
nous avons vu aussi comment produire un son sous SDL. Maintenant, ce qu'on
aimerait faire c'est déjà jouer des fichiers .wav, .mp3, etc ...
Mais avant de coder avec SDL_Mixer il faut que vous installiez, SDL_Mixer via à ce
lien [Link] comme nous l'avions fait pour le
module SDL_TTF ! Il faut que vous soyez autonome ��, juste pensez à modifier votre
configuration du projet sous visual studio, ou votre ligne de commande lors de la
compilation sous g++.
Donc, pour pouvoir utiliser SDL_Mixer il faut d'abord l'initialiser tout comme SDL
voici le prototype de la fonction a appelé :
extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, int chun
On connait déjà quelque paramètre
Le premier paramètre est la fréquence d'échantillonnage (qualité du son)
Le deuxième paramètre est le format de données (comme pour le champ
format de la structure SDL_AudioSpec )
Le troisième représente les canaux mono, stéréo, 5.1
Le quatrième est mon taux d'échantillons soit la taille du buffer.
Appartient à [Link] - lien original ici
Voici comment l'initialiser :
if (Mix_OpenAudio(96000, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) < 0)
{
SDL_Log("Erreur initialisation SDL_mixer : %s", Mix_GetError());
SDL_Quit();
return -1;
}
Ensuite pensez à libérer la mémoire, en utilisant la fonction Mix CloseAudio() .
extern DECLSPEC void SDLCALL Mix_CloseAudio(void);
Ce qui nous donne le code suivant :
#include <SDL.h>
#include <SDL_mixer.h>
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) // Pas besoin de SDL_INIT_AUDIO
return -1;
if (Mix_OpenAudio(96000, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) < 0) // création
{
SDL_Log("Erreur initialisation SDL_mixer : %s", Mix_GetError());
SDL_Quit();
return -1;
}
Mix_CloseAudio();
SDL_Quit();
return 0;
}
Ensuite nous devons créer un pointeur sur une structure Mix_Music afin de
récupérer le buffer audio de notre fichier son. cela ce fait en appelant la fonction
Mix_LoadMUS qui a pour signature :
extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file);
Appartient à [Link] - lien original ici
Elle retourne notre pointeur sur une structure Mix_Music
Elle prend pour unique paramètre le chemin de votre fichier son
Mix_Music* music = Mix_LoadMUS("ouman.mp3");
if (music == nullptr)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur chargement de la musique : %s", Mix_Get
Mix_CloseAudio();
SDL_Quit();
return -1;
}
Ensuite nous pouvons jouer notre musique en utilisant la fonction Mix_PlayMusic
voici sa signature :
extern DECLSPEC int SDLCALL Mix_PlayMusic(Mix_Music *music, int loops);
Le premier paramètre est le pointeur sur la Mix_Music .
Le dernier paramètre est pour savoir combien de fois nous devons jouer la
musique (-1 jouer en boucle).
Retourne -1 s'il y a une erreur et 0 s'il n'y en a pas.
Voici le code résultant :
#include <SDL.h>
#include <SDL_mixer.h>
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return -1;
// Initialisation de SDL_Mixer
if (Mix_OpenAudio(96000, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) < 0)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur initialisation SDL_mixer : %s", Mix
SDL_Quit();
return -1;
}
Appartient à [Link] - lien original ici
Mix_Music* music = Mix_LoadMUS("ouman.mp3"); // Charge notre musique
if (music == nullptr)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur chargement de la musique : %s", Mix
Mix_CloseAudio();
SDL_Quit();
return -1;
}
Mix_PlayMusic(music, -1); // Joue notre musique
SDL_Window* pWindow = nullptr;
SDL_Renderer* pRenderer = nullptr;
SDL_Event events;
bool close = false;
SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_SHOWN, &pWindow, &pRenderer);
while (!close)
{
while (SDL_PollEvent(&events))
{
if ([Link] == SDL_WINDOWEVENT && [Link] == SDL_WINDOWEVENT_CLOSE
close = true;
}
SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 255);
SDL_RenderClear(pRenderer);
SDL_RenderPresent(pRenderer);
}
SDL_DestroyRenderer(pRenderer);
SDL_DestroyWindow(pWindow);
Mix_FreeMusic(music); // Libére en mémoire notre musique
Mix_CloseAudio(); // Quitter correctement SDL_Mixer
SDL_Quit();
return 0;
}
Bon maintenant, nous allons voir quelque fonction utilitaire pour changer le
volume, reprendre la musique depuis le début etc...
Mettre en pause la musique avec Mix_PauseMusic() :
extern DECLSPEC void SDLCALL Mix_PauseMusic(void);
Appartient à [Link] - lien original ici
Reprendre la lecture après la pause de la musique Mix_ResumeMusic() :
extern DECLSPEC void SDLCALL Mix_ResumeMusic(void);
Revenir au début de la musique Mix_RewindMusic()
extern DECLSPEC void SDLCALL Mix_RewindMusic(void);
Changer le volume de la musique Mix_VolumeMusic()
extern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume);
Stopper la lecture de la musique Mix_HaltMusic() :
extern DECLSPEC int SDLCALL Mix_HaltMusic(void);
Voici un programme qui résume toutes les fonctions utilitaires vues précédemment
#include <SDL.h>
#include <SDL_mixer.h>
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return -1;
if (Mix_OpenAudio(96000, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) < 0)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur initialisation SDL_mixer : %s", Mix
SDL_Quit();
return -1;
}
Mix_Music* music = Mix_LoadMUS("ouman.mp3");
if (music == nullptr)
{
Appartient à [Link] - lien original ici
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur chargement de la musique : %s", Mix
Mix_CloseAudio();
SDL_Quit();
return -1;
}
Mix_PlayMusic(music, -1);
SDL_Window* pWindow = nullptr;
SDL_Renderer* pRenderer = nullptr;
SDL_Event events;
bool close = false;
if (SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_SHOWN, &pWindow, &pRenderer) < 0)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur creation fenetre et rendue SDL : %s
Mix_FreeMusic(music);
Mix_CloseAudio();
SDL_Quit();
return -1;
}
Uint8 volume = 0;
Mix_VolumeMusic(volume); // Mets le volume a 0
while (!close)
{
while (SDL_PollEvent(&events))
{
if ([Link] == SDL_WINDOWEVENT && [Link] == SDL_WINDOWEVENT_CLOSE
close = true;
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_p)
Mix_PauseMusic(); // Mets en pause la musique
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_r)
Mix_ResumeMusic(); // Reprend la lecture
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_s)
Mix_RewindMusic(); // Revient au début de la musique
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_UP && volume < MIX
volume++; // Augmente le volume jusqu'a MIX_MAX_VOLUME
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_DOWN && volume > 0
volume--; // Réduit le volume jusqu'a 0
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_ESCAPE)
Mix_HaltMusic(); // Arreter la musique
if ([Link] == SDL_KEYDOWN)
Mix_VolumeMusic(volume); // Applique le volume desirer
SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 255);
SDL_RenderClear(pRenderer);
SDL_RenderPresent(pRenderer);
}
Appartient à [Link] - lien original ici
SDL_DestroyRenderer(pRenderer);
SDL_DestroyWindow(pWindow);
Mix_FreeMusic(music);
Mix_CloseAudio();
SDL_Quit();
return 0;
}
Maintenant nous allons voir comment jouer plusieurs sons sous différents canaux
(buffer dédié pour le son). Nous allons voir que c'est encore très simple sous
SDL_Mixer .
Pour commencer, il faut définir préalablement combien de canaux seront utilisés à
l'aide de la fonction Mix AllocateChannels() , voici donc sa signature :
extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans);
Le premier paramètre c'est le nombre de canaux.
Elle retourne -1 si erreur et 0 si ça se passe bien.
Information
Le nombre de canaux alloués, c'est en fait le nombre de sons que nous pouvons
jouer simultanément, comme par exemple la respiration de votre joueur et le son
au contact du sol, donc il faudra deux canaux dans cet exemple.
Maintenant nous allons configurer le volume pour nos deux canaux ! Nous allons
mettre le premier canal à 100% et 50% pour le second canal, pour ce faire il faut
utiliser la fonction Mix_Volume() , voici sa signature
extern DECLSPEC int SDLCALL Mix_Volume(int channel, int volume);
Appartient à [Link] - lien original ici
Le premier paramètre est le canal.
Le second paramètre est le volume souhaité en pourcentage.
Elle retourne -1 en cas d'erreur 0 en cas de succès.
Pour jouer vos sons simultanément, il suffit de créer un pointeur sur une structure
Mix_Chunk pour celà nous appellerons Mix_LoadWAV() qui a pour signature :
#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1)
Nous avons à faire avec une Macro qui n'est rien d'autre qu'une utilisation de
SDL_RWFromFile() nous devons juste passez le chemin du fichier son. Ensuite
nous pouvons jouer notre son avec la fonction Mix_PlayChannel() voici la
signature
#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1)
Nous avons encore à faire à une macro fonction !
Le premier paramètre est le numéro du canal.
Le deuxième paramètre est le pointeur sur le Mix_Chunck .
Le troisième paramètre c'est le nombre de répétition du son (mettre 0 le
répète 1 fois, mettre 1 répète deux fois etc ...)
Puis n'oubliez pas de libérer la mémoire des Mix_Chunk à la fin du programme en
appellant Mix_FreeChunk() , voici sa signature :
extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk);
Le premier paramètre est un pointeur sur une stucture Mix_Chunk.
Appartient à [Link] - lien original ici
Voici maintenant le résultat final :
#include <SDL.h>
#include <SDL_mixer.h>
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return -1;
if (Mix_OpenAudio(96000, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) < 0)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur initialisation SDL_mixer : %s", Mix
SDL_Quit();
return -1;
}
SDL_Window* pWindow = nullptr;
SDL_Renderer* pRenderer = nullptr;
SDL_Event events;
bool close = false;
if (SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_SHOWN, &pWindow, &pRenderer) < 0)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Erreur creation fenetre et rendue SDL : %s
Mix_CloseAudio();
SDL_Quit();
return -1;
}
Mix_AllocateChannels(2); // Allouer 2 cannaux
Mix_Volume(0, MIX_MAX_VOLUME); // Mets le son a 100% en volume pour le premier cannaux
Mix_Volume(1, MIX_MAX_VOLUME / 2); // Mets le son a 50% en volume pour le deuxièmme cannau
Mix_Chunk* soundA = Mix_LoadWAV("[Link]");
Mix_Chunk* soundB = Mix_LoadWAV("[Link]");
while (!close)
{
while (SDL_PollEvent(&events))
{
if ([Link] == SDL_WINDOWEVENT && [Link] == SDL_WINDOWEVENT_CLOSE
close = true;
if([Link] == SDL_KEYDOWN && [Link] == SDLK_a)
Mix_PlayChannel(0, soundA, 1); // Joue soundA deux fois sur le canal 1
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_b)
Mix_PlayChannel(1, soundB, 0); // Joue soundB une fois sur le canal 2
if ([Link] == SDL_KEYDOWN && [Link] == SDLK_z)
Mix_PlayChannel(0, soundB, 3), Mix_PlayChannel(1, soundA, 0); // Joue deux son
SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 255);
Appartient à [Link] - lien original ici
SDL_RenderClear(pRenderer);
SDL_RenderPresent(pRenderer);
}
Mix_FreeChunk(soundA); // Libére la mémoire allouer pour le son
Mix_FreeChunk(soundB);
SDL_DestroyRenderer(pRenderer);
SDL_DestroyWindow(pWindow);
Mix_CloseAudio();
SDL_Quit();
return 0;
}
Voilà nous avons quasiment finit ce tutoriel. Dorénavant, il nous reste qu'à voir
encore que certaines fonctions utilitaires pour les sons simultanés :
Pour stop un canal
extern DECLSPEC int SDLCALL Mix_HaltChannel(int channel);
Pour mettre en pause un cannal
extern DECLSPEC void SDLCALL Mix_Pause(int channel);
Pour reprendre la lecture d'un cannal
extern DECLSPEC void SDLCALL Mix_Resume(int channel);
Vous pouvez rentrer en paramètre soit le numéro du canal en question, soit la
valeur "-1" afin de stopper tous les canaux.
Bon voilà, nous en avons fini pour ce cours de programmation sous SDL. On aura
l'occasion de manipuler SDL pour créer de réels jeux vidéo et nous aurons aussi
l'occasion de voir d'autres tutoriels, mais dès à présent vous être prêts pour
développer des jeux vidéo intéressants.
Appartient à [Link] - lien original ici
REMERCIEMENT
Mon ami ttatanepvp123 (ton autre pseudo me dégoûte)
Mon ami Timtim , sans lui il n'y aurait pas eu ces articles sur la SDL et merci
énormément pour avoir corrigé mes articles.
Mon professeur de physique, et mon professeur de mathématiques pour
m'avoir enseigné à l'école la série de Fourier
Remerciement à tous mes lecteurs.
Appartient à [Link] - lien original ici
Appartient à [Link] - lien original ici