Texel
DirectX | Index | Contact

Le son dans l'espace Part III:
En 3D



Nous allons enfin pouvoir passer aux choses sérieuses avec cette troisième partie. Au menu: Programmation d'un effet Doppler avec création d'un observateur dans une espace à trois dimensions. Le code source d'un exemple est disponible ICI (il n'utilise pas les cônes).

N'oubliez pas qu'avant de pouvoir utiliser les méthodes qui vont être présenter, il vous faut créer une voie audio avec un buffer en 3D avec les méthodes présentées à la première partie de ce tutorial. Envoyez donc le drapeau DMUS_APATH_DYNAMIC_3D à la méthode CreateStandardAudioPath. Pour le buffer 3D, déclarez un objet IDirectSound3DBuffer8 et envoyez l'identificateur IID_IDirectSound3DBuffer à la méthode GetObjectInPath.




1. Création d'un observateur

On ne va pas vraiment créé un observateur puisqu'il en existe déjà un par défaut. On va simplement créer un objet qui va nous permettre d'y accéder. Pour cela on utilise la même méthode de l'interface IDirectMusicAudioPath8 déjà utiliser pour accéder à un buffer.

IDirectSound3DListener* pDSListener = NULL;

p3DAudioPath->GetObjectInPath(
0,
DMUS_PATH_PRIMARY_BUFFER,
0,
GUID_NULL, 0, IID_IDirectSound3DListener,
(LPVOID*) &pDSListener
);












L'interface IDirectSound3DListener remplace celle du buffer. Le premier argument mis à zéro indique que l'on cherche seulement le premier canal. L'avant dernier argument est bien sûr IID_IDirectSound3DListener.

Cette interface doit être libérer avant la fermeture du programme avec la méthode Release.




2. Paramètres du buffer et de l'observateur

Pour gérer le son dans l'espace, il faut modifier certains paramètres du buffer (qui contient le son) et de l'observateur qui sont respectivement stockés dans des structures de type DS3DBUFFER et DS3DLISTENER.


Structure DS3DBUFFER
typedef struct{
DWORD dwSize; // taille de la structure (doit être initialiser avec sizeof)
D3DVECTOR vPosition; // structure D3DVECTOR pour la position du son
D3DVECTOR vVelocity; // structure D3DVECTOR pour le vecteur vitesse
DWORD dwInsideConeAngle; // angle du cône interne
DWORD dwOutsideConeAngle; // angle du cône externe
D3DVECTOR vConeOrientation; // struct. D3DVECTOR (direction du son)
LONG lConeOutsideVolume; // volume à l'extrémité du cône externe
D3DVALUE flMinDistance; // distance minimale
D3DVALUE flMaxDistance; // distance maximale
DWORD dwMode; // mode de traitement du son 3D
} DS3DBUFFER, *LPDS3DBUFFER;
















La structure D3DVECTOR contient trois champs:

typedef struct _D3DVECTOR {
float x;
float y;
float z;
} D3DVECTOR;








Regardons de plus près les champs de la structure DS3DBUFFER:

vPosition reçoit l'adresse d'une structure de type D3DVECTOR dans laquelle il faut définir les coordonnées la position du son. Ces coordonnées s'expriment en mètres. Pour réduire l'échelle de ces coordonnées, utilisez le champ flDistanceFactor de la structure DS3DLISTENER que nous verrons plus bas.

