Gestion du son avec Windows

Pour produire un son, il est possible d'utiliser les fonctions PlaySound ou sndPlaySound offertes par Windows. Ces deux fonctions sont déclarée dans le fichier d'en-tête mmsystem.h qu'il faut donc inclure en début de programme (#include <mmsystem.h>). Il faut également importer la librairie winmm.lib en l'ajoutant dans les paramètres du projet (voir Développer avec OpenGL).

Ces deux fonctions offrent plusieurs options. Nous ne détaillerons que quelques unes d'entre elles.

Remarque : ces fonctions ne gèrent pas les sons mp3 mais les wav.

La fonction PlaySound est déclarée ainsi :

BOOL PlaySound(
  LPCSTR pszSound,  
  HMODULE hmod,     
  DWORD fdwSound    
);

Le premier argument pszSound est une chaîne de caractères qui spécifie le son à jouer. Si ce paramètre est NULL, tous les sons en train d'être joués sont arrêtés

Le deuxième argument hmod est NULL, sauf si SND_RESOURCE est spécifié dans fdwSound (option que nous ne développerons pas).

Le troisième argument fdwSound est constitué de "flags" qui peuvent-être entre autres : (il est possible de mettre plusieurs valeurs à la suite les unes des autres)
   SND_ASYNC : Le son est joué de manière asynchrone et PlaySound rend la main tout de suite après avoir commencé le son. Pour terminer un son joué de manière asynchrone, rappeller PlaySound avec pszSound mis à NULL.
   SND_FILENAME : le paramètre pszSound est un nom de fichier.
   SND_LOOP : le son est joué indéfiniment jusqu'à ce que PlaySound soit de nouveau appelée avec le paramètre pszSound mis à NULL. Attention, il faut spécifier SND_ASYNC pour indiquer que le son est joué de manière asynchrone.
   SND_NODEFAULT : Si PlaySound ne peut pas trouver le son, la fonction rend la main en silence sans jouer le son par défaut.
   SND_NOSTOP : Si un son est en train d'être joué, la fonction retourne immédiatement la valeur FALSE sans jouer le son requis. Si le flag n'est pas spécifié, PlaySound tente d'arrêter le son en train d'être joué pour que le nouveau son puisse être joué.
   SND_SYNC : PlaySound rend la main après que le son est terminé.

Valeurs retournées : TRUE si succès, FALSE sinon.

Remarques : PlaySound cherche le fichier de son entre autres dans le répertoire courant. Si elle ne trouve pas le son spécifié, PlaySound utilise le son system par défaut à la place. Si elle ne le trouve pas non plus, elle ne fait aucun son et retourne FALSE.



La fonction sndPlaySound est déclarée ainsi :

BOOL sndPlaySound(
  LPCSTR lpszSound,  
  UINT fuSound       
);

Le premier argument lpszSound est une chaîne de caractères qui spécifie le son à jouer. Si ce paramètre est NULL, tous les sons en train d'être joués sont arrêtés

Le deuxième argument fuSound est constitué de "flags" qui peuvent-être entre autres : (il est possible de mettre plusieurs valeurs à la suite les unes des autres)


   SND_ASYNC : Le son est joué de manière asynchrone et la fonction rend la main tout de suite après avoir commencé le son. Pour terminer un son joué de manière asynchrone, rappeller sndPlaySound avec lpszSoundName mis à NULL.
   SND_LOOP : le son est joué indéfiniment jusqu'à ce que sndPlaySound soit de nouveau appelée avec le paramètre lpszSoundName mis à NULL. Il faut aussi spécifier le flag SND_ASYNC pour les sons joué en boucle.
   SND_NODEFAULT : si la fonction ne peut pas trouver le son, elle rend la main en silence sans jouer le son par défaut.
   SND_NOSTOP : Si un son est en train d'être joué, la fonction retourne immédiatement la valeur FALSE sans jouer le son requis.
   SND_SYNC : le son est joué de manière synchrone et la fonction rend la main quand le son est terminé.

Valeurs retournées : TRUE si succès, FALSE sinon.

Remarque : si la fonction sndPlaySound ne trouve pas le son spécifié, elle utilise le son system par défaut à la place. Si elle ne le trouve pas non plus, elle ne fait aucun son et retourne FALSE. Le fichier de son spécifié est cherché entre autres dans le répertoire courant.



Voici quelques exemples d'utilisation :

* Le son est joué puis apparaît le message "C'est fini".


#include <windows.h>
#include <mmsystem.h>

void main (void) { 
	sndPlaySound("test.wav",SND_SYNC);
	//ou PlaySound("test.wav",NULL,SND_SYNC);

	printf("C'est fini\n");
}



* Le son est joué et en même temps le programme continue (on introduit donc une pause de 3 secondes pour que le son ait le temps d'être joué). Le message "Delai de trois secondes" s'affiche en même temps que le son est joué.

#include <windows.h>
#include <mmsystem.h>
#include <time.h>

// Pauses pour un nombre spécifique de millisecondes
void sleep( clock_t wait )
{
   clock_t but;
   but = wait + clock();
   while( but > clock() );
}

void main (void) { 
	sndPlaySound("test.wav",SND_ASYNC);
	//ou PlaySound("test.wav",NULL,SND_ASYNC);

	// Delai pour un temps spécifique
	printf( "Delai de trois secondes\n" );
	sleep( (clock_t)3 * CLOCKS_PER_SEC );
	printf( "C'est fait!\n" );
}



* Un premier son est joué (test.wav). Un deuxième est joué en tâche de fond (test2.wav dans un timer Glut), mais il ne peut s'exprimer que lorsque le premier son est terminé car il a le flag SND_NOSTOP.

#include <windows.h>
#include <mmsystem.h>
#include <gl/gl.h>
#include <gl/glut.h>

void vTimer(int i)
{
	sndPlaySound("test2.wav",SND_SYNC|SND_NOSTOP);
	//ou PlaySound("test2.wav",NULL,SND_SYNC|SND_NOSTOP);

	glutTimerFunc(20, vTimer, 1);
}


void vDisplay()
{
	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT);
	glFlush();
}

void main ( int argc, char *argv[ ]) { 

	glutInit(&argc,argv);	// initialisation de GLUT
	glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
	glutInitWindowSize(50,50);
	glutInitWindowPosition(100,100);
	glutCreateWindow("Son");
	glutDisplayFunc(vDisplay);


	sndPlaySound("test.wav",SND_ASYNC);
	//ou PlaySound("test.wav",NULL,SND_ASYNC);

	glutTimerFunc(20, vTimer, 1);
	glutMainLoop();

}



* Un premier son (test.wav) est joué indéfiniment, jusqu'à l'appel de sndPlaySound qui joue le son test2.wav (3 secondes après).

#include <time.h>
#include <windows.h>
#include <mmsystem.h>


// Pauses pour un nombre spécifique de millisecondes
void sleep( clock_t wait )
{
   clock_t but;
   but = wait + clock();
   while( but > clock() );
}

void main (void) { 



	sndPlaySound("test.wav",SND_LOOP | SND_ASYNC);
	//ou PlaySound("test.wav",NULL,SND_LOOP | SND_ASYNC);

	// Delai pour un temps spécifique
	printf( "Delai de trois secondes\n" );
	sleep( (clock_t)3 * CLOCKS_PER_SEC );
	printf( "C'est fait!\n" );
	sndPlaySound("test2.wav",SND_SYNC);
	//ou PlaySound("test2.wav",NULL,SND_SYNC);

}