Télécharger le cours

Transcription

Télécharger le cours
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Audio Numérique
Leçon n°2 : DirectSound
Gestion de base
Pascal Mignot
[email protected]
Plateforme de développement
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Avantage de DirectSound
DirectX:
• gratuit
• maximum de flexibilité (interface de bas niveau).
• maximum de stabilité (largement testé)
• réactivité aux dernières évolutions technologiques (suit de
très prêt les évolutions du hardware).
• gestion dynamique possible.
Bibliothèques:
• en général payante,
• multi-plateforme
• toujours quelques bugs,
• basée sur DirectSound.
Conclusion: autant avoir sa propre implémentation, sauf si les
utilisations sont élémentaires.
U N IVERSIT É
D E R EIMS
Technologie DirectSound
C H AMP AGN E-A RD EN N E
Permet de jouer des sons:
•
•
avec un temps de latence très faible.
avec un niveau de contrôle bas-niveau sur les ressources.
Principale fonctionnalité:
•
•
•
•
•
jouer des fichiers ou des ressources au format WAV (non
compressé).
jouer des sons simultanément.
appliquer des effets dynamiquement sur des sons (echo,
chorus, ..).
jouer des sons dans environnement 3D.
capturer de son.
Interface de gestion bas-niveau: une gestion haut-niveau est
possible avec l’interface DirectMusic.
Architecture de base de DirectSound
pour la lecture de sons
U N IVERSIT É
D E R EIMS
Propriétés du
buffer secondaire
C H AMP AGN E-A RD EN N E
Buffer
secondaire
Buffer
secondaire
Effets
Effets
Buffer
secondaire
Effets 3D
Propriétés
du buffer
primaire
Emetteur
Recepteur
Buffer Primaire
Son Mixé
•
•
•
le mixage a lieu dans le buffer primaire.
le son est construit dans le buffer primaire avec les propriétés fixées pour la carte son (mono, stéréo, 5.1),
échantillonnage, …
la carte son est virtuelle: les opérations effectuées sur la carte son dépendent des fonctionnalités de celles-ci.
U N IVERSIT É
D E R EIMS
Niveau de coopération
C H AMP AGN E-A RD EN N E
Lorsqu’un périphérique est unique ou susceptible d’être partagé sur un
système, il faut déterminer l’interaction de l’application:
– avec le périphérique.
– avec les autres applications qui utilisent le même périphérique.
•
Mode Exclusif (DSSCL_EXCLUSIVE):
lorsque l’application a le focus, seuls les sons émis par celles-ci sont
entendus (contrôle sur le buffer primaire).
•
Mode Partagé:
les sons en provenance des applications sont mixés dans le buffer
primaire.
– Mode Normal (DSSCL_NORMAL):
partage du périphérique sans contrôle sur le buffer primaire.
– Mode Prioritaire (DSSCL_PRIORITY):
partage du périphérique avec contrôle sur le buffer primaire.
– Mode Primaire (DSSCL_WRITEPRIMARY):
écriture directe dans le buffer primaire (pas de buffer secondaire).
Principe d’utilisation de DirectSound
U N IVERSIT É
D E R EIMS
pour la lecture d’un son
C H AMP AGN E-A RD EN N E
Etapes:
1. Créer l’interface DirectSound
le buffer primaire automatiquement associé.
fixer le niveau de coopération.
2. Créer le (ou les) buffer(s) secondaire(s).
3. L’utilisation d’un buffer secondaire:
•
•
•
charger le contenu du buffer (lock/unlock : pour
verrouiller/déverrouiller le buffer).
fixer les propriétés du buffer (Position, Format,
Fréquence, FX, Pan, Volume).
jouer/arrêter le lecture du son.
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Entête d’une application
DirectSound
// minimum syndical
#include <dsound.h>
#pragma comment(lib,"dsound.lib")
// permet la définition des GUIDs et de certaines fonctions avancées.
#define INITGUID
#include <guiddef.h>
#include <dsconf.h>
#pragma comment(lib,"dxguid.lib")
Rappel: la commande pragma comment(lib,X) permet d’ajouter
automatiquement la bibliothèque X à la liste des bibliothèques avec
lesquels le projet est linké.
Initialisation de l’interface
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
la base
En 2 étapes:
1.
Création de l’interface DirectSound (IDIRECTSOUND8) :
LPDIRECTSOUND8
pDSD = NULL;
DirectSoundCreate8( NULL , &pDSD, NULL);
premier NULL : utiliser le device par défaut (LPCGUID).
pDSD [out] : pointeur sur l’interface DirectSound créé.
dernier NULL : obligatoire.
2.
Fixe le niveau de coopération:
pSDN->SetCooperativeLevel(Hwnd,level)
Hwnd est le handle associé à la fenêtre (renvoyé par CreateWindow).
level est le niveau de coopération (DSSCL_*).
Une fois complétées, on peut créer les buffers secondaires associés et destinés à
accueillir les sons à jouer.
HRESULT
hr = DirectSoundCreate8( NULL , &pSND, NULL);
if( FAILED(hr) ) {
MessageBox(hWnd,"Erreur lors de la creation du peripherique","Erreur" ,MB_OK);
return E_FAIL;
}
// Si on n’appelle pas cette fonction on ne peut pas joueur de son
pSND->SetCooperativeLevel( hWnd ,DSSCL_PRIORITY );
Initialisation de l’interface
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Choix d’un périphérique: périphériques par défaut
Les périphériques systèmes sont identifiés de manière unique grâce à
un GUID (Globally Unique Identifier):
ex: {BD6DD71A-3DEB-11D1-B171-00C04FC20006}
On peut connaître les périphériques par défaut en utilisant:
GetDeviceID(&guidtype,&guid);
guidtype [in] est parmi:
DSDEVID_DefaultPlayback
DSDEVID_DefaultCapture
DSDEVID_DefaultVoicePlayback
DSDEVID_DefaultVoiceCapture
périphérique de lecture.
périphérique de capture.
périphérique de lecture de la voix.
périphérique d’enregistrement de la voix.
guid [out] est le GUID du périphérique utilisé.
La récupération des périphériques disponibles se fait par énumération.
Initialisation de l’interface
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Choix d’un périphérique : énumération
Principe de l’énumération:
1.
Définir une fonction qui sera appelée pour chaque périphérique:
BOOL CALLBACK EnumerationDeviceCallback( LPGUID pGuid,
LPCSTR pDesc, LPCSTR pMode, LPVOID pCont )
à chaque appel, les paramètres de cette fonction contiennent:
pGUID : pointeur vers le GUID du périphérique.
pDesc : nom du périphérique (texte)
pMode : nom du module associé au périphérique (texte)
pCont : pointeur vers des données utilisateur.
la fonction doit renvoyer TRUE pour que l’énumération continue et FALSE
dans le cas contraire (par exemple, lorsque le device recherché
convient).
2.
Appeler DirectSoundEnumerate
DirectSoundEnumerate( EnumerationDeviceCallback , data )
EnumerationDeviceCallback : fonction appelée pour l’énumération.
data : pointeur vers les données utilisateur à passer à la fonction.
Note: l’énumération contient le périphérique par défaut (GUID=NULL). Dans ce
cas, les autres champs en sont pas renseignés.
Initialisation de l’interface
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Choix d’un périphérique : exemple
LPDIRECTSOUND8
pSND;
struct DeviceInfo {
LPGUID Guid;
LPCSTR Description, Module;
};
// fonction d’énumération
BOOL CALLBACK EnumerationDeviceCallback( LPGUID lpGuid,LPCSTR
lpcstrModule, LPVOID lpContext ) {
DeviceInfo
info;
vector<DeviceInfo>
*Device;
info.Guid
= lpGuid;
info.Description
= lpcstrDescription;
info.Module
= lpcstrModule;
Device = reinterpret_cast<vector<DeviceInfo>*>(lpContext);
Device->push_back( info );
return TRUE;
}
lpcstrDescription, LPCSTR
…
// énumération des périphériques
vector<DeviceInfo>
DeviceList;
DirectSoundEnumerate( EnumerationDeviceCallback , reinterpret_cast<LPVOID>(&DeviceList) );
// n’importe quel GUID des périphériques de la liste peut être utilisé avec
// DirectSoundCreate8
…
U N IVERSIT É
D E R EIMS
Capacités d’un device Audio
C H AMP AGN E-A RD EN N E
On utilise la méthode GetCaps du device:
DSCAPS
SndCaps;
pSND->GetCaps (&SndCaps);
Le champs dwSize doit être initialisé à sizeof(DSCAPS) avant l’appel.
Cette structure contient les informations suivantes:
•
quantification: 8/16 bits supportés sur les buffers primaire et secondaires (dwFlags)
DSCAPS_PRIMARY8BIT, DSCAPS_PRIMARY16BIT, DSCAPS_SECONDARY8BIT, DSCAPS_SECONDARY16BIT
•
mode mono/stéréo sur les buffers primaire et secondaires (dwFlags)
DSCAPS_PRIMARYMONO, DSCAPS_PRIMARYSTEREO, DSCAPS_SECONDARYMONO et DSCAPS_SECONDARYSTEREO
•
pas d’échantillonnage minimum et maximum disponible supporté par les buffers secondaires:
dwMinSecondarySampleRate, dwMaxSecondarySampleRate
•
nombre de buffers qui peuvent être mixés simultanément en hardware par la carte:
dwMaxHwMixingAllBuffers,
•
dwMaxHw3DStaticBuffers,
dwMaxHw3DStreamingBuffers
nombre de buffers disponibles (statique, 3D, streaming) au moment de GetCaps:
dwFreeHwMixingAllBuffers,
dwFreeHw3DAllBuffers,
•
dwMaxHwMixingStreamingBuffers
nombre de maximum de buffers 3D (statique, streaming):
dwMaxHw3DAllBuffers,
•
dwMaxHwMixingStaticBuffers,
dwFreeHwMixingStaticBuffers,
dwFreeHw3DStaticBuffers,
dwFreeHwMixingStreamingBuffers
dwFreeHw3DStreamingBuffers
mémoire (en octets) sur la carte son:
dwTotalHwMemBytes (totale) & dwFreeHwMemBytes (libre), dwMaxContigFreeHwMemBytes (contigüe),
dwUnlockTransferRateHwBuffers (vitesse de transfert).
•
pourcentage CPU nécessaire pour mixer les buffers softwares:
dwPlayCpuOverheadSwBuffers.
Fichier son
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
format wav
Le format waveform-audio data (extension wav) avait initialement pour but de stocker des
données au format PCM mono ou stéréo non compressé.
Dans le SDK, les champs suivant de la structure WAVEFORMATEX permet d’en décrire le
contenu:
wFormatTag
nChannels
nSamplesPerSec
nAvgBytesPerSec
nBlockAlign
wBitsPerSample
cbSize
: WAVE_FORMAT_PCM pour du PCM mono ou stéréo.
: 1 pour mono, 2 pour stéréo.
: pas d’échantillonnage en Hz.
: = nSamplesPerSec * nBlockAlign
: = nChannels * wBitsPerSample / 8 (en bytes)
: quantification (en nombre de bits par échantillon).
:0
La WAVEFORMATEX est directement utilisée pour décrire le type de buffer secondaire
souhaité lors de sa création.
Question: combien de seconde dure un fichier stéréo wav de 64 Mo de 16 bits à 44KHz?
Exemple: 16 bits stéréo @ 44.1 KHz
WAVEFORMATEX fmt = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0}
Ce format est flexible et permet de stocker des données compressées (non décrit ici).
cf http://www.tsp.ece.mcgill.ca/MMSP/Documents/AudioFormats/WAVE/WAVE.html
Chargement d’un son
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
la classe CWaveFile
Il n’y a pas de fonction DirectSound permettant de lire des sons au
format wav ou mp3 (par contre, possible avec DirectMusic).
Le SDK propose dans DXUTsound une classe CWaveFile permettant
de lire les fichiers au format wav.
Principales méthodes de la classe CWaveFile pour lire un fichier:
HRESULT Open( file, NULL, WAVEFILE_READ)
pour ouvrir le fichier file en lecture.
DWORD GetSize()
pour connaître le nombre d’octets dans le fichier.
HRESULT ResetFile()
pour revenir au début du fichier.
HRESULT Read( (BYTE*)pBuff, BuffSz, &nRead )
pour lire au plus BuffSz octets et les placer dans le buffer pBuff.
nRead contient au retour le nombre d’octets lu.
HRESULT Close()
pour fermer le fichier.
WAVEFORMATEX* GetFormat()
pour récupérer le format du fichier audio.
Création d’un buffer
secondaire
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
avec la méthode suivant de IDirectSound8:
CreateSoundBuffer(&BuffDesc, &pDSB, NULL)
BuffDesc [in]: structure de type DSBUFFERDESC contenant la
description du buffer à créer, dont les champs principaux sont:
dwBufferBytes : taille en octets du buffer à créer.
dwFlags : capacité particulière de réglage du buffer (voir la table cidessous). Combinaison bitwise de flags DSBCAPS_*:
CTRL3D
3D
CTRLFREQUENCY
fréquence
CTRLFX
effets
CTRLPAN
balance (non 3D)
CTRLVOLUME
volume
Note: chaque capacité consomme
des ressources.
Autres capacités disponibles:
• interaction du buffer avec le
système (cf transparent suivant)
• contrôle 3D (voir la partie son3D).
lpwfxFormat : format des données utilisées dans le buffer au format
WAVEFORMATEX ou WAVEFORMATEXTENSIBLE.
guid3DAlgorithm : algo 3D utilisé pour spatialiser le son (
DS3DALG_DEFAULT si pas de son 3D, voir la partie son3 D).
pDSB [out]: l’adresse sur l’interface IDIRECTSOUNDBUFFER du buffer
secondaire créé.
Création d’un buffer secondaire
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
interaction avec le système
Autres capacités possibles dans dwFlags:
Focus:
•
•
DSBCAPS_GLOBALFOCUS : le buffer est global (le son est entendu même si l’application n’a pas le
focus).
DSBCAPS_STICKYFOCUS : si l’application qui a le focus n’utilise pas DirectSound, le buffer
continue d’être entendu.
Gestion de la mémoire et des voies:
Principe:
•
•
•
•
•
•
Le nombre de voies hardware est limité sur la carte son (SB Audigy 2 = 64).
Par défaut, s’il reste des voies, le buffer est alloué en hardware, sinon le buffer est alloué en
software.
Les buffers alloués en hardware (resp. software) sont mixés en hardware (resp. software).
Mixage hardware = mixage sur la carte son. Mixage software = mixage sur le processeur.
Rappel: sur les cartes son moderne, les buffers (hardware ou software) sont stockés dans la
mémoire système.
Une voie de la carte son est affectée à chaque buffer secondaire.
Options mémoires de création d’un buffer secondaire:
•
•
•
•
DSBCAPS_LOCDEFER : le buffer peut être attribué à une ressource software ou hardware (=
localisation différée). Permet également une gestion dynamique (voir Dynamic Voice
Management).
DSBCAPS_LOCSOFTWARE : le buffer est mixé en software (donc, buffer placé en software).
DSBCAPS_LOCHARDWARE : le buffer est mixé en hardware.
DSBCAPS_STATIC : le buffer est placé en hardware (obsolète: carte son ancienne).
Utilisation du buffer secondaire
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
curseurs
un buffeur secondaire possède 2 curseurs:
– un curseur de lecture (dernière position lue)
– un curseur d’écriture (dernière position écrite, utile pour le streaming).
Méthodes pour les manipuler:
GetCurrentPosition(&PlayCur,&WriteCur)
pour récupérer les valeurs des deux curseurs.
SetCurrentPosition(PlayCur)
pour fixer la valeur du curseur de lecture.
Gestion:
• la gestion des curseur de lecture et d’écriture est automatique.
• lors de la création d’un buffer secondaire, spécifier dans dwFlags:
– DSBCAPS_GETCURRENTPOSITION2 pour s’assurer d’un curseur de
lecture précis.
– DSBCAPS_CTRLPOSITIONNOTIFY pour avoir une notification sur
curseur de lecture (voir la partie sur le streaming).
Utilisation du buffer secondaire
U N IVERSIT É
D E R EIMS
buffer statique ou streaming
C H AMP AGN E-A RD EN N E
un buffer ne peut contenir que des sons au format wav (en général du
PCM).
buffer statique:
on charge le son complet dans le buffer une fois pour toute.
avantage: pas de gestion.
inconvénient: place mémoire importante.
⇒ à privilégier pour les sons répétitifs et cours.
streaming:
le son n’est jamais totalement chargé en mémoire mais chargé et lu
progressivement dans un buffer circulaire de taille fixe.
avantage: consommation mémoire réduite.
inconvénient: gestion périodique pour charger le son à jouer, avec
éventuellement fractionnement de la zone mémoire à remplir.
p1
n1
Offset
Size
p2 n2
p1
Offset
n1 n2
Size
Chargement d’un son
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
dans un buffer secondaire
Le buffer secondaire doit avoir été créé au format du fichier à charger dans le
buffer.
1.
Verrouiller le buffer secondaire avec la méthode:
Lock(Offset, Size, &p1, &n1, &p2, &n2, flags)
Offset [in]: offset depuis le début du buffer.
Size [in]: taille à verrouiller.
p1, n1 [out] : pointeur et taille sur la zone verrouillée.
p2, n2 [out] : idem pour le cas d’un buffer circulaire (ou NULL).
flags:
DSBLOCK_FROMWRITECURSOR : pour utiliser automatiquement comme Offset la position du
curseur d’écriture.
DSBLOCK_ENTIREBUFFER : vérrouille tout le buffer.
2.
3.
Remplir la zone mémoire pointée par p1 (et éventuellement p2).
Déverrouiller le buffer secondaire avec la méthode:
Unlock( p1, n1, p2, n2)
permet de libérer correctement les zones verrouillées et de mettre à jour le pointeur
d’écriture.
p1 (et p2) : exactement les valeurs récupérées par lock.
n1 (et n2) : exactement le nombre d’octets écrits (éventuellement < au n1,n2 initiaux).
Chargement d’un son
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
dans un buffer secondaire (statique)
Exemple
LPDIRECTSOUND8
pSND = NULL;
char
filename[]=“sound.wav”;
LPDIRECTSOUNDBUFFER pDSB = NULL;
CWaveFile
waveFile;
// on suppose que l’initialisation de pSND a eu
// création du buffer secondaire
waveFile.Open( filename, NULL, WAVEFILE_READ );
DSBUFFERDESC
bdesc;
bdesc.dwSize
= sizeof(DSBUFFERDESC);
bdesc.dwFlags
= DSBCAPS_CTRLVOLUME ;
bdesc.dwBufferBytes
= waveFile.GetSize();
bdesc.guid3DAlgorithm
= DS3DALG_DEFAULT;
bdesc.lpwfxFormat
= waveFile.GetFormat();
pSND->CreateSoundBuffer( &ddesc, &pDSB, NULL );
lieu
// contrôle du volume
// taille du fichnier à charger
// format du fichier
// chargement des données depuis le fichier
VOID*
Buff = NULL;
// pointeur vers le buffer vérouillé
DWORD
BuffSz;
// taille effectivement vérouillée
DWORD
nRead = 0;
// nombre d’octets lus dans le fichier
pDSB->Lock(0, waveFile.GetSize(), &Buff, &BuffSz,NULL, NULL, 0 );
waveFile.ResetFile();
waveFile.Read( (BYTE*)Buff, BuffSz, &nRead );
pDSB->Unlock(Buff, nRead, NULL, 0 );
wavefile.Close();
Lecture du son
U N IVERSIT É
D E R EIMS
contenu dans le buffer secondaire
C H AMP AGN E-A RD EN N E
avec les méthodes:
• Play(0,priority,flag)
joue immédiatement le son sélectionné.
priority :
0 si la gestion dynamique de voies n’est pas utilisée.
flag: combinaison bitwise de:
DSBPLAY_LOOPING : répétition automatique.
voir ci-après pour la gestion dynamique de voies.
•
Stop()
arrête la lecture.
le curseur de lecture est placé à l’endroit où la lecture s’est arrêtée.
Conséquence:
– l’appel à Play fait reprendre la lecture à l’endroit où elle s’est arrêtée.
– pour reprendre la lecture du début, utiliser SetCurrentPosition.
Remarque:
•
SetCurrentPosition/GetCurrentPosition peuvent être appelé pendant
•
la lecture pour changer/lire la position courant du curseur de lecture.
si SetPriorityLevel n’a pas été appelé, le son ne sera pas entendu même si
Play renvoie S_OK.
Gestion dynamique de voies
U N IVERSIT É
D E R EIMS
DirectSound permet une gestion dynamique des voies hardware
(Dynamic Voice Management) de la carte son.
C H AMP AGN E-A RD EN N E
Utilisation:
•
Tous les buffers à gérer dynamiquement doivent être créés avec DSBCAPS_LOCDEFER.
– Seuls ceux-ci sont candidats pour libérer les ressources.
– C’est au moment du Play que sera déterminé si ce buffer secondaire est joué en
hardware ou en software.
•
le flag de Play contient des informations additionnelles pour tenter de jouer le son
en hardware:
– pour forcer le mode avec lequel le buffer sera joué:
DSBPLAY_LOCHARDWARE : pour forcer le mode hardware.
DSBPLAY_LOCSOFTWARE : pour forcer le mode software.
– pour choisir la stratégie de choix de libération d’un buffer hardware
DSBPLAY_TERMINATEBY_TIME : choisir le buffer pour lequel il reste le moins de temps à jouer
(exclue les buffers joués en boucle).
DSBPLAY_TERMINATEBY_DISTANCE : choisir un buffer créé avec le flag
DSBCAPS_MUTE3DATMAXDISTANCE et pour lequel le son se trouve au delà de la distance
maximum. S’il n’y en a pas, la méthode échoue.
DSBPLAY_TERMINATEBY_PRIORITY (peut être combiné avec l’un des deux modes précédents qui
ne servent qu’en cas d’égalité): utiliser le paramètre de priorité passé à Play (0 = priorité la plus
faible, 0xffffffff = priorité la plus forte). Le son de plus faible priorité est terminé immédiatement.
•
Remarque:
–
–
en cas d’échec, le son est joué en software, sauf si le mode hardware est forcé. Dans ce cas, la
méthode Play échoue.
voir aussi la méthode AcquireResources, qui permet d’allouer des ressources avant le Play. Elle
possède des arguments supplémentaires permettant d’allouer les ressources nécessaires aux effets.
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Réglages basique
sur un buffer secondaire
Méthode permettant de régler les propriétes du buffer:
• SetVolume(vol) : fixe le volume
où vol est l’atténuation en 1OOème de dB (-100=-1dB, -10000=-100dB), définie de
DSBVOLUME_MAX (0) à DSBVOLUME_MIN (-10000).
Le buffer doit avec été créé avec la capacité DSBCAPS_VOLUME.
• SetPan(pan) : fixe la balance gauche/droite
où pan va de -10000 (DSBPAN_LEFT) à 10000 (DSBPAN_RIGHT), centré à 0
(DSBPAN_CENTER).
Le buffer doit avec été créé avec la capacité DSBCAPS_PAN.
• SetFrequency(freq) : fréquence
joue à une fréquence freq différente de sa fréquence d’échantillonnage originale.
Conséquence: le pitch et la durée du son sont changés.
Le buffer doit avec été créé avec la capacité DSBCAPS_FREQUENCY.
Remarques:
– DSBFREQUENCY_ORIGINAL rétablit la fréquence originale.
– le fréquence doit être supportée (i.e. entre wMinSecondarySampleRate et
dwMaxSecondarySampleRate).
– certains OS ne permettent pas de dépasser 100KHz.
Interface IDIRECTSOUNDBUFFER8
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
sur un buffer secondaire
Par défaut, la méthode CreateSoundBuffer crée un pointeur sur une interface
de type IDIRECTSOUNDBUFFER qui est commune aux buffers primaire et
secondaires.
Certaines fonctionnalités caractéristiques des buffers secondaires ne sont pas
disponibles à travers cette interface mais avec l’interface
IDIRECTSOUNDBUFFER8 (qu’il est donc possible de récupérer pour un
buffer secondaire).
Récupérer un pointeur sur l’interface IDIRECTSOUNDBUFFER8 à partir
d’un pointeur sur l’interface IDIRECTSOUNDBUFFER:
// Initialiser l’interface COM (une seule fois dans tout l’application)
CoInitialize( NULL );
…
LPDIRECTSOUNDBUFFER
pDSB = NULL;
// initialiser le buffer secondaire pDSB ici
LPDIRECTSOUNDBUFFER8
pDSB8 = NULL;
pDSB->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*)&pDSB8 );
…
// A la fin de l’application
CoUninitialize();
Rappel: pensez au Release() sur les deux pointeurs.
Effets de base sur un buffer secondaire
U N IVERSIT É
D E R EIMS
Effets disponibles (1)
C H AMP AGN E-A RD EN N E
8 effets sont intégrés de base dans DirectSound:
Chorus : doublement de la voie créé en répétant le son original avec un petit délai.
Compressor : reduction des fluctuations au-delà d’une certaine amplitude.
Distortion : ajout d’harmoniques au son de façon à saturer les niveaux les plus hauts.
Echo : répétition du son après un délai, avec réduction du volume. Le son répété est de
nouveau répété.
Flanger : echo pour lequel le delai entre le signal original et son écho est très court et varie avec
le temps.
Gargle : modulation de l’amplitude du signal.
ParamEq : équaliseur paramétrique (permet d’amplifier ou d’atténuer certaines fréquences).
WavesReverb : réverbération conçues pour la musique.
Remarques:
• Les effets ne sont disponible QUE sur un buffer secondaire (donc récupérer un
pointeur IDIRECTSOUNDBUFFER8 sur le buffer secondaire).
• Le buffer sur lequel l’effet est appliqué doit être arrêté pour pouvoir créer
l’effet.
• Tous les effets sont appliqués en software, et ceci même si la carte son les supporte
en hardware.
• Le buffer doit avoir une durée d’au moins 150ms de données (DSBSIZE_FX_MIN).
Demonstration: voir l’application SoundFx dans le SDK.
Effets de base sur un buffer
secondaire
U N IVERSIT É
D E R EIMS
Définition d’un effet (1/3)
C H AMP AGN E-A RD EN N E
Guid/Interface/Structure/IID associés à chaque effets:
GUID
Interface
Structure
Interface ID
GUID_DSFX_STANDARD_CHORUS
IDirectSoundFXChorus8
DSFXChorus
IID_IDirectSoundFXChorus8
GUID_DSFX_STANDARD_COMPRESSOR
IDirectSoundFXCompressor8
DSFXCompressor
IID_IDirectSoundFXCompressor8
GUID_DSFX_STANDARD_DISTORTION
IDirectSoundFXDistortion8
DSFXDistortion
IID_IDirectSoundFXDistortion8
GUID_DSFX_STANDARD_ECHO
IDirectSoundFXEcho8
DSFXEcho
IID_IDirectSoundFXEcho8
GUID_DSFX_STANDARD_FLANGER
IDirectSoundFXFlanger8
DSFXFlanger
IID_IDirectSoundFXFlanger8
GUID_DSFX_STANDARD_GARGLE
IDirectSoundFXGargle8
DSFXGargle
IID_IDirectSoundFXGargle8
GUID_DSFX_STANDARD_PARAMEQ
IDirectSoundFXParamEq8
DSFXParamEq
IID_IDirectSoundFXParamEq8
GUID_DSFX_WAVES_REVERB
IDirectSoundFXWavesReverb8
DSFXWavesReverb
IID_IDirectSoundFXWavesReverb8
Structure à remplir pour définir un effet dans un buffer secondaire:
structures DSEFFECTDESC:
la structure contient principalement les champs suivants:
dwSize = sizeof(DSEFFECTDESC);
dwFlags : 0 ou
DSFX_LOCHARDWARE : pour forcer l’effet en hardware (pas d’avantage à le faire).
DSFX_LOCSOFTWARE : pour forcer l’effet en software.
guidDSFXClass : classe de l’effet (voir table ci-dessous)
Effets de base sur un buffer secondaire
Définition d’un effet (2/3)
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Pour définir une suite de n effets, il faut:
1. Fixer les effets à utiliser:
SetFX( n , desc, codes )
n : nombres d’effets
desc : tableau de n structures de type DSEFFECTDESC (à remplir) décrivant la suite d’effets
à appliquer dans l’ordre.
codes : tableau de n DWORDs contenant au retour le status de création de l’effet (DSFXR_x
où x est parmi LOCHARDWARE, LOCSOFTWARE, UNALLOCATED, FAILED, PRESENT).
Remarque:
• SetFX(0,NULL,NULL) désactive les effets sur le buffer.
• pour utiliser SetFX, il faut récupérer l’interface IDIRECTSOUNDBUFFER8 associée
au buffer secondaire.
2. Récupération du pointeur sur l’interface de chaque effet:
GetObjectInPath( guid , i, iid, (LPVOID*)&pEff );
i [in]: index de l’effet dans la table.
guid [in]: guid du ième effet.
iid [in]: iid du ième effet.
pEff [out]: pointeur sur l’interface de l’effet.
3. Configuration de l’effet
2 méthodes sont disponibles sur chaque effet:
GetAllParameter: pour récupérer, dans la structure DSFX* associée, la configuration
courante de l’effet.
SetAllParameter: pour fixer, à partir de la structure DSFX* associée, la configuration
de l’effet.
Effets de base sur un buffer secondaire
U N IVERSIT É
D E R EIMS
Définition d’un effet (3/3)
C H AMP AGN E-A RD EN N E
Exemple: définition de l’effet chorus sur un buffer secondaire
// Initialise l’interface COM (une seule fois dans tout l’application)
CoInitialize( NULL );
…
LPDIRECTSOUNDBUFFER
pDSB = NULL;
// créer ici le buffer secondaire avec l’option DSBCAPS_CTRLFX
// récupération de l’interface DIRECTSOUNDBUFFER8
LPDIRECTSOUNDBUFFER8
pDSB8 = NULL;
pDSB->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*)&pDSB8 );
// Définition de l’effet sur le buffer
DWORD
code; // code de retour (à tester)
DSEFFECTDESC
Desc = {sizeof(DSEFFECTDESC), 0, GUID_DSFX_STANDARD_CHORUS, 0, 0 };
pDSB8->SetFX( 1, &Desc , &code);
// récupération de l’interface sur l’effet
LPDIRECTSOUNDFXCHORUS8
pChorus = NULL;
DSFXChorus
ChorusData;
pDSB8->GetObjectInPath( GUID_DSFX_STANDARD_ECHO, 0, IID_IDirectSoundFXEcho8,
(LPVOID*)&pChorus);
// changement
pChorus->GetAllParameters(&ChorusData);
ChorusData.fWetDryMix = DSFXECHO_WETDRYMIX_MAX;
ChorusData.fDepth = 100;
pChorus->SetAllParameters(&ChorusData);
U N IVERSIT É
D E R EIMS
Etat d’un buffer secondaire
C H AMP AGN E-A RD EN N E
méthode GetStatus(&status)
au retour, status contient le statut courant du buffer.
DSBSTATUS_BUFFERLOST
buffer perdu: doit être restoré avant d’être lu ou verrouillé.
DSBSTATUS_LOOPING
lecture en boucle.
DSBSTATUS_PLAYING
lecture en cours.
DSBSTATUS_LOCSOFTWARE
buffer en mode software (LOCDEFER).
DSBSTATUS_LOCHARDWARE
buffer en mode hardware (LOCDEFER).
DSBSTATUS_TERMINATED
le buffer a subit une arret forcé (LOCDEFER).
Remarques:
méthode principalement utilisée pour deux raisons:
– pour tester la perte d’un buffer.
– pour tester l’état d’un buffer dans le cadre d’une gestion
dynamique des voies.
Gestion d’un buffer perdu
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Exemple de cas de perte d’un buffer:
si une application en mode coopératif passe en arrière-plan, tous ses
buffers sont alors perdus pour permettre à l’application du premier
plan l’écriture directe dans le buffer primaire.
Détection:
–
–
GetStatus(…) & DSBSTATUS_BUFFERLOST est vrai.
Play(…), Lock(…) renvoient DSERR_BUFFERLOST.
Restoration d’un buffer perdu:
1.
2.
faire appel à la méthode Restore() sur le buffer pour réallouer la
mémoire.
recopier le contenu du buffer (considérer que le contenu d’un buffer
perdu est perdu).
HRESULT h;
DWORD
dwStatus;
pDSB->GetStatus( &dwStatus );
if( dwStatus & DSBSTATUS_BUFFERLOST ) {
while( ( hr = pDSBuffer->Restore() ) == DSERR_BUFFERLOST )
Sleep( 10 );
// recopier ici le contenu du buffer perdu
}
Notification
U N IVERSIT É
D E R EIMS
1. Déclaration des notifications
C H AMP AGN E-A RD EN N E
Notification = déclenchement d’un évènement lorsqu’une position déterminée est
atteinte par le curseur de lecture dans le buffer (préférable à l’utilisation de
GetStatus).
Mise en place:
1. Récupérer l’interface IDirectSoundNotify8 (appel COM avec
IID_IDirectSoundNotify) sur le buffer.
2. Pour chaque notification attendu, remplir une structure
DSBPOSITIONNOTIFY:
dwOffset : offset dans le fichier qui déclenchera l’évènement lorsque le curseur de
lecture l’atteindra.
hEventNotify : handle associé à l’événement (crée avec CreateEvent, voir ci-après)
3. Appeler la méthode suivante de IDirectSoundNotify8:
SetNotificationPositions( nNot, NotArray )
nNot : nombre de notifications à installer sur le buffer.
NotArray : tableau de nNot structure de type DSBPOSITIONOTIFY.
afin de mettre en place l’ensemble des notifications.
Remarques:
•
•
SetNotificationPositions(0,NULL) permet de désactiver les notifications sur le
buffer.
le buffer doit être arrêté lors de l’installation des notifications.
Notification
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
•
2. Gestion d’évènements
Création d’évènement (pour remplir le tableau DSBPOSITIONNOTIFY)
h = CreateEvent(NULL, auto, init, name)
h : handle de l’événement créé.
auto : reset manuel (TRUE) / automatique (FALSE)
manuel = nécessite l’appel à ResetEvent(h) pour que l’événement soit considéré comme non signalé.
init : valeur initiale : signalé (TRUE) / non signalé (FALSE).
•
Boucle de message modifiée pour la lecture des événements supplémentaires:
// EventHandleArray = tableau des handles dont on attend la notification
r = MsgWaitForMultipleObjects( n, &EventHandleArray,FALSE, INFINITE, QS_ALLEVENTS );
switch( r ) {
case WAIT_OBJECT_0 + i: // du handle numéro i dans le EventHandleArray
// gestion de cet évènement
break;
case WAIT_OBJECT_0 + n: // traitement des autres événements
// insérer ici la boucle de traitement des messages
break;
}
•
Attente passive d’un évènement:
r = WaitForSingleObject(h, timeout)
h : handle de l’événement
timeout : attente avant retour forcé de la fonction (0=retour immédiat, n=nombre de ms, INFINITE=infini).
r : WAIT_OBJECT_0 = l’évenement est survenu, WAIT_TIMEOUT = retour après un timeout.
Attention: dans le cas d’une application multithread, voir les options de CreateEvent.
•
Destruction d’un événement:
CloseHandle(h) où h est le handle obtenu par CreateEvent.
Notification
U N IVERSIT É
D E R EIMS
3. Exemple
C H AMP AGN E-A RD EN N E
Création des événements associés
aux notifications et initialisation de
la table de notifications
// pDSB : pointeur sur le buffer
// BuffSize
: taille du buffer
// création de l’évenement
LPDIRECTSOUNDNOTIFY
pNot = NULL;
HANDLE NEvent;
NEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
// récupération de l’interface de gestion
// des notifications
pDSB->QueryInterface( IID_IDirectSoundNotify,
(VOID**)&pNot );
// création de la table de notifications
const int
nNot = 10;
uint
nSize = BuffSize / nNot;
DSBPOSITIONNOTIFY
NotPos[nNot];
for( INT i=0; i<nNot; i++ ) {
PosNot[i].dwOffset
= i*nSize;
PosNot[i].hEventNotify = NEvent;
}
// fixe les positions de notification
pNOT->SetNotificationPositions( nNot, PosNot );
Traitement des événements
associés aux notifications et des
messages Windows classiques
Done = FALSE;
while( !Done ) {
// 1
: nombre d’évenement
// &NEvent
: tableau des évenements
DWORD dwResult = MsgWaitForMultipleObjects( 1,
&NEvent, FALSE, INFINITE, QS_ALLEVENTS );
switch( dwResult ) {
case WAIT_OBJECT_0 + 0:
// NEvent est signalé (premier évenement)
// traitement de l’événement NEvent
break;
case WAIT_OBJECT_0 + 1:
// messages Windows classiques
// traitement classique des messages
// Done = TRUE si le message est WM_QUIT
break;
}
}
Notification
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
4. Problème potentiel avec les notifications
Pour un buffer hardware, les notifications sont gérés à travers le driver:
certains drivers ne gèrent pas les notifications de manière fiable, et
peuvent générer de fausses notifications.
Solutions:
• appeler la méthode GetCurrentPosition pour vérifier la validité
de la notification.
• utiliser un buffer software: dans ce cas, les notifications sont
toujours correctes.
inconvénient majeur: le mixage et l’application d’effet se font en
software (nuit à la performance).
•
utiliser plutôt des timers si la notification doit arriver à intervalle
régulier (comme dans le cas du streaming).
Remarque: la gestion des notifications dans le cas d’une application
multi-threads demande une attention particulière (à commencer par
les attributs de sécurité dans CreateEvent).
Gestion d’un timer
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Gestion:
SetTimer( h, id, lapse, tfunc)
h : handle de la fenêtre auquel le timer est associé.
id : numéro (UINT) associé au timer. Si le timer existe déjà, il est remplacé.
lapse : temps à attendre avant le déclenchement du timer en ms.
tfunc :
NULL : un message WM_TIMER est posté à l’expiration du timer (donc à intégrer à la boucle de
traitement des messages de h). L’id du timer se trouve dans wParam.
(TIMERPROC)MyTimerProc : fonction appelée (par DispatchMessage) lors de l’expiration du timer.
Une fonction peut différente peut être affectée par timer.
KillTimer( h, id )
détruire le timer de numéro id associé à fenêtre de handle h.
Fonction utilisateur:
VOID CALLBACK MyTimerProc( HWND h, UINT uMsg, UINT_PTR id, DWORD time )
h : handle de la fenêtre auquel le timer est associé.
uMsg : message (= WM_TIMER)
id : identification du timer.
time : valeur de GetTickCount du moment où le timer a expiré (= ms écoulés depuis le
dernier boot).
le paramètre id (et éventuellement h) permet d’utiliser la même fonction pour gérer plusieurs retour
de timer.
Problème potentiel: si la taille du buffer est trop petite, la précision du timer peut se révéler
insuffisante.
Streaming
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Principe de remplissage du buffer
Rappel: pour les sons de durée importante (dialogue, musique), on utilise un petit buffer
circulaire (quelques secondes) que l’on charge au fur et à mesure des besoins.
Exemple:
Première
mise-à-jour
Initialisation
Mises-à-jour
suivantes
cplay
cplay
cplay
d-ε
d
crec
crec
Le curseur de lecture Cplay et le
curseur d’enregistrement Crec
sont tous les deux au début du
buffer.
Le buffer complet est rempli avec
le début du son.
cplay
cplay
d-ε
d-ε
crec
crec
Lorsque d(Cplay,Crec) ≥ d, on
copie les d-ε octets suivants
dans le buffer à partir de Crec.
Remarques:
• le buffer est joué en mode DSBPLAY_LOOPING.
• en fin de la lecture (la fin du fichier est atteinte):
1. il faut continuer à écrire de 0 jusqu’à ce que Crec atteigne la fin du buffer.
2. Lorsque Crec dépasse la fin du buffer, déactiver le mode DSBPLAY_LOOPING.
crec
Pour la deuxième mise à jour,
le buffer d’écriture est coupé en
deux.
Paramétrage:
d = 20% de la taille du buffer (par exemple).
ε = 32 bits (imprécision du driver sur la
position de Cplay).
Streaming
U N IVERSIT É
D E R EIMS
Gestion du remplissage
C H AMP AGN E-A RD EN N E
•
A partir de notification:
Placer la notification sur Cplay+d.
Voir la partie sur les notifications pour voir les inconvénients de cette
méthode.
•
A partir de timer:
Les caractéristiques du buffer sont:
n = nombre de canaux.
f = fréquence d’échantillonnage.
q = nombre de bits par valeur (quantification).
Avec un buffer de taille b, on peut stocker s=b/nfq secondes.
Attendre que p% du buffer s’écoule, c’est attendre:
st = s.p% secondes
Donc, dans le cas d’une lecture continue, on peut fixer le timer à st.
Remarques:
Les deux méthodes sont valables mais celle utilisant les timers est plus
simple à mettre en place.
U N IVERSIT É
D E R EIMS
Partage d’un buffer secondaire
C H AMP AGN E-A RD EN N E
Il est possible pour deux buffers secondaires différents de partager la même zone
mémoire avec la méthode suivante de IDirectSound8:
DuplicateSoundBuffer( OriginalBuff, &CopyBuff)
crée une copie du buffer secondaire OriginalBuff appelée CopyBuff.
OriginalBuff ne doit pas avoir la capacité DSBCAPS_CTRLFX.
Différent d’un AddRef:
– Initialement, les paramètres de CopyBuff sont les mêmes que ceux d’ OriginalBuff.
– chaque buffer a ses propres paramètres (volume, balance, …) qui peuvent être
changés indépendamment sans perturber l’autre buffer.
– chaque buffer a ses propres curseurs de lecture et d’écriture (Play/Stop).
– seule la mémoire du buffer est partagée.
Note: le mémoire du buffer n’est libéré qu’une fois le dernier buffer secondaire
l’utilisant est libéré.
Applications (non limitatif):
• pour des sons ayant des comportements exclusifs (bruit de l’arme du joueur,
…).
• pour partager des sons très court dans un même buffer (à conjuguer avec des
notifications).
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Accès et manipulation
du buffer primaire
En général, on ne manipule pas directement le buffer primaire. Il est malgré
tout possible d’y accéder.
Pointeur sur le buffer primaire:
utiliser la méthode CreateSoundBuffer avec la capacité
DSBCAPS_PRIMARYBUFFER, dwBufferBytes=0 (la taille du buffer primaire
n’est pas géré pas l’utilisateur), et lpwfxFormat = NULL (ne pas spécifier de
format à la création).
Changer le format du buffer primaire (de mixage)
utiliser la méthode SetFormat(&fmt) où fmt est de type WAVEFORMATEX.
doit être appelé avant la création de tout buffer secondaire.
Autres opérations disponibles
Stop/Play : pour couper/relancer le son.
Lock/Unlock : pour verrouiller/déverrouiller le buffer primaire.
SetVolume/SetPan/SetFrequency : pour fixer le son/balance/fréquence
principal de l’application.
Attention: bien lire la documentation de ces méthodes qui ont souvent un
comportement particulier sur le buffer primaire.
Capture Audio
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
principe
En 4 étapes:
1. Enumérer les devices disponibles
DirectSoundCaptureEnumerate (pour choisir) ou récupérer le
device de capture par défaut avec GetDeviceID.
2. Créer un pointeur sur l’interface de capture
IDirectSoundCapture8 avec la fonction
DirectSoundCaptureCreate8.
3. Créer un pointeur sur l’interface du buffer de capture
IDirectSoundCaptureBuffer8 avec la méthode
CreateCaptureBuffer de IDirectSoundCapture8.
4. Utiliser les méthodes Start/Stop de
IDirectSoundCaptureBuffer8.
Remarque:
• l’interface IDirectSoundFullDuplex8 permet de faire du full duplex.
• des effets spécifiques pour la capture existent et permettent
d’éliminer l’écho ou les bruits de fond.
Capture Audio
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
devices de capture disponibles
Récupération du GUID du périphérique de capture:
1.
device par défaut:
utiliser GetDeviceID avec DSDEVID_DefaultCapture ou
DSDEVID_DefaultVoiceCapture.
utiliser NULL comme synonyme de DSDEVID_DefaultCapture.
2.
énumération:
comme pour la lecture, il faut écrire une fonction de type
EnumerationDeviceCallback (même prototype) et faire appel à la
fonction DirectSoundCaptureEnumerate pour parcourir l’ensemble des
device de capture disponibles.
DirectSoundCaptureEnumerate( EnumerationDeviceCallback , data )
EnumerationDeviceCallback : fonction appelée pour l’énumération.
data
: pointeur vers les données utilisateur à passer à la fonction.
Création de l’interface sur le device de capture: une fois le device
choisi, créer l’interface de capture avec:
DirectSoundCaptureCreate8(guid, &pREC, NULL)
guid [in]: est le guid obtenu ci-dessus.
pREC [out]: un pointeur sur l’interface IDIRECTSOUNDCAPTURE8.
Capture Audio
U N IVERSIT É
D E R EIMS
capacité du device de capture
C H AMP AGN E-A RD EN N E
On utilise la méthode GetCaps du device de capture:
DSCCAPS RecCaps;
pREC->GetCaps (&SndCaps);
Le champs dwSize doit être initialisé à sizeof(DSCCAPS) avant l’appel.
Cette structure contient les informations suivantes:
• des informations sur le driver (dwFlags) :
– DSCCAPS_EMULDRIVER : pas de driver de capture DirectSound.
– DSCCAPS_MULTIPLECAPTURE : le driver peut supporter plusieurs capture en même
temps.
•
•
les formats de capture supporté (dwFormats) : contient une combinaison bitwise de
WAVE_FORMAT_xyz avec:
x
Fréquence
y
canaux
z
Quantification
1
11.025 kHz
M
mono
08
8 bits
2
22.050 kHz
S
stéréo
16
16 bits
4
44.100 kHz
Exemples:
WAVE_FORMAT_1M08 = 11.025 kHz, mono, 8-bit
WAVE_FORMAT_4S16 = 44.1 kHz, stereo, 16-bit
le nombre de canaux (dwChannels) : 1=mono, 2=stéreo, ...
Capture Audio
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
création du buffer de capture
Avec la méthode suivante du device de capture:
CreateCaptureBuffer( &BuffDesc, &pACB, NULL)
BuffDesc [in]: structure de type DSCBUFFERDESC décrivant le buffer
de capture à créer dont les champs principaux sont:
dwFlags :
DSCBCAPS_CTRLFX : pour autoriser les effets.
DSCBCAPS_WAVEMAPPED : utiliser le wave mapper (=convertisseur
chargeant les codecs software nécessaires) si le format
(lpwfxFormat) demandé n’est pas supporté.
dwBufferBytes : taille (en octets) du buffer à créer.
lpwfxFormat : pointeur sur une structure de type WAVEFORMATEX
décrivant le format de capture des données (voir format wav).
dwFXCount : nombre d’élément dans le tableau de DSCEFFECTDESC
décrivant la liste d’effets à appliquer (0 si DSCBCAPS_CTRLFX n’est pas
présent dans dwFlags).
lpDSCFXDesc : pointeur sur le tableau de DSCEFFECTDESC.
pACB [out]: pointeur sur l’interface IDirectSoundCaptureBuffer de
manipulation du buffer de capture créé.
Note: les effets sont associés dès la création du buffer.
Capture Audio
U N IVERSIT É
D E R EIMS
gestion des effets à la création
C H AMP AGN E-A RD EN N E
Structure DSCEFFECTDESC de description des effets de capture:
dwSize : sizeof(DSCBUFFERDESC)
dwFlags : mode pour l’effet
DSCFX_LOCHARDWARE : effet hardware
DSCFX_LOCSOFTWARE : effet software
au retour de CreateCaptureBuffer, ce champs indique comment l’effet à été
effectivement créé.
guidDSCFXClass : effet souhaité
GUID_DSCFX_CLASS_AEC : élimination de l’écho.
GUID_DSCFX_CLASS_NS : suppression du bruit.
guidDSCFXInstance : choix de l’instance de l’effet
SW Microsoft
système
élimination d’écho
GUID_DSCFX_MS_AEC
GUID_DSCFX_SYSTEM_AEC
suppression de bruit
GUID_DSCFX_MS_NS
GUID_DSCFX_SYSTEM_NS
Important:
les effets ne sont utilisables qu’avec l’interface IDirectSoundCaptureBuffer8:
LPDIRECTSOUNDCAPTURE8 pACB8 = NULL;
pACB->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)&pACB8 );
Capture Audio
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Gestion du buffer de capture
Fonctionnement quasiment identique à un buffer secondaire.
Gestion courante:
Start(flag) : commencer la capture.
flag: 0 ou DSCBSTART_LOOPING pour enregistrement en boucle.
Stop() : arret de la capture.
Lock/Unlock (même syntaxe) : pour verrouiller le buffer et y lire les données
capturées.
GetCurrentPosition(&RecCur,&ReadCur) : pour lire la position du curseur
d’enregistrement et de lecture.
GetStatus(&s) : pour lire le statut s du buffer (combinaison bitwise de
DSCBSTATUS_CAPTURING si capture en cours, DSCBSTATUS_LOOPING si en
boucle).
Gestion des effets (IDirectSoundCaptureBuffer8):
GetObjectInPath: pour récupérer le pointeur sur l’interface de l’effet (puis
GetAllParameters/SetAllParameters pour configurer l’effet).
Remarque:
• si on ne fait pas de streaming (enregistrement en boucle), la durée de l’enregistrement
est limité à la taille du buffer.
• sous XP, voir aussi l’interface IDirectSoundFullDuplex8 (FullDuplex).
Audio Haute-Résolution
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Extension du WAVEFORMAT (WAVEFORMATEXTENSIBLE)
– utilisation de fréquence au-delà de 44kHz ou au delà de 16bits
– multicanal (surround, 5.1, 6.1, 7.1, hémisphérique): 18 canaux max.
Utiliser la structure WAVEFORMATEXTENSIBLE lors de la création du
buffer primaire.
Voir aussi:
MSDN : Multiple Channel Audio Data and WAVE Files.
http://www.microsoft.com/whdc/device/audio/multichaud.mspx
WaveInOpen
DirectSndCapture
WaveOutOpen
DirectSndPlayback
Bits
EX
EXTENSIBLE
EX
EXTENSIBLE
EX
EXTENSIBLE
EX
EXTENSIBLE
8
PCM8
PCM8
OK
OK
HF
HF
HF
HF
16
OK
OK
OK
OK
HF
HF
HF
HF
24
N/A
OK
N/A
OK
N/A
Trunc
N/A
Trunc
32
N/A
OK
N/A
OK
N/A
Trunc
N/A
Trunc
•
•
•
“HF” 24 bit alternate interface is always used. Capture uses highest sample rate.
PCM8 HF interface is used because Windows supports PCM8 rather than 8 bit PCM.
Trunc – Playback uses the 24 bit alt interface but all values are truncated to 16 bits.
EAX & Effets
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Filtres Haute-Qualités EAX4
EAX4 offre des filtres audio « qualité studio »:
•
Automatic Gain Control Compressor : ajustement automatique du
niveau sonore pour garder un niveau constant.
• Autowah : pedale Wah-Wah
• Chorus : effet de choeur.
• Distortion : saturation du signal et ajout d’harmoniques.
• Echo : mouvement et extension spatiale.
• Equalizer : equaliseur 4 bandes.
• Flanger : effet de tunnel ou de wooshing (passage d’un jet).
• Frequency Shifter : translation en fréquence.
• Vocal Morpher : filtre 4 bandes spécialisés pour la voie.
• Pitch Shifter : translation en fréquence avec conservation des
harmoniques.
• Ring Modulator : effet de trémolo.
Voir la documentation pour les paramètres associés à ces filtres.
EAX & Effets
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Ressources Hardware
Ces remarques s’appliquent aux cartes supportant EAX4
4 slots hardwares sont présents sur la carte.
• permet de gérer 4 effets différents simultanément sur les buffers
hardware.
• des slots fixes: Slot0 = Reverb, Slot1 = Chorus (limitation driver).
• au plus 2 slots associables à une source (limitation driver).
Au niveau optimisation:
• changer l’effet contenu dans un slot est lent.
• changer le paramétrage d’un effet est rapide (1ms).
• une application peut verrouiller des slots pour être sur que l’effet
qu’il contient ne changera pas.
Gestion des ressources:
comme pour le gestionnaire de ressource hardware de
DirectSound (DEFER)
EAX & Effets
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Environnement de programmation
SDK: voir le site développeur de Creative.
EAX2 : libre
EAX4 : libre mais réservé aux entreprises (secrets
industriels)
Compilation:
– header:
eax.h
– bibliothèque: eaxguid.lib
Principaux objets EAX:
– Slotn (n=0,1,2,3) : les 4 slots hardware utilisables.
– Context : propriétés globales de l’auditeur.
– Source : propriétés des sources.
EAX & Effets
Support d’EAX
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Accès à l’ensemble de propriétés:
•
Créer une interface IDirectSound3DBuffer8 (pDS3D)
il doit être un buffer hardware 3D (DSBCAPS_CTRL3D | DSBCAPS_LOCHARDWARE).
il n’est pas nécessaire de la conserver.
•
Appeler la méthode QueryInterface sur IKsPropertySet.
façon qu’ont les drivers d’exposer leurs capacités matérielles à DS.
QueryInterface renvoie:
•
•
succès si des capacités sont disponibles.
un pointeur (pPSET) sur l’ensemble de propriétés.
Test des propriétés EAX disponibles sur IKsPropertySet:
appeler la méthode QuerySupport(guid,prop,&supp)
•
guid : identification de la fonctionnalité offerte
EAXPROPERTYID_EAX40_x où x est pami Context, FXSlotn, Source.
•
prop : pour support éventuellement partiel sur les paramètres.
EAXx_ALLPARAMETERS où x comme ci-dessus (mais en majuscule).
le support est effectif si les flags KSPROPERTY_SUPPORT_GET |
KSPROPERTY_SUPPORT_SET sont activés dans supp.
EAX & Effets
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Contrôle et utilisation pratique
L’interface IKsPropertySet expose les méthodes:
– Set : pour fixer le propriété du GUID spécifié.
– Get : pour récupérer le propriété du GUID spécifié.
Exemples:
EAXPROPERTYID_EAX40_Slotn permet de:
– charger l’effet souhaité dans le slot n.
– fixer/lire les caractéristiques du filtre placé dans le slot n.
EAXPROPERTYID_EAX40_Source permet de:
– indiquer quels sont slots actifs pour cette source.
En pratique:
– Il y a un IKsPropertySet par buffer hardware.
– On affecte les effets dans les slots une fois pour toute.
– Chaque buffer indique quels sont les slots qu’il utilise (≤2) ainsi que
ses paramètres de configuration.
DirectSound
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
déboggage
Dans la configuration de DirectX dans le
panneau de configuration, il est
possible d’effectuer les réglages cicontre.
Debug Output Level: quantité de
traces envoyée dans la fenêtre
output en mode debug.
Multimedia Properties: ouverture du
control panel « sound and audio
device ».
Sound Playback/Sound Recording:
permet de consulter le statut des
devices:
Full/Standard/Basic acceleration
Emulation
(voir ci-après)
DirectSound
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Réglage de l’accelération matérielle
Le réglage de l’accelération matérielle se fait dans:
Control Panel/Sound and Audio Device/[Audio]/Advanced/[Performance]
Deux paramètres réglables:
Harware Acceleration : niveau d’utilisation des capacités matérielles de la carte.
Sample rate conversion quality: qualité de l’échantillonnage utilisé pour les conversions.
Le niveau d’accélération a un impact direct sur les capacités
matérielles visibles depuis les applications:
Full : accélération DirectSound complète
–
–
toutes les capacités matérielles de la carte sont utilisées.
accès aux ensembles de propriétés (extensions IKsPropertySet)
Standard : accélération classique.
–
–
accélération matérielle sur les buffers secondaires.
toutes les accélérations spécifiques à la carte sont désactivées
(i.e. l’accès au IKsPropertySet désactivé).
Basic : accélération de base
–
–
pas d’accélération matérielle sur les buffers secondaires.
mode à utiliser pour simuler les cartes sans accélération
matérielle
None: émulation
–
–
–
tout est fait sur le CPU (y compris le mixage).
résultat envoyé sur le Win32 waveform-audio device.
en général, très lent.
Lectures et programmes
U N IVERSIT É
D E R EIMS
C H AMP AGN E-A RD EN N E
Lectures:
– Fundamentals of Audio and Video Programming for Games
Turcan & Wasson (chapitres 1, 2, 5, 6)
– DirectX 9 Audio Exposed
Fay (chapitre 8)
– Game Audio Programming
Boer (chapitres 1 à 9 + 11)
Codes:
cf le site
SDK:
AdjustSound, AmplitudeModulation, CaptureSound,
EnumDevices, FullDuplexFilter, PlaySound, SoundFX,
VoiceManagement.

Documents pareils