vVelocity reçoit l'adresse d'une structure de type D3DVECTOR qui contient les coordonnées du vecteur vitesse du son (pour l'effet Doppler).

Les deux champs suivants sont les valeurs de l'angle du cône interne et de l'angle du cône externe du son. Ils ont la valeur de 360 degrés par défaut.

vConeOrientation reçoit l'adresse d'une structure de type D3DVECTOR pour les coordonnées du vecteur direction du cône.

L'argument suivant est la valeur en décibels du volume à l'extrémité du cône externe. Le drapeau DSBVOLUME_MIN fixe le volume à zéro tandis ce que le drapeau DSBVOLUME_MAX annule l'atténuation entre les cônes.

La distance minimale et maximale concerne l'atténuation et l'amplification. A partir d'une certaine distance, le son est tellement atténué qu'il est inutile de continuer de l'atténuer. Pour économiser des calculs inutiles pour la machine, la distance maximale est la distance à partir de laquelle on ne veut plus que le son soit atténué.
La distance minimale est la distance à partir de laquelle le son n'augmente plus lorsqu'il s'approche.

Le dernier champ est le mode de traitement du son 3D. Il définit par défaut par le drapeau DS3DMODE_NORMAL. Le drapeau DS3DMODE_DISABLE désactive le traitement des sons en 3D. Le dernier drapeau DS3DMODE_HEADRELATIVE met automatiquement à jours les paramètres du buffer en fonction de l'observateur pour garder constante les valeurs relatives entre l'observateur et les sons.


Structure DS3DLISTENER
typedef struct{
DWORD dwSize; // taille de la structure (doit être initialiser avec sizeof)
D3DVECTOR vPosition; // position de l'observateur
D3DVECTOR vVelocity; // vitesse de l'observateur
D3DVECTOR vOrientFront; // vecteur face de la tête de l'observate
ur D3DVECTOR vOrientTop; // vecteur haut de la tête de l'observateur
D3DVALUE flDistanceFactor; // facteur pour la distance
D3DVALUE flRolloffFactor; // facteur pour l'atténuation
D3DVALUE flDopplerFactor; // facteur pour l'effet Doppler
} DS3DLISTENER, *LPDS3DLISTENER;














Pour les trois premiers paramètres c'est la même chose mais pour l'observateur.

Les deux vecteurs face et haut doivent être orthogonaux (Rappel: face et haut définissent l'orientation de la tête de l'observateur. cf. PART II ). Si ce n'est pas le cas, DirectX modifie le vecteur face pour qu'il puisse être orthogonal au vecteur haut.

Les facteurs de distance et d'atténuation amplifient ou réduisent ces deux effets. Une valeur inférieure à 1 réduit l'effet. Une valeur supérieure à 1 amplifie l'effet. Ces facteurs sont fixés à 1 par défaut.




3. Obtenir et appliquer les paramètres

Les paramètres ci-dessus ont des valeurs par défaut. Pour connaître ces paramètres, on utilise la méthode suivante, commune aux deux interfaces buffer et listener:

g_pDS3DBuffer->GetAllParameters( &g_dsBufferParams );




Ici, l'argument est l'adresse d'une structure de type DS3DBUFFER. C'est la même chose pour l'observateur, avec l'interface et le type de structure correspondant.

Pour appliquer de nouveau paramètre on utilise logiquement la méthode suivante:

g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE );




Le premier paramètre vous le connaissez déjà. Le deuxième argument est un drapeau indiquant que l'on souhaite que la modification soit immédiate. Si vous voulez différer ce changement, utilisez le drapeau DS3D_DEFERRED. L'opération restera en attente jusqu'à ce que vous appeliez la méthode sans argument: CommitDeferredSettings. Toutes les opérations mises en attente seront alors exécutées. Ca peut être utile pour éviter les surcharges de calculs.

Pour changer les paramètres d'un buffer ou d'un observateur, suivez les étapes suivantes:
_ Remplissez le champ dwSize de la structure DS3DBUFFER ou DS3DLISTENER
_ Appelez la méthode GetAllParameters.
_ Modifiez les paramètres
_ Appelez la méthode SetAllParameters.


Remarque:

Après avoir remplit une structure de type D3DVECTOR, utilisez la fonction memcpy pour l'envoyer dans une structure DS3DBUFFER ou DS3DLISTENER.


Remarque 2:

Vous n'êtes pas obliger de passer à chaque fois par SetAllParameters pour changer les paramètres. Vous pouvez utiliser des méthodes comme SetPosition ou SetVelocity. Mais apparemment, il semble obligatoire de déclarer et d'utiliser les structures DS3DBUFFER ou DS3DLISTENER. Si vous changé les paramètres en utilisant uniquement des méthodes comme SetPosition ou SetVelocity, vous aurez des résultats bizarres sur certaines machines. C'est peut-être dû au faite qu'il faille remplir le champ dwSize des structures.



Conclusion:

Désormais, vous savez placer les sons dans l'espace et gérer leur vitesse. DirectX peut vous permettre d'aller encore plus loin dans le rendu réaliste d'un environnement sonore. Vous pouvez en effet ajouter des effets spéciaux ( distorsion, écho, réverbération…) avec certaines interfaces de DirectSound. Et si ça ne vous suffit pas, allez télécharger le Kit de développement gratuit EAX SDK et son éditeur d'environnement "eagle" sur le site de creative (section "developper").




Version originale: Avril 2001
Dernière mise à jour: Février 2003
Par Grégory Smialek
www.texel.fr.fm