Accueil > > > MOTEUR DE SON UTILISANT FMOD (C++) (WAV-MIDI-MP3-ETC...)
MOTEUR DE SON UTILISANT FMOD (C++) (WAV-MIDI-MP3-ETC...)
Information sur la source
Description
Ce petit moteur sonore est vraiment le B-A BA de ce
que l'on peut faire avec Fmod.
Il est réalisé en C/C++ mais d'autres
langages aurais aussi bien pu faire l'affaire ...
Il va sagir d'initialiser/désinitialiser Fmod,
de pouvoir ajouter/retirer des sons stockés à l'intérieur
d'un vector (utilisé pour l'occasion comme un petit tableau dynamique),
et de pouvoir les jouer et les stopper quand on le désire.
Donc en résumé, tout ça restera très basique : pas de son 3D, pas d'effets ou de fioritures...
Ce tut est donc réservé aux débutants (dont je fais partie ;-)) désirant avoir une première approche évoluée de ce que peut apporter la prise en charge du son dans un prog...
J'ai réalisé ce SoundEngine sous Visual C++ 6, donc je ne peux
expliquer comment régler l'environnement que sur VS.
Mais la doc de Fmod étant très complète, je vous propose d'aller y jeter
un oeil si vous êtes allergiques à Microsoft, tout sera expliqué en détail pour les autres EDI.
Donc pour commencer vous n'aurez besoin de 3 choses :
- la librairie fmodvc.lib à inclure dans le projet (spécifique ici à VS6 !)
- le fichier d'entête fmod.h
- la dll de Fmod : fmod.dll à mettre soit dans le
répertoire de l'exécutable, soit dans system32
Vous trouverez tout ça en téléchargeant l'api Fmod sur le site de Fmod (http://www.fmod.org)
Après, c'est que du code, mais rien de bien méchant vous allez voir.
Source
- 1. Création d'une classe intermédiaire, la classe Son
-
-
- INTERFACE
-
- class Son
- {
- public:
- Son() {}
- ~Son() {}
-
- //format
- int format;
- FSOUND_STREAM * stream;
- FSOUND_SAMPLE * sample;
- FMUSIC_MODULE * module;
-
- //charge un fichier son
- BOOL Charger(char *fichAdr, int format);
- void Liberer(void);
-
- //joue et un stoppe le son
- BOOL Jouer(void);
- void Stopper(void);
- };
-
-
- Vous vous demandez sûrement quels sont les formats de sons évoqués ci-dessus. C'est tout simple. On peut disinguer 3 grandes sortes de sons :
- - les gros fichiers WAV/MP3/etc... stockés en stream
- - les petits fichiers WAV/MP3/etc... stockés en sample
- - les fichiers MIDI/etc... stockés en modules
-
-
- Remarque : c'est à l'utilisateur lui-même de savoir à l'avance quel format de fichier va être chargé
-
- Remarque : un petit point important : Fmod est séparé en deux plus petites api, FSound et FMusic. Chacune est spécialisée dans le traitement d'une famille de son. FSound pour les stream et sample et FMusic pour les modules.
-
-
- Pour chaque son il y a donc un pointeur vers chacune de ces structures.
-
- On définit pour cela quelques constantes qui vont être passées en argument lors du chargement des sons :
-
- //gros mp3/wav -> loop
- #define STREAM_TYPE 0
- //petits mp3/wav -> joués une fois
- #define SAMPLE_TYPE 1
- //midi et autres -> loop
- #define MODULE_TYPE_MUSIC 2
- //midi et autres -> joués une fois
- #define MODULE_TYPE_SOUND 3
-
-
- Les autres fonctions parlant d'elles-même, passons à la réalisation.
-
- Nous n'allons exposer ici que la méthode de chargement. Etant la plus "complexe" (^_^ toute proportion gardée), elle va nous permettre de poser quelques bases :
-
-
-
-
- REALISATION
-
- /* Charge un son en fonction du format spécifié*/
- BOOL Son::Charger(char *fichAdr, int format)
- {
- BOOL result = TRUE;
-
- //on stocke le format du son
- this->format = format;
-
- //on charge suivant le format
- switch(format)
- {
- //stream
- case STREAM_TYPE:
- stream = NULL;
- stream = FSOUND_Stream_OpenFile(fichAdr, FSOUND_LOOP_NORMAL, 0);
- if(stream == NULL)
- result = FALSE;
- break;
-
- //sample
- case SAMPLE_TYPE:
- sample = NULL;
- sample = FSOUND_Sample_Load(FSOUND_FREE, fichAdr, FSOUND_LOOP_OFF, 0);
- if(sample == NULL)
- result = FALSE;
- break;
-
- //module loop
- case MODULE_TYPE_MUSIC:
- module = NULL;
- module = FMUSIC_LoadSong(fichAdr);
- FMUSIC_SetMasterVolume(module, 160);
- if(module == NULL)
- result = FALSE;
- break;
-
- //module simple
- case MODULE_TYPE_SOUND:
- module = NULL;
- module = FMUSIC_LoadSong(fichAdr);
- FMUSIC_SetMasterVolume(module, 160);
- FMUSIC_SetLooping(module,FALSE);
- if(module == NULL)
- result = FALSE;
- break;
-
- //si aucun init fail
- default:
- result = FALSE;
- break;
- }
-
- return result;
- }
-
-
- Remarque : j'ai choisi de régler du volume des sons de type module juste après leur chargement.
- Il faut savoir que pour ce type de fichiers particulier, le volume se règle individuellement pour chaque module (de 0 à 255 - 160 étant un bon compromis).
- On aurais aussi bien pu régler tout ça par la suite, mais autant le faire depuis le début....
-
- Ce qu'il faut bien remarquer dans cette méthode est le passage en paramètre du format du son. Comme je l'ai évoqué plus haut, c'est donc à l'utilisateur de savoir quel sont il va charger au moment de l'appel de la procédure.
-
- J'ai également fait un choix (contestable, mais se révèlant après expérience plutôt concluant) : les répétitions.
- C'est-à-dire le nombre de fois qu'un son va être joué d'affilé : les stream et les modules de type musique sont répétées à l'infini, tandis que les sample et les modules de type son ne sont joués qu'une fois.
- On aurais très bien pu complexifier cette fonction de chargement pour la rendre plus "customisable"... Mais le principal caractère de ce moteur étant son accessibilité, je n'ai rien inplémenté de tel.
-
- Excepté ces petits détails, aucune difficulté (consultez la doc de Fmod pour les méthodes de chargement (d'ailleurs très simples à utiliser)).
-
- Le reste des méthodes, Jouer/Stopper et Liberer ne necessitent pas selon moi de longues explications si l'on à compris comment était réalisée la méthode Charger.
-
- A noter tout de même que la fonction Charger ne libére rien au moment de charger un son. Pensez donc bien à libérer un son avant de vouloir le recharger à partir d'un autre fichier.
-
- Voilà les autres fonction.
-
- /* Libère le son*/
- void Son::Liberer(void)
- {
- //si c'est une stream ou un module on libère
- if(format == STREAM_TYPE)
- {
- FSOUND_Stream_Close(stream);
- stream=NULL;
- }
- else if(format == MODULE_TYPE_MUSIC
- || format == MODULE_TYPE_SOUND)
- {
- FMUSIC_FreeSong(module);
- module=NULL;
- }
- }
-
- /* Joue le son en fonction du format*/
- BOOL Son::Jouer(void)
- {
- //on joue suivant le type de format
- switch(format)
- {
- //stream (loop)
- case STREAM_TYPE:
- if(FSOUND_Stream_Play(FSOUND_FREE, stream) == -1)
- return FALSE;
- break;
-
- //sample
- case SAMPLE_TYPE:
- if(FSOUND_PlaySound(FSOUND_FREE, sample) == -1)
- return FALSE;
- break;
-
- //module (loop)
- case MODULE_TYPE_MUSIC:
- if(FMUSIC_PlaySong(module) == NULL)
- return FALSE;
- break;
-
- //module
- case MODULE_TYPE_SOUND:
- if(FMUSIC_PlaySong(module) == NULL)
- return FALSE;
- break;
-
- default:
- break;
- }
-
- return TRUE;
- }
-
- /* Stope la lecture en cours d'une stream ou d'un module*/
- void Son::Stopper(void)
- {
- //si c'est une stream ou un module on stoppe
- if(format == STREAM_TYPE)
- FSOUND_Stream_Stop(stream);
- else if(format == MODULE_TYPE_MUSIC
- ||format == MODULE_TYPE_SOUND)
- FMUSIC_StopSong(module);
- }
-
-
-
-
-
- 2. La classe SoundEngine
-
- Voilà comment elle se présente :
-
- INTERFACE
-
- class SoundEngine
- {
- public :
- vector<Son> sons;
-
- SoundEngine() {}
- ~SoundEngine() {}
-
- /* Initialise tout :
- * mixRate = frequence de sortie
- * maxChannels = nombre de sons pouvant être traité à la fois
- */
- BOOL Initialiser(int mixRate, int maxChannels);
-
- //On désinitialise tout
- BOOL Desinitialiser(void);
-
- /* Charge un nouveau son :
- * fichAdr = adresse du fichier son
- * format = stream/sample/module (voir constantes)
- */
- BOOL AjouterSon(Son son);
- BOOL AjouterSon(Son son, int index);
- BOOL AjouterSon(char *fichAdr, int format);
- BOOL AjouterSon(char *fichAdr, int format, int index);
-
- //Retire un son, soit à un index donné, soit le dernier chargé
- BOOL RetirerSon(void);
- BOOL RetirerSon(int index);
-
- //Joue le son
- BOOL Jouer(int index);
-
- //Stoppe le son
- BOOL Stopper(int index);
- };
-
-
- On peut distinguer 3 types de méthodes :
-
- - Initialisation : Initialiser/Desinitialiser
- - Stockage : AjouterSon/RetirerSon
- - Rendu : Jouer/Stopper
-
- Pour stocker les sons j'utilise un vector de Son Pour ceux qui ne savent pas ce que c'est qu'un vector, c'est en fait une fonctionnalité faisant partie de la stl - bibliothèque de classes container - permettant en autres de créer de tableaux dynamique efficacement. Il permet d'éviter l'enchainement des new et delete en cascade et ainsi pas mal de problèmes ^_^.
- Allez faire un tour sur la page des liens si vous voulez en savoir plus.
-
-
- REALISATION
-
- Bon, voilà le code :
-
- /*Initialisation*/
- BOOL SoundEngine::Initialiser(int mixRate, int maxChannels)
- {
- //On definit le volume des mp3 et wave
- FSOUND_SetVolume(FSOUND_ALL,160);
-
- return FSOUND_Init(mixRate, maxChannels, FSOUND_INIT_USEDEFAULTMIDISYNTH );
- }
-
-
- Remarque : on règle ici le volume des stream et des sample (map3 et wav principalement). Le volume de ces format ne sont pas réglés individuellement pour chaque son, comme pour les modules, mais globalement. A noter que cette fonctionalité est utilisable à n'importe quel moment dans un programme.
-
-
- /*Desinitialisation*/
- BOOL SoundEngine::Desinitialiser(void)
- {
- BOOL init = TRUE;
-
- try
- {
- //on stoppe et libère les sons
- for(int i=0; i<sons.size(); i++)
- {
- sons.at(i).Stopper();
- sons.at(i).Liberer();
- }
- }
- catch(...)
- {
- init = FALSE;
- }
-
- //on ferme Fmod
- FSOUND_Close();
-
- return init;
- }
-
- Remarque : attention à ne pas l'oublier, la bonne libération des objets peut éviter bien des soucis par la suite (surtout sous Win9x...)
-
-
-
- /*Ajoute un son dans le vector - Ver1*/
- BOOL SoundEngine::AjouterSon(Son son)
- {
- //on le range dans le vector
- sons.push_back(son);
-
- return TRUE;
- }
-
-
- /*Ajoute un son dans le vector - Ver2*/
- BOOL SoundEngine::AjouterSon(Son son, int index)
- {
- //si l'index dépasse la capacité du vector
- if(index < 0 || index > sons.size() - 1)
- return FALSE;
-
- vector<Son>::iterator it;
- it = sons.begin();
- it += index;
-
- //on le range dans le vector à l'index indiqué
- sons.insert(it, son);
-
- return TRUE;
- }
-
-
- /*Ajoute un son dans le vector - Ver3*/
- BOOL SoundEngine::AjouterSon(char *fichAdr, int format)
- {
- Son temp;
-
- if(!temp.Charger(fichAdr, format))
- return FALSE;
-
- //on le range dans le vector
- sons.push_back(temp);
-
- return TRUE;
- }
-
- /*Ajoute un son dans le vector - Ver4*/
- BOOL SoundEngine::AjouterSon(char *fichAdr, int format, int index)
- {
- Son temp;
-
- //si l'index dépasse la capacité du vector
- if(index < 0 || index > sons.size() - 1)
- return FALSE;
-
- //on charge un objet temporaire
- if(!temp.Charger(fichAdr, format))
- return FALSE;
-
- vector<Son>::iterator it;
- it = sons.begin();
- it += index;
-
- //on le range dans le vector à l'index indiqué
- sons.insert(it, temp);
-
- return TRUE;
- }
-
- Remarque : 4 versions pour une même méthode. On peut ainsi ajouter des sons directement à partir d'une classe Son mais également en fournissant simplement le chemin d'accès au fichier ainsi que son format. Il est également possible de choisir où ce son sera stocké dans le vector.
-
-
-
- /*Retire un son du vector - Ver1*/
- BOOL SoundEngine::RetirerSon(void)
- {
- //on retire le dernier son chargé
- sons.pop_back();
-
- return TRUE;
- }
-
- /*Retire un son du vector - Ver2*/
- BOOL SoundEngine::RetirerSon(int index)
- {
- //si l'index dépasse la capacité du vector
- if(index > sons.size() - 1 || index < 0)
- return FALSE;
-
- vector<Son>::iterator it;
- it = sons.begin();
- it += index;
-
- //on retire le son à l'index indiqué
- sons.erase(it);
-
- return TRUE;
- }
-
-
- Remarque : 2 versions pour cette méthode. Cela va permettre de pouvoir retirer un son à n'importe quel endroit du vector.
-
-
-
- /*Joue le son situé à l'index indiqué*/
- BOOL SoundEngine::Jouer(int index)
- {
- //si l'index dépasse la capacité du vector
- if(index > sons.size() - 1 || index < 0)
- return FALSE;
-
- sons[index].Jouer();
-
- return TRUE;
- }
-
- /*Stoppe le son indiqué*/
- BOOL SoundEngine::Stopper(int index)
- {
- //si l'index dépasse la capacité du vector
- if(index > sons.size() - 1 || index < 0)
- return FALSE;
-
- //on joue le son
- sons[index].Stopper();
-
- return TRUE;
- }
-
-
- Remarque : Pour jouer et stopper les sons, on utilise directement
- la fonction contenue dans la classe Son, après avoir bien
- sur testé la validité de l'index fournis en paramètre.
-
- Voilà, c'est tout pour la création du SoundEngine.
- Si vous avez des questions n'hésitez pas à me contacter.
-
- Passons maintenant à son utilisation au sein de votre programme.
-
-
-
-
- 3. Utilisation
-
-
- Tout d'abord, vous devez déclarer une variable
- de type SoundEngine (ici globale mais on peut adapter).
-
-
- //variable de type SoundEngine
- SoundEngine soundEngine;
-
- //Viens ensuite l'initialisation :
- //fréquence à 44khz et 32 cannaux
- soundEngine.Initialiser(44000, 32);
-
- //On peut maintant ajouter des sons :
- //ajout de sons avec une classe Son déjà déclarée
- Son temp;
- temp.Charger("grosMP3.mp3", TYPE_STREAM);
- soundEngine.AjouterSon(temp);
-
- temp.Liberer();
- temp.Charger("petitWAV.wav", TYPE_SAMPLE);
- soundEngine.AjouterSon(temp, 1);
-
- temp.Liberer();
- temp.Charger("midiMusique1.mid", MODULE_TYPE_MUSIC);
- soundEngine.AjouterSon(temp);
-
- temp.Liberer();
- temp.Charger("midiSon1.mid", MODULE_TYPE_SOUND);
- soundEngine.AjouterSon(temp);
-
- temp.Liberer();
-
- //ajout de sons par chemin d'accés
- soundEngine.AjouterSon("petitMP3.mp3", SAMPLE_TYPE);
- soundEngine.AjouterSon("grosWAV.wav", STREAM_TYPE);
- soundEngine.AjouterSon("midiMusique1.mid", MODULE_TYPE_MUSIC);
- soundEngine.AjouterSon("midiSon1.mid", MODULE_TYPE_SOUND, 0);
-
-
- //Par exemple.
- //On peut maintenant les jouer/stopper.
-
-
- ...
- //jouera midiSon1.mid
- soundEngine.Jouer(0);
- //jouera grosMP3.mp3
- soundEngine.Jouer(1);
- ...
- //arretera la lecture
- soundEngine.Stopper(0);
- //arretera la lecture
- soundEngine.Stopper(1);
-
- ...
- //jouera grosWAV.wav
- soundEngine.Jouer(6);
- ...
- //arretera la lecture
- soundEngine.Stopper(6);
-
-
-
-
- //A la fin de votre programme il ne vous restera plus qu'à désinitialiser :
-
- //désinitialise Fmod et libère tous les sons chargés
- soundEngine.Desinitialiser();
-
-
-
-
-
-
-
- Voilà c'est tout !
- Si vous voyez des erreurs, prévenez-moi je corrigerais tout ça dès que je pourrais.
-
- Si vous avez des conseils concernant ce SoundEngine, n'hésitez pas non plus à me contacter ;-).
-
- J'ai fournit une archive contenat le fichier d'entête et de réalisation.
-
- Bonne lecture. Fab
-
1. Création d'une classe intermédiaire, la classe Son
INTERFACE
class Son
{
public:
Son() {}
~Son() {}
//format
int format;
FSOUND_STREAM * stream;
FSOUND_SAMPLE * sample;
FMUSIC_MODULE * module;
//charge un fichier son
BOOL Charger(char *fichAdr, int format);
void Liberer(void);
//joue et un stoppe le son
BOOL Jouer(void);
void Stopper(void);
};
Vous vous demandez sûrement quels sont les formats de sons évoqués ci-dessus. C'est tout simple. On peut disinguer 3 grandes sortes de sons :
- les gros fichiers WAV/MP3/etc... stockés en stream
- les petits fichiers WAV/MP3/etc... stockés en sample
- les fichiers MIDI/etc... stockés en modules
Remarque : c'est à l'utilisateur lui-même de savoir à l'avance quel format de fichier va être chargé
Remarque : un petit point important : Fmod est séparé en deux plus petites api, FSound et FMusic. Chacune est spécialisée dans le traitement d'une famille de son. FSound pour les stream et sample et FMusic pour les modules.
Pour chaque son il y a donc un pointeur vers chacune de ces structures.
On définit pour cela quelques constantes qui vont être passées en argument lors du chargement des sons :
//gros mp3/wav -> loop
#define STREAM_TYPE 0
//petits mp3/wav -> joués une fois
#define SAMPLE_TYPE 1
//midi et autres -> loop
#define MODULE_TYPE_MUSIC 2
//midi et autres -> joués une fois
#define MODULE_TYPE_SOUND 3
Les autres fonctions parlant d'elles-même, passons à la réalisation.
Nous n'allons exposer ici que la méthode de chargement. Etant la plus "complexe" (^_^ toute proportion gardée), elle va nous permettre de poser quelques bases :
REALISATION
/* Charge un son en fonction du format spécifié*/
BOOL Son::Charger(char *fichAdr, int format)
{
BOOL result = TRUE;
//on stocke le format du son
this->format = format;
//on charge suivant le format
switch(format)
{
//stream
case STREAM_TYPE:
stream = NULL;
stream = FSOUND_Stream_OpenFile(fichAdr, FSOUND_LOOP_NORMAL, 0);
if(stream == NULL)
result = FALSE;
break;
//sample
case SAMPLE_TYPE:
sample = NULL;
sample = FSOUND_Sample_Load(FSOUND_FREE, fichAdr, FSOUND_LOOP_OFF, 0);
if(sample == NULL)
result = FALSE;
break;
//module loop
case MODULE_TYPE_MUSIC:
module = NULL;
module = FMUSIC_LoadSong(fichAdr);
FMUSIC_SetMasterVolume(module, 160);
if(module == NULL)
result = FALSE;
break;
//module simple
case MODULE_TYPE_SOUND:
module = NULL;
module = FMUSIC_LoadSong(fichAdr);
FMUSIC_SetMasterVolume(module, 160);
FMUSIC_SetLooping(module,FALSE);
if(module == NULL)
result = FALSE;
break;
//si aucun init fail
default:
result = FALSE;
break;
}
return result;
}
Remarque : j'ai choisi de régler du volume des sons de type module juste après leur chargement.
Il faut savoir que pour ce type de fichiers particulier, le volume se règle individuellement pour chaque module (de 0 à 255 - 160 étant un bon compromis).
On aurais aussi bien pu régler tout ça par la suite, mais autant le faire depuis le début....
Ce qu'il faut bien remarquer dans cette méthode est le passage en paramètre du format du son. Comme je l'ai évoqué plus haut, c'est donc à l'utilisateur de savoir quel sont il va charger au moment de l'appel de la procédure.
J'ai également fait un choix (contestable, mais se révèlant après expérience plutôt concluant) : les répétitions.
C'est-à-dire le nombre de fois qu'un son va être joué d'affilé : les stream et les modules de type musique sont répétées à l'infini, tandis que les sample et les modules de type son ne sont joués qu'une fois.
On aurais très bien pu complexifier cette fonction de chargement pour la rendre plus "customisable"... Mais le principal caractère de ce moteur étant son accessibilité, je n'ai rien inplémenté de tel.
Excepté ces petits détails, aucune difficulté (consultez la doc de Fmod pour les méthodes de chargement (d'ailleurs très simples à utiliser)).
Le reste des méthodes, Jouer/Stopper et Liberer ne necessitent pas selon moi de longues explications si l'on à compris comment était réalisée la méthode Charger.
A noter tout de même que la fonction Charger ne libére rien au moment de charger un son. Pensez donc bien à libérer un son avant de vouloir le recharger à partir d'un autre fichier.
Voilà les autres fonction.
/* Libère le son*/
void Son::Liberer(void)
{
//si c'est une stream ou un module on libère
if(format == STREAM_TYPE)
{
FSOUND_Stream_Close(stream);
stream=NULL;
}
else if(format == MODULE_TYPE_MUSIC
|| format == MODULE_TYPE_SOUND)
{
FMUSIC_FreeSong(module);
module=NULL;
}
}
/* Joue le son en fonction du format*/
BOOL Son::Jouer(void)
{
//on joue suivant le type de format
switch(format)
{
//stream (loop)
case STREAM_TYPE:
if(FSOUND_Stream_Play(FSOUND_FREE, stream) == -1)
return FALSE;
break;
//sample
case SAMPLE_TYPE:
if(FSOUND_PlaySound(FSOUND_FREE, sample) == -1)
return FALSE;
break;
//module (loop)
case MODULE_TYPE_MUSIC:
if(FMUSIC_PlaySong(module) == NULL)
return FALSE;
break;
//module
case MODULE_TYPE_SOUND:
if(FMUSIC_PlaySong(module) == NULL)
return FALSE;
break;
default:
break;
}
return TRUE;
}
/* Stope la lecture en cours d'une stream ou d'un module*/
void Son::Stopper(void)
{
//si c'est une stream ou un module on stoppe
if(format == STREAM_TYPE)
FSOUND_Stream_Stop(stream);
else if(format == MODULE_TYPE_MUSIC
||format == MODULE_TYPE_SOUND)
FMUSIC_StopSong(module);
}
2. La classe SoundEngine
Voilà comment elle se présente :
INTERFACE
class SoundEngine
{
public :
vector<Son> sons;
SoundEngine() {}
~SoundEngine() {}
/* Initialise tout :
* mixRate = frequence de sortie
* maxChannels = nombre de sons pouvant être traité à la fois
*/
BOOL Initialiser(int mixRate, int maxChannels);
//On désinitialise tout
BOOL Desinitialiser(void);
/* Charge un nouveau son :
* fichAdr = adresse du fichier son
* format = stream/sample/module (voir constantes)
*/
BOOL AjouterSon(Son son);
BOOL AjouterSon(Son son, int index);
BOOL AjouterSon(char *fichAdr, int format);
BOOL AjouterSon(char *fichAdr, int format, int index);
//Retire un son, soit à un index donné, soit le dernier chargé
BOOL RetirerSon(void);
BOOL RetirerSon(int index);
//Joue le son
BOOL Jouer(int index);
//Stoppe le son
BOOL Stopper(int index);
};
On peut distinguer 3 types de méthodes :
- Initialisation : Initialiser/Desinitialiser
- Stockage : AjouterSon/RetirerSon
- Rendu : Jouer/Stopper
Pour stocker les sons j'utilise un vector de Son Pour ceux qui ne savent pas ce que c'est qu'un vector, c'est en fait une fonctionnalité faisant partie de la stl - bibliothèque de classes container - permettant en autres de créer de tableaux dynamique efficacement. Il permet d'éviter l'enchainement des new et delete en cascade et ainsi pas mal de problèmes ^_^.
Allez faire un tour sur la page des liens si vous voulez en savoir plus.
REALISATION
Bon, voilà le code :
/*Initialisation*/
BOOL SoundEngine::Initialiser(int mixRate, int maxChannels)
{
//On definit le volume des mp3 et wave
FSOUND_SetVolume(FSOUND_ALL,160);
return FSOUND_Init(mixRate, maxChannels, FSOUND_INIT_USEDEFAULTMIDISYNTH );
}
Remarque : on règle ici le volume des stream et des sample (map3 et wav principalement). Le volume de ces format ne sont pas réglés individuellement pour chaque son, comme pour les modules, mais globalement. A noter que cette fonctionalité est utilisable à n'importe quel moment dans un programme.
/*Desinitialisation*/
BOOL SoundEngine::Desinitialiser(void)
{
BOOL init = TRUE;
try
{
//on stoppe et libère les sons
for(int i=0; i<sons.size(); i++)
{
sons.at(i).Stopper();
sons.at(i).Liberer();
}
}
catch(...)
{
init = FALSE;
}
//on ferme Fmod
FSOUND_Close();
return init;
}
Remarque : attention à ne pas l'oublier, la bonne libération des objets peut éviter bien des soucis par la suite (surtout sous Win9x...)
/*Ajoute un son dans le vector - Ver1*/
BOOL SoundEngine::AjouterSon(Son son)
{
//on le range dans le vector
sons.push_back(son);
return TRUE;
}
/*Ajoute un son dans le vector - Ver2*/
BOOL SoundEngine::AjouterSon(Son son, int index)
{
//si l'index dépasse la capacité du vector
if(index < 0 || index > sons.size() - 1)
return FALSE;
vector<Son>::iterator it;
it = sons.begin();
it += index;
//on le range dans le vector à l'index indiqué
sons.insert(it, son);
return TRUE;
}
/*Ajoute un son dans le vector - Ver3*/
BOOL SoundEngine::AjouterSon(char *fichAdr, int format)
{
Son temp;
if(!temp.Charger(fichAdr, format))
return FALSE;
//on le range dans le vector
sons.push_back(temp);
return TRUE;
}
/*Ajoute un son dans le vector - Ver4*/
BOOL SoundEngine::AjouterSon(char *fichAdr, int format, int index)
{
Son temp;
//si l'index dépasse la capacité du vector
if(index < 0 || index > sons.size() - 1)
return FALSE;
//on charge un objet temporaire
if(!temp.Charger(fichAdr, format))
return FALSE;
vector<Son>::iterator it;
it = sons.begin();
it += index;
//on le range dans le vector à l'index indiqué
sons.insert(it, temp);
return TRUE;
}
Remarque : 4 versions pour une même méthode. On peut ainsi ajouter des sons directement à partir d'une classe Son mais également en fournissant simplement le chemin d'accès au fichier ainsi que son format. Il est également possible de choisir où ce son sera stocké dans le vector.
/*Retire un son du vector - Ver1*/
BOOL SoundEngine::RetirerSon(void)
{
//on retire le dernier son chargé
sons.pop_back();
return TRUE;
}
/*Retire un son du vector - Ver2*/
BOOL SoundEngine::RetirerSon(int index)
{
//si l'index dépasse la capacité du vector
if(index > sons.size() - 1 || index < 0)
return FALSE;
vector<Son>::iterator it;
it = sons.begin();
it += index;
//on retire le son à l'index indiqué
sons.erase(it);
return TRUE;
}
Remarque : 2 versions pour cette méthode. Cela va permettre de pouvoir retirer un son à n'importe quel endroit du vector.
/*Joue le son situé à l'index indiqué*/
BOOL SoundEngine::Jouer(int index)
{
//si l'index dépasse la capacité du vector
if(index > sons.size() - 1 || index < 0)
return FALSE;
sons[index].Jouer();
return TRUE;
}
/*Stoppe le son indiqué*/
BOOL SoundEngine::Stopper(int index)
{
//si l'index dépasse la capacité du vector
if(index > sons.size() - 1 || index < 0)
return FALSE;
//on joue le son
sons[index].Stopper();
return TRUE;
}
Remarque : Pour jouer et stopper les sons, on utilise directement
la fonction contenue dans la classe Son, après avoir bien
sur testé la validité de l'index fournis en paramètre.
Voilà, c'est tout pour la création du SoundEngine.
Si vous avez des questions n'hésitez pas à me contacter.
Passons maintenant à son utilisation au sein de votre programme.
3. Utilisation
Tout d'abord, vous devez déclarer une variable
de type SoundEngine (ici globale mais on peut adapter).
//variable de type SoundEngine
SoundEngine soundEngine;
//Viens ensuite l'initialisation :
//fréquence à 44khz et 32 cannaux
soundEngine.Initialiser(44000, 32);
//On peut maintant ajouter des sons :
//ajout de sons avec une classe Son déjà déclarée
Son temp;
temp.Charger("grosMP3.mp3", TYPE_STREAM);
soundEngine.AjouterSon(temp);
temp.Liberer();
temp.Charger("petitWAV.wav", TYPE_SAMPLE);
soundEngine.AjouterSon(temp, 1);
temp.Liberer();
temp.Charger("midiMusique1.mid", MODULE_TYPE_MUSIC);
soundEngine.AjouterSon(temp);
temp.Liberer();
temp.Charger("midiSon1.mid", MODULE_TYPE_SOUND);
soundEngine.AjouterSon(temp);
temp.Liberer();
//ajout de sons par chemin d'accés
soundEngine.AjouterSon("petitMP3.mp3", SAMPLE_TYPE);
soundEngine.AjouterSon("grosWAV.wav", STREAM_TYPE);
soundEngine.AjouterSon("midiMusique1.mid", MODULE_TYPE_MUSIC);
soundEngine.AjouterSon("midiSon1.mid", MODULE_TYPE_SOUND, 0);
//Par exemple.
//On peut maintenant les jouer/stopper.
...
//jouera midiSon1.mid
soundEngine.Jouer(0);
//jouera grosMP3.mp3
soundEngine.Jouer(1);
...
//arretera la lecture
soundEngine.Stopper(0);
//arretera la lecture
soundEngine.Stopper(1);
...
//jouera grosWAV.wav
soundEngine.Jouer(6);
...
//arretera la lecture
soundEngine.Stopper(6);
//A la fin de votre programme il ne vous restera plus qu'à désinitialiser :
//désinitialise Fmod et libère tous les sons chargés
soundEngine.Desinitialiser();
Voilà c'est tout !
Si vous voyez des erreurs, prévenez-moi je corrigerais tout ça dès que je pourrais.
Si vous avez des conseils concernant ce SoundEngine, n'hésitez pas non plus à me contacter ;-).
J'ai fournit une archive contenat le fichier d'entête et de réalisation.
Bonne lecture. Fab
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Forum
MATRICE TEMPLATEMATRICE TEMPLATE par hjr2610
Cliquez pour lire la suite par hjr2610 RE : SAC A DOS RE : SAC A DOS par hadjkaddour
Cliquez pour lire la suite par hadjkaddour
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|