From c05efa8d7ae464235cf83d7c0956e42dc6974103 Mon Sep 17 00:00:00 2001 From: julieng Date: Sat, 2 Oct 2021 17:20:14 +0200 Subject: move *.html to *.md --- .../basic_concepts_behind_web_audio_api/index.html | 345 ----------------- .../basic_concepts_behind_web_audio_api/index.md | 345 +++++++++++++++++ files/fr/web/api/web_audio_api/index.html | 429 --------------------- files/fr/web/api/web_audio_api/index.md | 429 +++++++++++++++++++++ .../web_audio_api/using_web_audio_api/index.html | 277 ------------- .../api/web_audio_api/using_web_audio_api/index.md | 277 +++++++++++++ .../visualizations_with_web_audio_api/index.html | 180 --------- .../visualizations_with_web_audio_api/index.md | 180 +++++++++ .../web_audio_spatialization_basics/index.html | 261 ------------- .../web_audio_spatialization_basics/index.md | 261 +++++++++++++ 10 files changed, 1492 insertions(+), 1492 deletions(-) delete mode 100644 files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.html create mode 100644 files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.md delete mode 100644 files/fr/web/api/web_audio_api/index.html create mode 100644 files/fr/web/api/web_audio_api/index.md delete mode 100644 files/fr/web/api/web_audio_api/using_web_audio_api/index.html create mode 100644 files/fr/web/api/web_audio_api/using_web_audio_api/index.md delete mode 100644 files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.html create mode 100644 files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.md delete mode 100644 files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.html create mode 100644 files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.md (limited to 'files/fr/web/api/web_audio_api') diff --git a/files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.html b/files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.html deleted file mode 100644 index 6e5c9cae01..0000000000 --- a/files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.html +++ /dev/null @@ -1,345 +0,0 @@ ---- -title: Les concepts de base de la Web Audio API -slug: Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API -translation_of: Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API ---- - -

Cet article explique une partie de la théorie sur laquelle s'appuient les fonctionnalités de la Web Audio API. Il ne fera pas de vous un ingénieur du son, mais vous donnera les bases nécessaires pour comprendre pourquoi la Web Audio API fonctionne de cette manière, et vous permettre de mieux l'utiliser.

- -

Graphes audio

- -

La Web Audio API implique d'effectuer le traitement du son dans un contexte audio; elle a été conçue sur le principe de routage modulaire. Les opérations basiques sont effectuées dans noeuds audio, qui sont liés entre eux pour former un graphe de routage audio. Un seul contexte peut supporter plusieurs sources — avec différentes configurations de canaux. Cette architecture modulaire assure la flexibilité nécessaire pour créer des fonctions audio complexes avec des effets dynamiques.

- -

Les noeuds audio sont liés au niveau de leur entrée et leur sortie, formant une chaîne qui commence avec une ou plusieurs sources, traverse un ou plusieurs noeuds, et se termine avec une sortie spécifique (bien qu'il ne soit pas nécessaire de spécifier une sortie si, par exemple, vous souhaitez seulement visualiser des données audio). Un scénario simple, représentatif de la Web Audio API, pourrait ressembler à ceci :

- -
    -
  1. Création d'un contexte audio
  2. -
  3. Dans ce contexte, création des sources — telles que <audio>, oscillateur, flux
  4. -
  5. Création des noeuds d'effets, tels que réverb, filtres biquad, balance,  compresseur
  6. -
  7. Choix final de la sortie audio, par exemple les enceintes du système 
  8. -
  9. Connection des sources aux effets, et des effets à la sortie.
  10. -
- -

Diagramme simple composé de trois rectangles intitulés Sources, Effets et Sortie, reliés par des flèches, de gauche à droite, qui indiquent le sens du flux d'informations audio.

- -

Chaque entrée ou sortie est composée de plusieurs canaux, chacun correspondant à une configuration audio spécifique. Tout type de canal discret est supporté, y compris mono, stereo, quad, 5.1, etc.

- -

Diagramme qui montre comment les AudioNodes sont reliés par leurs entrées et sorties, et la configuration des canaux à l'intérieur de ces entrées/sorties.

- -

Les sources audio peuvent être de provenance variée :

- - - -

Données audio: ce qu'on trouve dans un échantillon

- -

Lors du traitement d'un signal audio, l'échantillonage désigne la conversion d'un signal continu en signal discret; formulé autrement, une onde de son continue, comme un groupe qui joue en live, est convertie en une séquence d'échantillons (un signal temporel discret) qui permet à l'ordinateur de traiter le son en blocs distincts.

- -

On peut trouver davantage de détails sur la page Wikipedia Echantillonage (signal).

- -

Mémoire tampon : trames, échantillons et canaux

- -

Un {{ domxref("AudioBuffer") }} prend comme paramètres un nombre de canaux (1 pour mono, 2 pour stéréo, etc), une longueur, qui correspond au nombre de trames d'échantillon dans la mémoire tampon, et un taux d'échantillonage, qui indique le nombre de trames d'échantillons lues par seconde.

- -

Un échantillon est une valeur float32 unique, qui correspond à la valeur du flux audio à un point précis dans le temps, sur un canal spécifique (gauche ou droit dans le cas de la stéréo). Une trame, ou trame d'échantillon est l'ensemble de toutes les valeurs pour tous les canaux (deux pour la stéréo, six pour le 5.1, etc.)  à un point précis dans le temps.

- -

Le taux d'échantillonage est le nombre d'échantillons (ou de trames, puisque tous les échantillons d'une trame jouent en même temps) qui sont joués en une seconde, exprimés en Hz. Plus le taux d'échantillonage est élevé, meilleure est la qualité du son.

- -

Prenons deux {{ domxref("AudioBuffer") }}, l'un en mono et l'autre en stéréo, chacun d'une durée de 1 seconde et d'une fréquence de 44100Hz:

- - - -

Le diagramme montre une succession de tames dans un buffer audio. Comme le buffer est composé de deux canaux (stéréo), chaque trame contient deux échantillons.

- -

Lorsqu'un noeud de mémoire tampon est lu, on entend d'abord la trame la trame la plus à gauche, puis celle qui la suit à droite, etc. Dans le cas de la stéréo, on entend les deux canaux en même temps. Les trames d'échantillon sont très utiles, car elles représentent le temps indépendamment du nombre de canaux.

- -
-

Note : Pour obtenir le temps en secondes à partir du nombre de trames, diviser le nombre de trames par le taux d'échantillonage. Pour obtenir le nombre de trames à partir du nombre d'échantillons, diviser le nombre d'échantillons par le nombre de canaux.

-
- -

Voici quelques exemples simples:

- -
var contexte = new AudioContext();
-var memoireTampon = contexte.createBuffer(2, 22050, 44100);
- -
-

Note : 44,100 Hz (que l'on peut aussi écrire 44.1 kHz) est un taux d'échantillonage couramment utilisé. Pourquoi 44.1kHz ?
-
- D'abord, parce ce que le champ auditif qui peut être perçu par des oreilles humaines se situe à peu près entre 20 Hz et 20,000 Hz, et que selon le théorème d'échantillonage de Nyquist–Shannon la fréquence d'échantillonage doit être supérieure à deux fois la fréquence maximum que l'on souhaite reproduire; le taux d'échantillonage doit donc être supérieur à 40 kHz.
-
- De plus, le signal doit être traité par un filtre passe-bas avant d'être échantilloné, afin d'éviter le phénomène d'aliasing, et, si en théorie un  filtre passe-bas idéal devrait être capable de laisser passer les fréquences inférieures à 20 kHz (sans les atténuer) et de couper parfaitement les fréquences supérieures à 20 kHz, en pratique une bande de transition dans laquelle les fréquences sont partiellement atténuées est nécessaire. Plus la bande de transition est large, plus il est facile et économique de faire un filtre anti-aliasing. Le taux d'échantillonage 44.1 kHz laisse une bande de transition de 2.05 kHz.

-
- -

Ce code génère une mémoire tampon stéréo (deux canaux) qui, lorsqu'elle est lue dans un AudioContext à 44100Hz (configuration répandue, la plupart des cartes sons tournant à cette fréquence), dure 0.5 secondes: 22050 trames / 44100Hz = 0.5 secondes.

- -
var contexte = new AudioContext();
-var memoireTampon = context.createBuffer(1, 22050, 22050);
- -

Ce code génère une mémoire tampon mono (un seul canal) qui, lorsqu'elle est lue dans un AudioContext à 44100Hzz, est automatiquement *rééchantillonnée* à 44100Hz (et par conséquent produit 44100 trames), et dure 1.0 seconde: 44100 frames / 44100Hz = 1 seconde.

- -
-

Note : le rééchantillonnage audio est très similaire à la redimension d'une image : imaginons que vous ayiez une image de 16 x 16, mais que vous vouliez remplir une surface de 32x32: vous la redimensionnez (rééchantillonnez). Le résultat est de qualité inférieure (il peut être flou ou crénelé, en fonction de l'algorithme de redimensionnement), mais cela fonctionne, et l'image redimensionnée prend moins de place que l'originale. C'est la même chose pour le rééchantillonnage audio — vous gagnez de la place, mais en pratique il sera difficle de reproduire correctement des contenus de haute fréquence (c'est-à-dire des sons aigus).

-
- -

Mémoire tampon linéaire ou entrelacée

- -

La Web Audio API utilise un format de mémoire tampon linéaire : les canaux gauche et droite sont stockés de la façon suivante :

- -
LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR (pour un buffer de 16 trames)
- -

C'est assez courant dans le traitement audio, car cela permet de traiter facilement chaque canal de façon indépendante.

- -

L'alternative est d'utiliser un format entrelacé:

- -
LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR (pour un buffer de 16 trames)
- -

Ce format est communément utilisé pour stocker et lire du son avec très peu de traitement, comme par exemple pour un flux de  MP3 décodé.
-
- La Web Audio API expose *uniquement* des buffer linéaires, car elle est faite pour le traitement du son. Elle fonctionne en linéaire, mais convertit les données au format entrelacé au moment de les envoyer à la carte son pour qu'elles soient jouées. A l'inverse, lorsqu'un MP3 est décodé, le format d'origine entrelacé est converti en linéaire pour le traitement.

- -

Canaux audio

- -

Une mémoire tampon audio peut contenir différents nombres de canaux, depuis les configurations simple mono (un seul canal) ou stéréo (canal gauche et canal droit) en allant jusquà des configurations plus complexe comme le quad ou le 5.1, pour lesquels chaque canal contient plusieurs échantillons de sons, ce qui permet une expérience sonore plus riche. Les canaux sont généralement représentés par les abbréviations standard  détaillées dans le tableau ci-après :

- - - - - - - - - - - - - - - - - - - - -
Mono0: M: mono
Stereo0: L: gauche
- 1: R: droit
Quad0: L: gauche
- 1: R: droit
- 2: SL: surround gauche
- 3: SR: surround droit
5.10: L: gauche
- 1: R: droit
- 2: C: centre
- 3: LFE: subwoofer
- 4: SL: surround gauche
- 5: SR: surround droit
- -

Conversion ascendante et descendante

- -

Lorsque le nombre de canaux n'est pas le même en entrée et en sortie, on effectue une conversion ascendante ou descendante selon les règles suivantes. Cela peut être plus ou moins controllé en assignant la valeur speakers ou discrete à la propriété {{domxref("AudioNode.channelInterpretation")}} .

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
InterprétationCanaux d'entréeCanaux de sortieRègles de conversion
speakers1 (Mono)2 (Stéréo)Conversion ascendante de mono vers stéréo.
- Le canal d'entrée M est utilisé pour les deux canaux de sortie (L et R).
- output.L = input.M
- output.R = input.M
1 (Mono)4 (Quad)Conversion ascendante de mono vers quad.
- Le canal d'entrée M est utilisé pour les canaux de sortie autres que surround (L et R). Les canaux de sortie surround (SL et SR) sont silencieux.
- output.L = input.M
- output.R = input.M
- output.SL = 0
- output.SR = 0
1 (Mono)6 (5.1)Conversion ascendante de mono vers 5.1.
- Le canal d'entrée M est utilisé pour le canal de sortie central (C). Tous les autres canaux (L, R, LFE, SL, et SR) sont silencieux.
- output.L = 0
- output.R = 0

- output.C = input.M
- output.LFE = 0
- output.SL = 0
- output.SR = 0
2 (Stéréo)1 (Mono)Conversion descendante de stéréo vers mono.
- Les deux canaux d'entrée (L et R) sont combinées pour produire l'unique canal de sortie (M).
- output.M = 0.5 * (input.L + input.R)
2 (Stéréo)4 (Quad)Conversion ascendante de stéréo vers quad.
- Les canaux d'entrée L et R input sont utilisés pour leurs équivalents respectifs non-surround en sortie (L et R). Les canaux de sortie surround (SL et SR) sont silencieux.
- output.L = input.L
- output.R = input.R
- output.SL = 0
- output.SR = 0
2 (Stéréo)6 (5.1)Conversion ascendante de stéréo vers 5.1.
- Les canaux d'entrée L et R sont utilisés pour leurs équivalents respectifs non-surround en sortie (L et R). Les canaux de sortie surround (SL et SR), ainsi que le canal central (C) et le canal subwoofer (LFE) restent silencieux.
- output.L = input.L
- output.R = input.R
- output.C = 0
- output.LFE = 0
- output.SL = 0
- output.SR = 0
4 (Quad)1 (Mono)Conversion descendante de quad vers mono.
- Les quatre canaux de sortie (L, R, SL, et SR) sont  combinés pour produire l'unique canal de sortie (M).
- output.M = 0.25 * (input.L + input.R + input.SL + input.SR)
4 (Quad)2 (Stéréo)Conversion descendante de quad vers stéréo.
- Les deux canaux d'entrée à gauche (L and SL) sont combinés pour produire l'unique canal de sortie à gauche (L). De la même façon, les deux canaux d'entrée à droite (R et SR) sont combinés pour produire l'unique canal de sortie à droite (R).
- output.L = 0.5 * (input.L + input.SL)
- output.R = 0.5 * (input.R + input.SR)
4 (Quad)6 (5.1)Conversion ascendante de quad vers 5.1.
- Les canaux d'entrée L, R, SL, et SR sont utilisés pour leur canaux de sortie équivalents respectifs (L and R). Le canal central (C) et le canal subwoofer (LFE) restent silencieux.
- output.L = input.L
- output.R = input.R
- output.C = 0
- output.LFE = 0
- output.SL = input.SL
- output.SR = input.SR
6 (5.1)1 (Mono)Conversion descendante de 5.1 vers mono.
- Les canaux de gauche (L et SL), de droite (R et SR) et central sont tous mixés ensemble. Les canaux surround sont légèrement atténués et la puissance des canaux latéraux est compensée pour la faire compter comme un seul canal en la multipliant par √2/2. Le canal subwoofer (LFE) est perdu.
- output.M = 0.7071 * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR)
6 (5.1)2 (Stéréo)Conversion descendante de 5.1 vers stéréo.
- Le canal central (C) est additionné avec chacun des canaux latéraux  (SL et SR) puis combiné avec chacun des canaux latéraux (L et R). Comme il est converti en deux canaux, il est mixé à une puissance inférieure : multiplié par √2/2. Le canal subwoofer (LFE) est perdu.
- output.L = input.L + 0.7071 * (input.C + input.SL)
- output.R = input.R
+ 0.7071 * (input.C + input.SR)
6 (5.1)4 (Quad)Conversion descendante de 5.1 vers quad.
- Le canal central (C) est combiné avec les canaux latéraux non-surround (L et R). Comme il est converti en deux canaux, il est mixé à une puissance inférieure : multiplié par √2/2. Les canaux surround restent inchangés. Le canal subwoofer (LFE) est perdu.
- output.L = input.L + 0.7071 * input.C
- output.R = input.R + 0.7071 * input.C
- output.SL = input.SL
- output.SR = input.SR
Autres configurations non-standardLes configurations non-standard sont traitées comme si la propriété channelInterpretation avait la valeur discrete.
- La spécification autorise explicitement la définition à venir de nouvelles configurations de sortie pour les enceintes. Ce cas de figure  n'est par conséquent pas garanti dans le futur, car le comportement des navigateurs pour un nombre spécifique de canaux pourrait être amené à changer.
discretetout (x)tout (y) pour lequel x<yConversion ascendante de canaux discrets.
- Remplit chaque canal de sortie avec son équivalent en entrée, c'est-à-dire le canal qui a le même index. Les canaux de sortie qui n'ont pas d'équivalent en entrée restent silencieux.
tout (x)tout (y) pour lequel x>yConversion descendante de canaux discrets.
- Remplit chaque canal de sortie avec son équivalent en entrée, c'est-à-dire le canal qui a le même index. Les canaux d'entrée qui n'ont pas d'équivalent en sortie sont perdus.
- -

Visualisations

- -

Une visualisation audio consiste en général à utiliser un flux de données audio dans le temps (souvent des informations de gain ou de fréquence) pour générer un affichage graphique (comme un graphe). La Web Audio API possède un {{domxref("AnalyserNode")}} qui n'altère pas le signal audio qui le traverse, permettant de générer des données qui peuvent être utilisées par une technologie de visualisation telle que {{htmlelement("canvas")}}.

- -

Le noeud permet de récupérer la fréquence et le domaine temporel en utilisant FFT, et ce sans modifier le flux audio

- -

On peut accéder aux données en utilisant les méthodes suivantes:

- -
-
{{domxref("AnalyserNode.getFloatFrequencyData()")}}
-
Copie les données de fréquence dans le tableau {{domxref("Float32Array")}} passé en argument.
-
- -
-
{{domxref("AnalyserNode.getByteFrequencyData()")}}
-
Copies les données de fréquence dans le tableau d'octets non signés {{domxref("Uint8Array")}} passé en argument.
-
- -
-
{{domxref("AnalyserNode.getFloatTimeDomainData()")}}
-
Copie les données de l'onde de forme, ou domaine temporel, dans le {{domxref("Float32Array")}} passé en argument.
-
{{domxref("AnalyserNode.getByteTimeDomainData()")}}
-
Copie les données de l'onde de forme, ou domaine temporel, dans le tableau d'octets non signés {{domxref("Uint8Array")}} passé en argument.
-
- -
-

Note : Pour plus d'informations, voir notre article Visualizations with Web Audio API.

-
- -

Spatialisations

- -
-

Une spatialisation audio (gérée par les noeuds {{domxref("PannerNode")}} et {{domxref("AudioListener")}} dans la Web Audio API) permet de modéliser la position et le comportement d'un signal audio situé dans l'espace, ainsi que l'auditeur qui perçoit ce signal.

- -

La position du panoramique est décrite avec des coodonnées cartésiennes selon la règle de la main droite, son mouvement à l'aide d'un vecteur de vélocité (nécessaire pour la création d'effets Doppler) et sa direction avec un cone de direction. Le cone peut être très large, par exemple dans le cas de sources omnidirectionnelles.

-
- -

Le PannerNode donne la position dans l'espace, la vélocité et la direction d'un signal donné

- -
-

La position de l'auditeur est décrite avec des coodonnées cartésiennes selon la règle de la main droite,  son mouvement à l'aide d'un vecteur de vélocité et la direction vers laquelle elle pointe en utilisant deux vecteurs de direction : haut et face. Ceux-ci définissent respectivement la direction vers laquelle pointent le haut de la tête et le bout du nez de l'auditeur, et forment un angle droit entre eux.

-
- -

On voit la position d'un auditeur, ainsi que les vecteurs de direction haut et de face qui forment un angle de 90°

- -
-

Note : For more information, see our Web audio spatialization basics article.

-
- -

Fan-in et Fan-out

- -

En audio, fan-in désigne le processus par lequel un {{domxref("ChannelMergerNode")}} prend une série d'entrées mono entrée et restitue un seul signal multi-canaux :

- -

- -

Fan-out désigne le processus opposé, par lequel un {{domxref("ChannelSplitterNode")}} prend une source multi-canaux en entrée et restitue plusieurs signaux mono en sortie:

- -

diff --git a/files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.md b/files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.md new file mode 100644 index 0000000000..6e5c9cae01 --- /dev/null +++ b/files/fr/web/api/web_audio_api/basic_concepts_behind_web_audio_api/index.md @@ -0,0 +1,345 @@ +--- +title: Les concepts de base de la Web Audio API +slug: Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API +translation_of: Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API +--- + +

Cet article explique une partie de la théorie sur laquelle s'appuient les fonctionnalités de la Web Audio API. Il ne fera pas de vous un ingénieur du son, mais vous donnera les bases nécessaires pour comprendre pourquoi la Web Audio API fonctionne de cette manière, et vous permettre de mieux l'utiliser.

+ +

Graphes audio

+ +

La Web Audio API implique d'effectuer le traitement du son dans un contexte audio; elle a été conçue sur le principe de routage modulaire. Les opérations basiques sont effectuées dans noeuds audio, qui sont liés entre eux pour former un graphe de routage audio. Un seul contexte peut supporter plusieurs sources — avec différentes configurations de canaux. Cette architecture modulaire assure la flexibilité nécessaire pour créer des fonctions audio complexes avec des effets dynamiques.

+ +

Les noeuds audio sont liés au niveau de leur entrée et leur sortie, formant une chaîne qui commence avec une ou plusieurs sources, traverse un ou plusieurs noeuds, et se termine avec une sortie spécifique (bien qu'il ne soit pas nécessaire de spécifier une sortie si, par exemple, vous souhaitez seulement visualiser des données audio). Un scénario simple, représentatif de la Web Audio API, pourrait ressembler à ceci :

+ +
    +
  1. Création d'un contexte audio
  2. +
  3. Dans ce contexte, création des sources — telles que <audio>, oscillateur, flux
  4. +
  5. Création des noeuds d'effets, tels que réverb, filtres biquad, balance,  compresseur
  6. +
  7. Choix final de la sortie audio, par exemple les enceintes du système 
  8. +
  9. Connection des sources aux effets, et des effets à la sortie.
  10. +
+ +

Diagramme simple composé de trois rectangles intitulés Sources, Effets et Sortie, reliés par des flèches, de gauche à droite, qui indiquent le sens du flux d'informations audio.

+ +

Chaque entrée ou sortie est composée de plusieurs canaux, chacun correspondant à une configuration audio spécifique. Tout type de canal discret est supporté, y compris mono, stereo, quad, 5.1, etc.

+ +

Diagramme qui montre comment les AudioNodes sont reliés par leurs entrées et sorties, et la configuration des canaux à l'intérieur de ces entrées/sorties.

+ +

Les sources audio peuvent être de provenance variée :

+ + + +

Données audio: ce qu'on trouve dans un échantillon

+ +

Lors du traitement d'un signal audio, l'échantillonage désigne la conversion d'un signal continu en signal discret; formulé autrement, une onde de son continue, comme un groupe qui joue en live, est convertie en une séquence d'échantillons (un signal temporel discret) qui permet à l'ordinateur de traiter le son en blocs distincts.

+ +

On peut trouver davantage de détails sur la page Wikipedia Echantillonage (signal).

+ +

Mémoire tampon : trames, échantillons et canaux

+ +

Un {{ domxref("AudioBuffer") }} prend comme paramètres un nombre de canaux (1 pour mono, 2 pour stéréo, etc), une longueur, qui correspond au nombre de trames d'échantillon dans la mémoire tampon, et un taux d'échantillonage, qui indique le nombre de trames d'échantillons lues par seconde.

+ +

Un échantillon est une valeur float32 unique, qui correspond à la valeur du flux audio à un point précis dans le temps, sur un canal spécifique (gauche ou droit dans le cas de la stéréo). Une trame, ou trame d'échantillon est l'ensemble de toutes les valeurs pour tous les canaux (deux pour la stéréo, six pour le 5.1, etc.)  à un point précis dans le temps.

+ +

Le taux d'échantillonage est le nombre d'échantillons (ou de trames, puisque tous les échantillons d'une trame jouent en même temps) qui sont joués en une seconde, exprimés en Hz. Plus le taux d'échantillonage est élevé, meilleure est la qualité du son.

+ +

Prenons deux {{ domxref("AudioBuffer") }}, l'un en mono et l'autre en stéréo, chacun d'une durée de 1 seconde et d'une fréquence de 44100Hz:

+ + + +

Le diagramme montre une succession de tames dans un buffer audio. Comme le buffer est composé de deux canaux (stéréo), chaque trame contient deux échantillons.

+ +

Lorsqu'un noeud de mémoire tampon est lu, on entend d'abord la trame la trame la plus à gauche, puis celle qui la suit à droite, etc. Dans le cas de la stéréo, on entend les deux canaux en même temps. Les trames d'échantillon sont très utiles, car elles représentent le temps indépendamment du nombre de canaux.

+ +
+

Note : Pour obtenir le temps en secondes à partir du nombre de trames, diviser le nombre de trames par le taux d'échantillonage. Pour obtenir le nombre de trames à partir du nombre d'échantillons, diviser le nombre d'échantillons par le nombre de canaux.

+
+ +

Voici quelques exemples simples:

+ +
var contexte = new AudioContext();
+var memoireTampon = contexte.createBuffer(2, 22050, 44100);
+ +
+

Note : 44,100 Hz (que l'on peut aussi écrire 44.1 kHz) est un taux d'échantillonage couramment utilisé. Pourquoi 44.1kHz ?
+
+ D'abord, parce ce que le champ auditif qui peut être perçu par des oreilles humaines se situe à peu près entre 20 Hz et 20,000 Hz, et que selon le théorème d'échantillonage de Nyquist–Shannon la fréquence d'échantillonage doit être supérieure à deux fois la fréquence maximum que l'on souhaite reproduire; le taux d'échantillonage doit donc être supérieur à 40 kHz.
+
+ De plus, le signal doit être traité par un filtre passe-bas avant d'être échantilloné, afin d'éviter le phénomène d'aliasing, et, si en théorie un  filtre passe-bas idéal devrait être capable de laisser passer les fréquences inférieures à 20 kHz (sans les atténuer) et de couper parfaitement les fréquences supérieures à 20 kHz, en pratique une bande de transition dans laquelle les fréquences sont partiellement atténuées est nécessaire. Plus la bande de transition est large, plus il est facile et économique de faire un filtre anti-aliasing. Le taux d'échantillonage 44.1 kHz laisse une bande de transition de 2.05 kHz.

+
+ +

Ce code génère une mémoire tampon stéréo (deux canaux) qui, lorsqu'elle est lue dans un AudioContext à 44100Hz (configuration répandue, la plupart des cartes sons tournant à cette fréquence), dure 0.5 secondes: 22050 trames / 44100Hz = 0.5 secondes.

+ +
var contexte = new AudioContext();
+var memoireTampon = context.createBuffer(1, 22050, 22050);
+ +

Ce code génère une mémoire tampon mono (un seul canal) qui, lorsqu'elle est lue dans un AudioContext à 44100Hzz, est automatiquement *rééchantillonnée* à 44100Hz (et par conséquent produit 44100 trames), et dure 1.0 seconde: 44100 frames / 44100Hz = 1 seconde.

+ +
+

Note : le rééchantillonnage audio est très similaire à la redimension d'une image : imaginons que vous ayiez une image de 16 x 16, mais que vous vouliez remplir une surface de 32x32: vous la redimensionnez (rééchantillonnez). Le résultat est de qualité inférieure (il peut être flou ou crénelé, en fonction de l'algorithme de redimensionnement), mais cela fonctionne, et l'image redimensionnée prend moins de place que l'originale. C'est la même chose pour le rééchantillonnage audio — vous gagnez de la place, mais en pratique il sera difficle de reproduire correctement des contenus de haute fréquence (c'est-à-dire des sons aigus).

+
+ +

Mémoire tampon linéaire ou entrelacée

+ +

La Web Audio API utilise un format de mémoire tampon linéaire : les canaux gauche et droite sont stockés de la façon suivante :

+ +
LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR (pour un buffer de 16 trames)
+ +

C'est assez courant dans le traitement audio, car cela permet de traiter facilement chaque canal de façon indépendante.

+ +

L'alternative est d'utiliser un format entrelacé:

+ +
LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR (pour un buffer de 16 trames)
+ +

Ce format est communément utilisé pour stocker et lire du son avec très peu de traitement, comme par exemple pour un flux de  MP3 décodé.
+
+ La Web Audio API expose *uniquement* des buffer linéaires, car elle est faite pour le traitement du son. Elle fonctionne en linéaire, mais convertit les données au format entrelacé au moment de les envoyer à la carte son pour qu'elles soient jouées. A l'inverse, lorsqu'un MP3 est décodé, le format d'origine entrelacé est converti en linéaire pour le traitement.

+ +

Canaux audio

+ +

Une mémoire tampon audio peut contenir différents nombres de canaux, depuis les configurations simple mono (un seul canal) ou stéréo (canal gauche et canal droit) en allant jusquà des configurations plus complexe comme le quad ou le 5.1, pour lesquels chaque canal contient plusieurs échantillons de sons, ce qui permet une expérience sonore plus riche. Les canaux sont généralement représentés par les abbréviations standard  détaillées dans le tableau ci-après :

+ + + + + + + + + + + + + + + + + + + + +
Mono0: M: mono
Stereo0: L: gauche
+ 1: R: droit
Quad0: L: gauche
+ 1: R: droit
+ 2: SL: surround gauche
+ 3: SR: surround droit
5.10: L: gauche
+ 1: R: droit
+ 2: C: centre
+ 3: LFE: subwoofer
+ 4: SL: surround gauche
+ 5: SR: surround droit
+ +

Conversion ascendante et descendante

+ +

Lorsque le nombre de canaux n'est pas le même en entrée et en sortie, on effectue une conversion ascendante ou descendante selon les règles suivantes. Cela peut être plus ou moins controllé en assignant la valeur speakers ou discrete à la propriété {{domxref("AudioNode.channelInterpretation")}} .

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
InterprétationCanaux d'entréeCanaux de sortieRègles de conversion
speakers1 (Mono)2 (Stéréo)Conversion ascendante de mono vers stéréo.
+ Le canal d'entrée M est utilisé pour les deux canaux de sortie (L et R).
+ output.L = input.M
+ output.R = input.M
1 (Mono)4 (Quad)Conversion ascendante de mono vers quad.
+ Le canal d'entrée M est utilisé pour les canaux de sortie autres que surround (L et R). Les canaux de sortie surround (SL et SR) sont silencieux.
+ output.L = input.M
+ output.R = input.M
+ output.SL = 0
+ output.SR = 0
1 (Mono)6 (5.1)Conversion ascendante de mono vers 5.1.
+ Le canal d'entrée M est utilisé pour le canal de sortie central (C). Tous les autres canaux (L, R, LFE, SL, et SR) sont silencieux.
+ output.L = 0
+ output.R = 0

+ output.C = input.M
+ output.LFE = 0
+ output.SL = 0
+ output.SR = 0
2 (Stéréo)1 (Mono)Conversion descendante de stéréo vers mono.
+ Les deux canaux d'entrée (L et R) sont combinées pour produire l'unique canal de sortie (M).
+ output.M = 0.5 * (input.L + input.R)
2 (Stéréo)4 (Quad)Conversion ascendante de stéréo vers quad.
+ Les canaux d'entrée L et R input sont utilisés pour leurs équivalents respectifs non-surround en sortie (L et R). Les canaux de sortie surround (SL et SR) sont silencieux.
+ output.L = input.L
+ output.R = input.R
+ output.SL = 0
+ output.SR = 0
2 (Stéréo)6 (5.1)Conversion ascendante de stéréo vers 5.1.
+ Les canaux d'entrée L et R sont utilisés pour leurs équivalents respectifs non-surround en sortie (L et R). Les canaux de sortie surround (SL et SR), ainsi que le canal central (C) et le canal subwoofer (LFE) restent silencieux.
+ output.L = input.L
+ output.R = input.R
+ output.C = 0
+ output.LFE = 0
+ output.SL = 0
+ output.SR = 0
4 (Quad)1 (Mono)Conversion descendante de quad vers mono.
+ Les quatre canaux de sortie (L, R, SL, et SR) sont  combinés pour produire l'unique canal de sortie (M).
+ output.M = 0.25 * (input.L + input.R + input.SL + input.SR)
4 (Quad)2 (Stéréo)Conversion descendante de quad vers stéréo.
+ Les deux canaux d'entrée à gauche (L and SL) sont combinés pour produire l'unique canal de sortie à gauche (L). De la même façon, les deux canaux d'entrée à droite (R et SR) sont combinés pour produire l'unique canal de sortie à droite (R).
+ output.L = 0.5 * (input.L + input.SL)
+ output.R = 0.5 * (input.R + input.SR)
4 (Quad)6 (5.1)Conversion ascendante de quad vers 5.1.
+ Les canaux d'entrée L, R, SL, et SR sont utilisés pour leur canaux de sortie équivalents respectifs (L and R). Le canal central (C) et le canal subwoofer (LFE) restent silencieux.
+ output.L = input.L
+ output.R = input.R
+ output.C = 0
+ output.LFE = 0
+ output.SL = input.SL
+ output.SR = input.SR
6 (5.1)1 (Mono)Conversion descendante de 5.1 vers mono.
+ Les canaux de gauche (L et SL), de droite (R et SR) et central sont tous mixés ensemble. Les canaux surround sont légèrement atténués et la puissance des canaux latéraux est compensée pour la faire compter comme un seul canal en la multipliant par √2/2. Le canal subwoofer (LFE) est perdu.
+ output.M = 0.7071 * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR)
6 (5.1)2 (Stéréo)Conversion descendante de 5.1 vers stéréo.
+ Le canal central (C) est additionné avec chacun des canaux latéraux  (SL et SR) puis combiné avec chacun des canaux latéraux (L et R). Comme il est converti en deux canaux, il est mixé à une puissance inférieure : multiplié par √2/2. Le canal subwoofer (LFE) est perdu.
+ output.L = input.L + 0.7071 * (input.C + input.SL)
+ output.R = input.R
+ 0.7071 * (input.C + input.SR)
6 (5.1)4 (Quad)Conversion descendante de 5.1 vers quad.
+ Le canal central (C) est combiné avec les canaux latéraux non-surround (L et R). Comme il est converti en deux canaux, il est mixé à une puissance inférieure : multiplié par √2/2. Les canaux surround restent inchangés. Le canal subwoofer (LFE) est perdu.
+ output.L = input.L + 0.7071 * input.C
+ output.R = input.R + 0.7071 * input.C
+ output.SL = input.SL
+ output.SR = input.SR
Autres configurations non-standardLes configurations non-standard sont traitées comme si la propriété channelInterpretation avait la valeur discrete.
+ La spécification autorise explicitement la définition à venir de nouvelles configurations de sortie pour les enceintes. Ce cas de figure  n'est par conséquent pas garanti dans le futur, car le comportement des navigateurs pour un nombre spécifique de canaux pourrait être amené à changer.
discretetout (x)tout (y) pour lequel x<yConversion ascendante de canaux discrets.
+ Remplit chaque canal de sortie avec son équivalent en entrée, c'est-à-dire le canal qui a le même index. Les canaux de sortie qui n'ont pas d'équivalent en entrée restent silencieux.
tout (x)tout (y) pour lequel x>yConversion descendante de canaux discrets.
+ Remplit chaque canal de sortie avec son équivalent en entrée, c'est-à-dire le canal qui a le même index. Les canaux d'entrée qui n'ont pas d'équivalent en sortie sont perdus.
+ +

Visualisations

+ +

Une visualisation audio consiste en général à utiliser un flux de données audio dans le temps (souvent des informations de gain ou de fréquence) pour générer un affichage graphique (comme un graphe). La Web Audio API possède un {{domxref("AnalyserNode")}} qui n'altère pas le signal audio qui le traverse, permettant de générer des données qui peuvent être utilisées par une technologie de visualisation telle que {{htmlelement("canvas")}}.

+ +

Le noeud permet de récupérer la fréquence et le domaine temporel en utilisant FFT, et ce sans modifier le flux audio

+ +

On peut accéder aux données en utilisant les méthodes suivantes:

+ +
+
{{domxref("AnalyserNode.getFloatFrequencyData()")}}
+
Copie les données de fréquence dans le tableau {{domxref("Float32Array")}} passé en argument.
+
+ +
+
{{domxref("AnalyserNode.getByteFrequencyData()")}}
+
Copies les données de fréquence dans le tableau d'octets non signés {{domxref("Uint8Array")}} passé en argument.
+
+ +
+
{{domxref("AnalyserNode.getFloatTimeDomainData()")}}
+
Copie les données de l'onde de forme, ou domaine temporel, dans le {{domxref("Float32Array")}} passé en argument.
+
{{domxref("AnalyserNode.getByteTimeDomainData()")}}
+
Copie les données de l'onde de forme, ou domaine temporel, dans le tableau d'octets non signés {{domxref("Uint8Array")}} passé en argument.
+
+ +
+

Note : Pour plus d'informations, voir notre article Visualizations with Web Audio API.

+
+ +

Spatialisations

+ +
+

Une spatialisation audio (gérée par les noeuds {{domxref("PannerNode")}} et {{domxref("AudioListener")}} dans la Web Audio API) permet de modéliser la position et le comportement d'un signal audio situé dans l'espace, ainsi que l'auditeur qui perçoit ce signal.

+ +

La position du panoramique est décrite avec des coodonnées cartésiennes selon la règle de la main droite, son mouvement à l'aide d'un vecteur de vélocité (nécessaire pour la création d'effets Doppler) et sa direction avec un cone de direction. Le cone peut être très large, par exemple dans le cas de sources omnidirectionnelles.

+
+ +

Le PannerNode donne la position dans l'espace, la vélocité et la direction d'un signal donné

+ +
+

La position de l'auditeur est décrite avec des coodonnées cartésiennes selon la règle de la main droite,  son mouvement à l'aide d'un vecteur de vélocité et la direction vers laquelle elle pointe en utilisant deux vecteurs de direction : haut et face. Ceux-ci définissent respectivement la direction vers laquelle pointent le haut de la tête et le bout du nez de l'auditeur, et forment un angle droit entre eux.

+
+ +

On voit la position d'un auditeur, ainsi que les vecteurs de direction haut et de face qui forment un angle de 90°

+ +
+

Note : For more information, see our Web audio spatialization basics article.

+
+ +

Fan-in et Fan-out

+ +

En audio, fan-in désigne le processus par lequel un {{domxref("ChannelMergerNode")}} prend une série d'entrées mono entrée et restitue un seul signal multi-canaux :

+ +

+ +

Fan-out désigne le processus opposé, par lequel un {{domxref("ChannelSplitterNode")}} prend une source multi-canaux en entrée et restitue plusieurs signaux mono en sortie:

+ +

diff --git a/files/fr/web/api/web_audio_api/index.html b/files/fr/web/api/web_audio_api/index.html deleted file mode 100644 index 087d05a380..0000000000 --- a/files/fr/web/api/web_audio_api/index.html +++ /dev/null @@ -1,429 +0,0 @@ ---- -title: Web Audio API -slug: Web/API/Web_Audio_API -translation_of: Web/API/Web_Audio_API ---- -
-

La Web Audio API propose un système puissant et flexible pour contrôler les données audio sur internet. Elle permet notamment de sélectionner des sources audio (microphone, flux media), d'y ajouter des effets, de créer des visualisations, d'appliquer des effets de spatialisation (comme la balance), etc.

-
- -

Concepts et usages

- -

La Web Audio API effectue des opérations dans un contexte audio; elle a été conçue pour supporter le routing modulaire. Les opérations audio basiques sont réalisées via des noeuds audio reliés entre eux pour former un graphe de routage audio. Plusieurs sources - avec différents types d'agencements de canaux - peuvent être supportées, même dans un seul contexte. Ce design modulaire et flexible permet de créer des fonctions audio complexes avec des effets dynamiques.

- -

Les noeuds audio sont reliés au niveau de leurs entrées et sorties, formant des chaînes ou des réseaux simples. Il peut y avoir une ou plusieurs sources. Les sources fournissent des tableaux d'intensités sonores (échantillons), souvent plusieurs dizaines de milliers par seconde. Ceux-ci peuvent être calculées mathématiquement (avec un {{domxref("OscillatorNode")}}), ou peuvent provenir de fichiers sons ou vidéos (comme {{domxref("AudioBufferSourceNode")}} ou {{domxref("MediaElementAudioSourceNode")}}) ou de flux audio ({{domxref("MediaStreamAudioSourceNode")}}). En réalité, les fichiers sons sont eux-même des enregistrements d'intensités sonores, qui viennent de microphones ou d'instruments électriques, et sont mixés dans une seule onde complexe.

- -

Les sorties de ces noeuds peuvent être liées aux entrées d'autres noeuds, qui mixent ces flux d'échantillons sonores ou les séparent en différents flux. Une modification courante est la multiplications des échantillons par une valeur afin d'en augmenter ou diminuer le volume sonore (comme c'est le cas pour le {{domxref("GainNode")}}). Le son est ensuite lié à une destination ({{domxref("AudioContext.destination")}}), qui l'envoie aux enceintes ou au casque audio. Cette dernière connexion n'est utile que si le son doit être entendu.
-
- Un processus de développement typique avec web audio ressemble à ceci :

- - - -

Un diagramme de boîte avec une boîte extérieure intitulée contexte audio et trois boîtes à l'intérieur intitulées source, effets et destination. Les trois boîtes intérieures ont des flèches qui pointent de la gauche vers la droite, indiquant le sens du flux de l'information audio.

- -

Le timing est contrôlé avec une grande précision et une latence faible, ce qui permet aux développeurs d'écrire un code qui réagit précisément aux événements et qui est capable de traiter des échantillons précis, même avec un taux d'échantillonnage élevé. Cela permet d'envisager des applications telles que des boîtes à rythme ou des séquenceurs.

- -

La Web Audio API permet également de contrôler la spatialisation du son. En utilisant un système basé sur le modèle émetteur - récepteur, elle permet le contrôle de la balance ainsi que la gestion de l'atténuation du son en fonction de la distance, ou effet doppler, induite par un déplacement de la source sonore (ou de l'auditeur).

- -
-

Note : Vous pouvez lire d'avantage de détails sur la Web Audio API en vous rendant sur notre article Concepts de base de la Web Audio API.

-
- -

Interface de la Web Audio API

- -

La Web Audio API expose 28 interfaces avec des événements associés, classés selon leur fonction en 9 catégories.

- -

Définition du graphe audio

- -

Conteneurs et définitions qui donnent sa forme au graphe audio

- -
-
{{domxref("AudioContext")}}
-
Un objet AudioContext désigne un graphe de traitement audio construit à partir de modules reliés entre eux, chacun représenté par un noeud audio ({{domxref("AudioNode")}}). Le contexte audio contrôle la création des noeuds qu'il contient, ainsi que l'exécution du traitement audio, et du décodage. Il est nécessaire de créer un AudioContext avant de faire quoi que ce soit d'autre, puisque tout se passe dans un contexte.
-
{{domxref("AudioNode")}}
-
Un objet AudioNode est un module de traitement audio, tel qu'une source audio (c'est-à-dire un élément HTML {{HTMLElement("audio")}} ou {{HTMLElement("video")}}), une destination audio, un module de traitement intermédiaire (par exemple un filtre {{domxref("BiquadFilterNode")}}), ou un contrôle du volume {{domxref("GainNode")}}).
-
{{domxref("AudioParam")}}
-
Un objet AudioParam est un paramètre audio, qui est lié à un {{domxref("AudioNode")}}. On peut lui assigner une valeur ou un changement de valeur, que l'on peut programmer à un moment spécifique et/ou selon un motif particulier.
-
{{event("ended_(Web_Audio)", "ended")}} (event)
-
L'évènement ended est diffusé lorsque la lecture s'arrête en arrivant à la fin d'un media.
-
- -

Définition des sources audio

- -
-
{{domxref("OscillatorNode")}}
-
Un objet OscillatorNode est un module de traitement audio qui génère la création d'une onde sinusoïdale d'une certaine fréquence.
-
{{domxref("AudioBuffer")}}
-
Un objet AudioBuffer est un petit morceau de contenu audio monté en mémoire. Il peut être créé à partir d'un fichier audio avec la méthode {{ domxref("AudioContext.decodeAudioData()") }}, ou à partir de données brutes en utilisant {{ domxref("AudioContext.createBuffer()") }}. Une fois décodé sous cette forme, la source audio peut être placée dans un {{ domxref("AudioBufferSourceNode") }}.
-
{{domxref("AudioBufferSourceNode")}}
-
Un objet AudioBufferSourceNode est une source audio composée de données audio montées en mémoire dans un {{domxref("AudioBuffer")}}. C'est un {{domxref("AudioNode")}} qui se comporte comme une source audio.
-
{{domxref("MediaElementAudioSourceNode")}}
-
Un objet MediaElementAudioSourceNode est une source audio composée d'un élément  HTML5 {{ htmlelement("audio") }} ou {{ htmlelement("video") }}. C'est un {{domxref("AudioNode")}} qui se comporte comme une source audio.
-
{{domxref("MediaStreamAudioSourceNode")}}
-
Un objet MediaStreamAudioSourceNode est une source audio composée d'un WebRTC {{domxref("MediaStream")}} (tel qu'une webcam ou un microphone). C'est un {{domxref("AudioNode")}} qui se comporte comme une source audio.
-
- -

Définition des filtres d'effets audio

- -
-
{{domxref("BiquadFilterNode")}}
-
Un objet BiquadFilterNode est un simple filtre de bas niveau. Il peut s'agir de différents types de filtres, contrôle du volume ou égaliseurs graphiques. Un BiquadFilterNode a toujours exactement une entrée et une sortie.
-
{{domxref("ConvolverNode")}}
-
Un objet ConvolverNode est un {{domxref("AudioNode")}} qui exécute une circonvolution linéaire sur un AudioBuffer donné, souvent utilisé pour créer un effet de réverbération.
-
{{domxref("DelayNode")}}
-
Un objet DelayNode est une ligne à retard numérique, c'est-à-dire un module de traitement automatique qui provoque un délai entre l'arrivée du son en entrée et sa propagation en sortie.
-
{{domxref("DynamicsCompressorNode")}}
-
Un objet DynamicsCompressorNode permet un effet de compression, qui réduit le volume des parties les plus fortes du signal de façon à éviter les effets de clipping et la distortion qui peuvent se produire lorsque des sons multiples sont diffusés simultanément.
-
{{domxref("GainNode")}}
-
Un objet GainNode  représente une modification du volume sonore. C'est un module de traitement audio qui provoque l'application d'un gain aux données récupérées en entrée avant leur propagation vers la sortie.
-
{{domxref("WaveShaperNode")}}
-
Un objet WaveShaperNode représente une distortion non linéaire. C'est un {{domxref("AudioNode")}} qui utilise une courbe pour appliquer au signal une distortion de mise en forme des ondes. En dehors de l'effet de distortion évident, il est souvent utilisé pour donner un caractère plus chaleureux au son. 
-
{{domxref("PeriodicWave")}}
-
Un objet {{domxref("PeriodicWave")}} est utilisé pour définir une forme d'onde périodique qui peut être utilisée pour façonner la sortie d'un {{ domxref("OscillatorNode") }}.
-
- -

Définition des destinations audio

- -

Une fois que le signal audio a été traité, ces interfaces définissent sa destination.

- -
-
{{domxref("AudioDestinationNode")}}
-
Un noeud AudioDestinationNode représente la destination finale d'une source audio source dans un contexte donné — en général les enceintes du matériel.
-
{{domxref("MediaStreamAudioDestinationNode")}}
-
Un noeud MediaStreamAudioDestinationNode représente une destination audio constituée d'un {{domxref("MediaStream")}} WebRTC à une seule piste AudioMediaStreamTrack; il peut être utilisé de façon similaire à un {{domxref("MediaStream")}} obtenu avec {{ domxref("Navigator.getUserMedia") }}. C'est un {{domxref("AudioNode")}} qui se comporte comme une destination audio.
-
- -

Analyse des données et visualisation

- -
-
{{domxref("AnalyserNode")}}
-
Un objet AnalyserNode fournit en temps réel des informations concernant la fréquence et le temps, afin de les analyser et les visualiser.
-
- -

Division et fusion des pistes audio

- -
-
{{domxref("ChannelSplitterNode")}}
-
Un noeud ChannelSplitterNode prend en entrée une source audio et sépare ses différentes pistes en une série de sorties mono.
-
{{domxref("ChannelMergerNode")}}
-
Un noeud ChannelMergerNode réunit différentes entrées mono en une seule sortie. Chaque entrée devient une des pistes de la sortie unique.
-
- -

Spatialisation audio

- -
-
{{domxref("AudioListener")}}
-
Un objet AudioListener représente la position et l'orientation de l'unique personne écoutant la scene audio utilisée dans la spatialisation audio.
-
{{domxref("PannerNode")}}
-
Un noeud PannerNode représente le comportement d'un signal dans l'espace. C'est un module de traitement audio qui décrit sa position avec des coordonnées cartésiennes fondées sur la règle de la main droite; ses mouvements utilisent un vecteur de vélocité et sa directionnalité un cône de direction.
-
- -

Traitement audio avec JavaScript

- -
-

Note : Au jour de la publication de la spécification Web Audio API le 29 août 2014, ces fonctionnalités sont dépréciées, et seront bientôt remplacées par {{ anch("Audio_Workers") }}.

-
- -
-
{{domxref("ScriptProcessorNode")}}
-
Un noeud ScriptProcessorNode permet de générer, traiter ou analyser du son avec JavaScript. C'est un module de traitement audio qui est lié à deux buffers, l'un en entrée, et l'autre en sortie. Un évènement implémentant {{domxref("AudioProcessingEvent")}} est envoyé à l'objet à chaque fois que le buffer d'entrée reçoit de nouvelles données, et le gestionnaire d'évènement prend fin lorsque les nouvelles données ont été communiquées au buffer de sortie. 
-
{{event("audioprocess")}} (event)
-
L'évènement audioprocess est émis lorsque le buffer d'entrée d'un {{domxref("ScriptProcessorNode")}} de la Web Audio API est prêt à être traité.
-
{{domxref("AudioProcessingEvent")}}
-
L'objet  AudioProcessingEvent est envoyé aux fonctions de callback qui écoutent l'évènement audioprocess.
-
- -

Traitement audio hors ligne ou en tâche de fond

- -

Il est possible de traiter et exporter un graphe audio très rapidement en tâche de fond — en l'exportant dans un {{domxref("AudioBuffer")}} plutôt que sur les enceintes du matériel — grâce aux objets suivants.

- -
-
{{domxref("OfflineAudioContext")}}
-
Un objet OfflineAudioContext est un {{domxref("AudioContext")}} qui représente un graphe de traitement audio construit à partir de noeuds audio. A la différence du AudioContext standard, un OfflineAudioContext n'exporte pas vraiment le son, mais le génère, aussi vite que possible, dans un buffer.
-
{{event("complete")}} (event)
-
Un évènement complete est émis lorsque le rendu d'un {{domxref("OfflineAudioContext")}} est terminé.
-
{{domxref("OfflineAudioCompletionEvent")}}
-
The OfflineAudioCompletionEvent est envoyé aux fonctions de callback qui écoutent l'évènement {{event("complete")}} event implements this interface.
-
- -

Audio Workers

- -

Les Audio workers offrent la possibilité de traiter le son directement dans le contexte d'un web worker. En date du 29 August 2014, ils ne sont encore implémentés par aucun navigateur. Lorsqu'ils seront implémentés, ils remplaceront {{domxref("ScriptProcessorNode")}}, et les autres fonctionnalités mentionnées dans la section Traitement audio avec JavaScript ci-avant.

- -
-
{{domxref("AudioWorkerNode")}}
-
Un objet AudioWorkerNode représente un {{domxref("AudioNode")}} qui interagit avec le thread d'un worker pour générer, traiter, ou analyse le son directement.
-
{{domxref("AudioWorkerGlobalScope")}}
-
Un objet AudioWorkerGlobalScope est un objet dérivé d'un objet DedicatedWorkerGlobalScope. Il représente le contexte d'un worker dans lequel un script de traitement audio est lancé; il est conçu pour permettre la génération, le traitement, et l'analyse de données audio directement avec JavaScript dans le thread d'un worker.
-
{{domxref("AudioProcessEvent")}}
-
UN objet Event est transmis aux objets {{domxref("AudioWorkerGlobalScope")}} pour effectuer un traitement audio.
-
- -

Objets obsolètes

- -

Les objets suivants étaient définis dans les versions précédentes de la spécification, mais sont maintenant obsolètes et ont été remplacés.

- -
-
{{domxref("JavaScriptNode")}}
-
Utilisé pour le traitement du son directement en Javascript. Cet objet est obsolète, et a été remplacé par {{domxref("ScriptProcessorNode")}}.
-
{{domxref("WaveTableNode")}}
-
Utilisé pour définir une forme d'onde périodique. Cet objet est obsolète, et a été remplacé par {{domxref("PeriodicWave")}}.
-
- -

Exemple

- -

Cet exemple montre l'utilisation d'un grand nombre de fonctions Web Audio. La démo est disponible en ligne sur Voice-change-o-matic (voir aussi le code source complet sur Github) —c'est une démo expérimentale d'application pour modifier la voix; baissez le son de vos enceintes pour l'utiliser, au moins au début !

- -

Les lignes qui concernent la Web Audio API sont surlignées; si vous voulez en savoir davantage sur les différentes méthodes, consultez la documentation.

- -
var contexteAudio = new (window.AudioContext || window.webkitAudioContext)(); // définition du contexte audio
-// les navigateurs avec un moteur Webkit/blink demandent un préfixe
-
-var voixSelectionnee = document.getElementById("voice"); // case à cocher pour la sélection d'effets de voix
-var visualisationSelectionnee = document.getElementById("visual"); // case à cocher pour la sélection d'options de visualisation audio
-var silence = document.querySelector('.mute'); // bouton pour couper le son
-var renduVisuel; // requestAnimationFrame
-
-var analyseur = contexteAudio.createAnalyser();
-var distorsion = contexteAudio.createWaveShaper();
-var gainVolume = contexteAudio.createGain();
-var filtreAccordable = contexteAudio.createBiquadFilter();
-
-function creerCourbeDistorsion(taille) { // fonction qui crée une forme de courbe qui sera utilisée par le générateur de l'onde de distorsion
-  var k = typeof taille === 'number' ? taille : 50,
-    nombre_echantillons = 44100,
-    courbe = new Float32Array(nombre_echantillons),
-    angle = Math.PI / 180,
-    i = 0,
-    x;
-  for ( ; i < nombre_echantillons; ++i ) {
-    x = i * 2 / nombre_echantillons - 1;
-    courbe[i] = ( 3 + k ) * x * 20 * angle / ( Math.PI + k * Math.abs(x) );
-  }
-  return courbe;
-};
-
-navigator.getUserMedia (
-  // contraintes - uniquement audio dans cet exemple
-  {
-    audio: true
-  },
-
-  // callback de succès
-  function(flux) {
-    source = contexteAudio.createMediaStreamSource(flux);
-    source.connect(analyseur);
-    analyseur.connect(distorsion);
-    distorsion.connect(filtreAccordable);
-    filtreAccordable.connect(gainVolume);
-    gainVolume.connect(contexteAudio.destination); // connecte les différents noeuds de graphes audio entre eux
-
-    genererVisualisation(flux);
-    voiceChange();
-
-  },
-
-  // callback d'erreur
-  function(err) {
-    console.log("L'erreur GUM suivante a eu lieu : " + err);
-  }
-);
-
-function genererVisualisation(flux) {
-  const LARGEUR = canvas.width;
-  const HAUTEUR = canvas.height;
-
-  var parametreVisualisation = visualisationSelectionnee.value;
-  console.log(parametreVisualisation);
-
-  if(parametreVisualisation == "sinewave") {
-    analyseur.fftSize = 2048;
-    var tailleBuffer = analyseur.frequencyBinCount; // la moitié de la valeur FFT (Transformation de Fourier rapide)
-    var tableauDonnees = new Uint8Array(tailleBuffer); // crée un tableau pour stocker les données
-
-    canvasCtx.clearRect(0, 0, LARGEUR, HAUTEUR);
-
-    function draw() {
-
-      renduVisuel = requestAnimationFrame(draw);
-
-      analyseur.getByteTimeDomainData(tableauDonnees); // récupère les données de l'onde de forme et les met dans le tableau créé
-
-      canvasCtx.fillStyle = 'rgb(200, 200, 200)'; // dessine une onde dans le canvas
-      canvasCtx.fillRect(0, 0, LARGEUR, HAUTEUR);
-
-      canvasCtx.lineWidth = 2;
-      canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
-
-      canvasCtx.beginPath();
-
-      var sliceWidth = LARGEUR * 1.0 / tailleBuffer;
-      var x = 0;
-
-      for(var i = 0; i < tailleBuffer; i++) {
-
-        var v = tableauDonnees[i] / 128.0;
-        var y = v * HAUTEUR/2;
-
-        if(i === 0) {
-          canvasCtx.moveTo(x, y);
-        } else {
-          canvasCtx.lineTo(x, y);
-        }
-
-        x += sliceWidth;
-      }
-
-      canvasCtx.lineTo(canvas.width, canvas.height/2);
-      canvasCtx.stroke();
-    };
-
-    draw();
-
-  } else if(parametreVisualisation == "off") {
-    canvasCtx.clearRect(0, 0, LARGEUR, HAUTEUR);
-    canvasCtx.fillStyle = "red";
-    canvasCtx.fillRect(0, 0, LARGEUR, HAUTEUR);
-  }
-
-}
-
-function modifierVoix() {
-  distorsion.curve = new Float32Array;
-  filtreAccordable.gain.value = 0; // reset les effets à chaque fois que la fonction modifierVoix est appelée
-
-  var choixVoix = voixSelectionnee.value;
-  console.log(choixVoix);
-
-  if(choixVoix == "distortion") {
-    distorsion.curve = creerCourbeDistorsion(400); // applique la distorsion au son en utilisant le noeud d'onde de forme
-  } else if(choixVoix == "biquad") {
-    filtreAccordable.type = "lowshelf";
-    filtreAccordable.frequency.value = 1000;
-    filtreAccordable.gain.value = 25; // applique le filtre lowshelf aux sons qui utilisent le filtre accordable
-  } else if(choixVoix == "off") {
-    console.log("Choix de la voix désactivé"); // ne fait rien, quand l'option off est sélectionnée
-  }
-
-}
-
-// écouteurs d'évènements pour les changements de visualisation et de voix
-
-visualisationSelectionnee.onchange = function() {
-  window.cancelAnimationFrame(renduVisuel);
-  genererVisualisation(flux);
-}
-
-voixSelectionnee.onchange = function() {
-  modifierVoix();
-}
-
-silence.onclick = muterVoix;
-
-function muterVoix() { // allumer / éteindre le son
-  if(silence.id == "") {
-    gainVolume.gain.value = 0; // gain à 0 pour éteindre le son
-    silence.id = "activated";
-    silence.innerHTML = "Unmute";
-  } else {
-    gainVolume.gain.value = 1; // gain à 1 pour allumer le son
-    silence.id = "";
-    silence.innerHTML = "Mute";
-  }
-}
-
- -

Spécifications

- - - - - - - - - - - - - - - - -
SpécificationStatutCommentaire
{{SpecName('Web Audio API')}}{{Spec2('Web Audio API')}}
- -

Compatibilité des navigateurs

- -

{{Compat("api.AudioContext", 0)}}

- -

Voir aussi

- - - -

Guides

- - - -

Démos

- - -

API

- - diff --git a/files/fr/web/api/web_audio_api/index.md b/files/fr/web/api/web_audio_api/index.md new file mode 100644 index 0000000000..087d05a380 --- /dev/null +++ b/files/fr/web/api/web_audio_api/index.md @@ -0,0 +1,429 @@ +--- +title: Web Audio API +slug: Web/API/Web_Audio_API +translation_of: Web/API/Web_Audio_API +--- +
+

La Web Audio API propose un système puissant et flexible pour contrôler les données audio sur internet. Elle permet notamment de sélectionner des sources audio (microphone, flux media), d'y ajouter des effets, de créer des visualisations, d'appliquer des effets de spatialisation (comme la balance), etc.

+
+ +

Concepts et usages

+ +

La Web Audio API effectue des opérations dans un contexte audio; elle a été conçue pour supporter le routing modulaire. Les opérations audio basiques sont réalisées via des noeuds audio reliés entre eux pour former un graphe de routage audio. Plusieurs sources - avec différents types d'agencements de canaux - peuvent être supportées, même dans un seul contexte. Ce design modulaire et flexible permet de créer des fonctions audio complexes avec des effets dynamiques.

+ +

Les noeuds audio sont reliés au niveau de leurs entrées et sorties, formant des chaînes ou des réseaux simples. Il peut y avoir une ou plusieurs sources. Les sources fournissent des tableaux d'intensités sonores (échantillons), souvent plusieurs dizaines de milliers par seconde. Ceux-ci peuvent être calculées mathématiquement (avec un {{domxref("OscillatorNode")}}), ou peuvent provenir de fichiers sons ou vidéos (comme {{domxref("AudioBufferSourceNode")}} ou {{domxref("MediaElementAudioSourceNode")}}) ou de flux audio ({{domxref("MediaStreamAudioSourceNode")}}). En réalité, les fichiers sons sont eux-même des enregistrements d'intensités sonores, qui viennent de microphones ou d'instruments électriques, et sont mixés dans une seule onde complexe.

+ +

Les sorties de ces noeuds peuvent être liées aux entrées d'autres noeuds, qui mixent ces flux d'échantillons sonores ou les séparent en différents flux. Une modification courante est la multiplications des échantillons par une valeur afin d'en augmenter ou diminuer le volume sonore (comme c'est le cas pour le {{domxref("GainNode")}}). Le son est ensuite lié à une destination ({{domxref("AudioContext.destination")}}), qui l'envoie aux enceintes ou au casque audio. Cette dernière connexion n'est utile que si le son doit être entendu.
+
+ Un processus de développement typique avec web audio ressemble à ceci :

+ + + +

Un diagramme de boîte avec une boîte extérieure intitulée contexte audio et trois boîtes à l'intérieur intitulées source, effets et destination. Les trois boîtes intérieures ont des flèches qui pointent de la gauche vers la droite, indiquant le sens du flux de l'information audio.

+ +

Le timing est contrôlé avec une grande précision et une latence faible, ce qui permet aux développeurs d'écrire un code qui réagit précisément aux événements et qui est capable de traiter des échantillons précis, même avec un taux d'échantillonnage élevé. Cela permet d'envisager des applications telles que des boîtes à rythme ou des séquenceurs.

+ +

La Web Audio API permet également de contrôler la spatialisation du son. En utilisant un système basé sur le modèle émetteur - récepteur, elle permet le contrôle de la balance ainsi que la gestion de l'atténuation du son en fonction de la distance, ou effet doppler, induite par un déplacement de la source sonore (ou de l'auditeur).

+ +
+

Note : Vous pouvez lire d'avantage de détails sur la Web Audio API en vous rendant sur notre article Concepts de base de la Web Audio API.

+
+ +

Interface de la Web Audio API

+ +

La Web Audio API expose 28 interfaces avec des événements associés, classés selon leur fonction en 9 catégories.

+ +

Définition du graphe audio

+ +

Conteneurs et définitions qui donnent sa forme au graphe audio

+ +
+
{{domxref("AudioContext")}}
+
Un objet AudioContext désigne un graphe de traitement audio construit à partir de modules reliés entre eux, chacun représenté par un noeud audio ({{domxref("AudioNode")}}). Le contexte audio contrôle la création des noeuds qu'il contient, ainsi que l'exécution du traitement audio, et du décodage. Il est nécessaire de créer un AudioContext avant de faire quoi que ce soit d'autre, puisque tout se passe dans un contexte.
+
{{domxref("AudioNode")}}
+
Un objet AudioNode est un module de traitement audio, tel qu'une source audio (c'est-à-dire un élément HTML {{HTMLElement("audio")}} ou {{HTMLElement("video")}}), une destination audio, un module de traitement intermédiaire (par exemple un filtre {{domxref("BiquadFilterNode")}}), ou un contrôle du volume {{domxref("GainNode")}}).
+
{{domxref("AudioParam")}}
+
Un objet AudioParam est un paramètre audio, qui est lié à un {{domxref("AudioNode")}}. On peut lui assigner une valeur ou un changement de valeur, que l'on peut programmer à un moment spécifique et/ou selon un motif particulier.
+
{{event("ended_(Web_Audio)", "ended")}} (event)
+
L'évènement ended est diffusé lorsque la lecture s'arrête en arrivant à la fin d'un media.
+
+ +

Définition des sources audio

+ +
+
{{domxref("OscillatorNode")}}
+
Un objet OscillatorNode est un module de traitement audio qui génère la création d'une onde sinusoïdale d'une certaine fréquence.
+
{{domxref("AudioBuffer")}}
+
Un objet AudioBuffer est un petit morceau de contenu audio monté en mémoire. Il peut être créé à partir d'un fichier audio avec la méthode {{ domxref("AudioContext.decodeAudioData()") }}, ou à partir de données brutes en utilisant {{ domxref("AudioContext.createBuffer()") }}. Une fois décodé sous cette forme, la source audio peut être placée dans un {{ domxref("AudioBufferSourceNode") }}.
+
{{domxref("AudioBufferSourceNode")}}
+
Un objet AudioBufferSourceNode est une source audio composée de données audio montées en mémoire dans un {{domxref("AudioBuffer")}}. C'est un {{domxref("AudioNode")}} qui se comporte comme une source audio.
+
{{domxref("MediaElementAudioSourceNode")}}
+
Un objet MediaElementAudioSourceNode est une source audio composée d'un élément  HTML5 {{ htmlelement("audio") }} ou {{ htmlelement("video") }}. C'est un {{domxref("AudioNode")}} qui se comporte comme une source audio.
+
{{domxref("MediaStreamAudioSourceNode")}}
+
Un objet MediaStreamAudioSourceNode est une source audio composée d'un WebRTC {{domxref("MediaStream")}} (tel qu'une webcam ou un microphone). C'est un {{domxref("AudioNode")}} qui se comporte comme une source audio.
+
+ +

Définition des filtres d'effets audio

+ +
+
{{domxref("BiquadFilterNode")}}
+
Un objet BiquadFilterNode est un simple filtre de bas niveau. Il peut s'agir de différents types de filtres, contrôle du volume ou égaliseurs graphiques. Un BiquadFilterNode a toujours exactement une entrée et une sortie.
+
{{domxref("ConvolverNode")}}
+
Un objet ConvolverNode est un {{domxref("AudioNode")}} qui exécute une circonvolution linéaire sur un AudioBuffer donné, souvent utilisé pour créer un effet de réverbération.
+
{{domxref("DelayNode")}}
+
Un objet DelayNode est une ligne à retard numérique, c'est-à-dire un module de traitement automatique qui provoque un délai entre l'arrivée du son en entrée et sa propagation en sortie.
+
{{domxref("DynamicsCompressorNode")}}
+
Un objet DynamicsCompressorNode permet un effet de compression, qui réduit le volume des parties les plus fortes du signal de façon à éviter les effets de clipping et la distortion qui peuvent se produire lorsque des sons multiples sont diffusés simultanément.
+
{{domxref("GainNode")}}
+
Un objet GainNode  représente une modification du volume sonore. C'est un module de traitement audio qui provoque l'application d'un gain aux données récupérées en entrée avant leur propagation vers la sortie.
+
{{domxref("WaveShaperNode")}}
+
Un objet WaveShaperNode représente une distortion non linéaire. C'est un {{domxref("AudioNode")}} qui utilise une courbe pour appliquer au signal une distortion de mise en forme des ondes. En dehors de l'effet de distortion évident, il est souvent utilisé pour donner un caractère plus chaleureux au son. 
+
{{domxref("PeriodicWave")}}
+
Un objet {{domxref("PeriodicWave")}} est utilisé pour définir une forme d'onde périodique qui peut être utilisée pour façonner la sortie d'un {{ domxref("OscillatorNode") }}.
+
+ +

Définition des destinations audio

+ +

Une fois que le signal audio a été traité, ces interfaces définissent sa destination.

+ +
+
{{domxref("AudioDestinationNode")}}
+
Un noeud AudioDestinationNode représente la destination finale d'une source audio source dans un contexte donné — en général les enceintes du matériel.
+
{{domxref("MediaStreamAudioDestinationNode")}}
+
Un noeud MediaStreamAudioDestinationNode représente une destination audio constituée d'un {{domxref("MediaStream")}} WebRTC à une seule piste AudioMediaStreamTrack; il peut être utilisé de façon similaire à un {{domxref("MediaStream")}} obtenu avec {{ domxref("Navigator.getUserMedia") }}. C'est un {{domxref("AudioNode")}} qui se comporte comme une destination audio.
+
+ +

Analyse des données et visualisation

+ +
+
{{domxref("AnalyserNode")}}
+
Un objet AnalyserNode fournit en temps réel des informations concernant la fréquence et le temps, afin de les analyser et les visualiser.
+
+ +

Division et fusion des pistes audio

+ +
+
{{domxref("ChannelSplitterNode")}}
+
Un noeud ChannelSplitterNode prend en entrée une source audio et sépare ses différentes pistes en une série de sorties mono.
+
{{domxref("ChannelMergerNode")}}
+
Un noeud ChannelMergerNode réunit différentes entrées mono en une seule sortie. Chaque entrée devient une des pistes de la sortie unique.
+
+ +

Spatialisation audio

+ +
+
{{domxref("AudioListener")}}
+
Un objet AudioListener représente la position et l'orientation de l'unique personne écoutant la scene audio utilisée dans la spatialisation audio.
+
{{domxref("PannerNode")}}
+
Un noeud PannerNode représente le comportement d'un signal dans l'espace. C'est un module de traitement audio qui décrit sa position avec des coordonnées cartésiennes fondées sur la règle de la main droite; ses mouvements utilisent un vecteur de vélocité et sa directionnalité un cône de direction.
+
+ +

Traitement audio avec JavaScript

+ +
+

Note : Au jour de la publication de la spécification Web Audio API le 29 août 2014, ces fonctionnalités sont dépréciées, et seront bientôt remplacées par {{ anch("Audio_Workers") }}.

+
+ +
+
{{domxref("ScriptProcessorNode")}}
+
Un noeud ScriptProcessorNode permet de générer, traiter ou analyser du son avec JavaScript. C'est un module de traitement audio qui est lié à deux buffers, l'un en entrée, et l'autre en sortie. Un évènement implémentant {{domxref("AudioProcessingEvent")}} est envoyé à l'objet à chaque fois que le buffer d'entrée reçoit de nouvelles données, et le gestionnaire d'évènement prend fin lorsque les nouvelles données ont été communiquées au buffer de sortie. 
+
{{event("audioprocess")}} (event)
+
L'évènement audioprocess est émis lorsque le buffer d'entrée d'un {{domxref("ScriptProcessorNode")}} de la Web Audio API est prêt à être traité.
+
{{domxref("AudioProcessingEvent")}}
+
L'objet  AudioProcessingEvent est envoyé aux fonctions de callback qui écoutent l'évènement audioprocess.
+
+ +

Traitement audio hors ligne ou en tâche de fond

+ +

Il est possible de traiter et exporter un graphe audio très rapidement en tâche de fond — en l'exportant dans un {{domxref("AudioBuffer")}} plutôt que sur les enceintes du matériel — grâce aux objets suivants.

+ +
+
{{domxref("OfflineAudioContext")}}
+
Un objet OfflineAudioContext est un {{domxref("AudioContext")}} qui représente un graphe de traitement audio construit à partir de noeuds audio. A la différence du AudioContext standard, un OfflineAudioContext n'exporte pas vraiment le son, mais le génère, aussi vite que possible, dans un buffer.
+
{{event("complete")}} (event)
+
Un évènement complete est émis lorsque le rendu d'un {{domxref("OfflineAudioContext")}} est terminé.
+
{{domxref("OfflineAudioCompletionEvent")}}
+
The OfflineAudioCompletionEvent est envoyé aux fonctions de callback qui écoutent l'évènement {{event("complete")}} event implements this interface.
+
+ +

Audio Workers

+ +

Les Audio workers offrent la possibilité de traiter le son directement dans le contexte d'un web worker. En date du 29 August 2014, ils ne sont encore implémentés par aucun navigateur. Lorsqu'ils seront implémentés, ils remplaceront {{domxref("ScriptProcessorNode")}}, et les autres fonctionnalités mentionnées dans la section Traitement audio avec JavaScript ci-avant.

+ +
+
{{domxref("AudioWorkerNode")}}
+
Un objet AudioWorkerNode représente un {{domxref("AudioNode")}} qui interagit avec le thread d'un worker pour générer, traiter, ou analyse le son directement.
+
{{domxref("AudioWorkerGlobalScope")}}
+
Un objet AudioWorkerGlobalScope est un objet dérivé d'un objet DedicatedWorkerGlobalScope. Il représente le contexte d'un worker dans lequel un script de traitement audio est lancé; il est conçu pour permettre la génération, le traitement, et l'analyse de données audio directement avec JavaScript dans le thread d'un worker.
+
{{domxref("AudioProcessEvent")}}
+
UN objet Event est transmis aux objets {{domxref("AudioWorkerGlobalScope")}} pour effectuer un traitement audio.
+
+ +

Objets obsolètes

+ +

Les objets suivants étaient définis dans les versions précédentes de la spécification, mais sont maintenant obsolètes et ont été remplacés.

+ +
+
{{domxref("JavaScriptNode")}}
+
Utilisé pour le traitement du son directement en Javascript. Cet objet est obsolète, et a été remplacé par {{domxref("ScriptProcessorNode")}}.
+
{{domxref("WaveTableNode")}}
+
Utilisé pour définir une forme d'onde périodique. Cet objet est obsolète, et a été remplacé par {{domxref("PeriodicWave")}}.
+
+ +

Exemple

+ +

Cet exemple montre l'utilisation d'un grand nombre de fonctions Web Audio. La démo est disponible en ligne sur Voice-change-o-matic (voir aussi le code source complet sur Github) —c'est une démo expérimentale d'application pour modifier la voix; baissez le son de vos enceintes pour l'utiliser, au moins au début !

+ +

Les lignes qui concernent la Web Audio API sont surlignées; si vous voulez en savoir davantage sur les différentes méthodes, consultez la documentation.

+ +
var contexteAudio = new (window.AudioContext || window.webkitAudioContext)(); // définition du contexte audio
+// les navigateurs avec un moteur Webkit/blink demandent un préfixe
+
+var voixSelectionnee = document.getElementById("voice"); // case à cocher pour la sélection d'effets de voix
+var visualisationSelectionnee = document.getElementById("visual"); // case à cocher pour la sélection d'options de visualisation audio
+var silence = document.querySelector('.mute'); // bouton pour couper le son
+var renduVisuel; // requestAnimationFrame
+
+var analyseur = contexteAudio.createAnalyser();
+var distorsion = contexteAudio.createWaveShaper();
+var gainVolume = contexteAudio.createGain();
+var filtreAccordable = contexteAudio.createBiquadFilter();
+
+function creerCourbeDistorsion(taille) { // fonction qui crée une forme de courbe qui sera utilisée par le générateur de l'onde de distorsion
+  var k = typeof taille === 'number' ? taille : 50,
+    nombre_echantillons = 44100,
+    courbe = new Float32Array(nombre_echantillons),
+    angle = Math.PI / 180,
+    i = 0,
+    x;
+  for ( ; i < nombre_echantillons; ++i ) {
+    x = i * 2 / nombre_echantillons - 1;
+    courbe[i] = ( 3 + k ) * x * 20 * angle / ( Math.PI + k * Math.abs(x) );
+  }
+  return courbe;
+};
+
+navigator.getUserMedia (
+  // contraintes - uniquement audio dans cet exemple
+  {
+    audio: true
+  },
+
+  // callback de succès
+  function(flux) {
+    source = contexteAudio.createMediaStreamSource(flux);
+    source.connect(analyseur);
+    analyseur.connect(distorsion);
+    distorsion.connect(filtreAccordable);
+    filtreAccordable.connect(gainVolume);
+    gainVolume.connect(contexteAudio.destination); // connecte les différents noeuds de graphes audio entre eux
+
+    genererVisualisation(flux);
+    voiceChange();
+
+  },
+
+  // callback d'erreur
+  function(err) {
+    console.log("L'erreur GUM suivante a eu lieu : " + err);
+  }
+);
+
+function genererVisualisation(flux) {
+  const LARGEUR = canvas.width;
+  const HAUTEUR = canvas.height;
+
+  var parametreVisualisation = visualisationSelectionnee.value;
+  console.log(parametreVisualisation);
+
+  if(parametreVisualisation == "sinewave") {
+    analyseur.fftSize = 2048;
+    var tailleBuffer = analyseur.frequencyBinCount; // la moitié de la valeur FFT (Transformation de Fourier rapide)
+    var tableauDonnees = new Uint8Array(tailleBuffer); // crée un tableau pour stocker les données
+
+    canvasCtx.clearRect(0, 0, LARGEUR, HAUTEUR);
+
+    function draw() {
+
+      renduVisuel = requestAnimationFrame(draw);
+
+      analyseur.getByteTimeDomainData(tableauDonnees); // récupère les données de l'onde de forme et les met dans le tableau créé
+
+      canvasCtx.fillStyle = 'rgb(200, 200, 200)'; // dessine une onde dans le canvas
+      canvasCtx.fillRect(0, 0, LARGEUR, HAUTEUR);
+
+      canvasCtx.lineWidth = 2;
+      canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
+
+      canvasCtx.beginPath();
+
+      var sliceWidth = LARGEUR * 1.0 / tailleBuffer;
+      var x = 0;
+
+      for(var i = 0; i < tailleBuffer; i++) {
+
+        var v = tableauDonnees[i] / 128.0;
+        var y = v * HAUTEUR/2;
+
+        if(i === 0) {
+          canvasCtx.moveTo(x, y);
+        } else {
+          canvasCtx.lineTo(x, y);
+        }
+
+        x += sliceWidth;
+      }
+
+      canvasCtx.lineTo(canvas.width, canvas.height/2);
+      canvasCtx.stroke();
+    };
+
+    draw();
+
+  } else if(parametreVisualisation == "off") {
+    canvasCtx.clearRect(0, 0, LARGEUR, HAUTEUR);
+    canvasCtx.fillStyle = "red";
+    canvasCtx.fillRect(0, 0, LARGEUR, HAUTEUR);
+  }
+
+}
+
+function modifierVoix() {
+  distorsion.curve = new Float32Array;
+  filtreAccordable.gain.value = 0; // reset les effets à chaque fois que la fonction modifierVoix est appelée
+
+  var choixVoix = voixSelectionnee.value;
+  console.log(choixVoix);
+
+  if(choixVoix == "distortion") {
+    distorsion.curve = creerCourbeDistorsion(400); // applique la distorsion au son en utilisant le noeud d'onde de forme
+  } else if(choixVoix == "biquad") {
+    filtreAccordable.type = "lowshelf";
+    filtreAccordable.frequency.value = 1000;
+    filtreAccordable.gain.value = 25; // applique le filtre lowshelf aux sons qui utilisent le filtre accordable
+  } else if(choixVoix == "off") {
+    console.log("Choix de la voix désactivé"); // ne fait rien, quand l'option off est sélectionnée
+  }
+
+}
+
+// écouteurs d'évènements pour les changements de visualisation et de voix
+
+visualisationSelectionnee.onchange = function() {
+  window.cancelAnimationFrame(renduVisuel);
+  genererVisualisation(flux);
+}
+
+voixSelectionnee.onchange = function() {
+  modifierVoix();
+}
+
+silence.onclick = muterVoix;
+
+function muterVoix() { // allumer / éteindre le son
+  if(silence.id == "") {
+    gainVolume.gain.value = 0; // gain à 0 pour éteindre le son
+    silence.id = "activated";
+    silence.innerHTML = "Unmute";
+  } else {
+    gainVolume.gain.value = 1; // gain à 1 pour allumer le son
+    silence.id = "";
+    silence.innerHTML = "Mute";
+  }
+}
+
+ +

Spécifications

+ + + + + + + + + + + + + + + + +
SpécificationStatutCommentaire
{{SpecName('Web Audio API')}}{{Spec2('Web Audio API')}}
+ +

Compatibilité des navigateurs

+ +

{{Compat("api.AudioContext", 0)}}

+ +

Voir aussi

+ + + +

Guides

+ + + +

Démos

+ + +

API

+ + diff --git a/files/fr/web/api/web_audio_api/using_web_audio_api/index.html b/files/fr/web/api/web_audio_api/using_web_audio_api/index.html deleted file mode 100644 index 26ea00da32..0000000000 --- a/files/fr/web/api/web_audio_api/using_web_audio_api/index.html +++ /dev/null @@ -1,277 +0,0 @@ ---- -title: Utiliser la Web Audio API -slug: Web/API/Web_Audio_API/Using_Web_Audio_API -translation_of: Web/API/Web_Audio_API/Using_Web_Audio_API ---- - -

La Web Audio API offre un méchanisme à la fois simple et puissant pour implémenter et manipuler le contenu audio dans une application web. Elle permet de manipuler mixages audio, effets, balance, etc. Cet article donne les bases pour l'utiliser, à travers quelques exemples simples.

- -
-

La Web Audio API ne vient pas remplacer l'élément <audio>, mais plutôt le compléter, de même que l'API Canvas 2D coexiste avec l'élément <video>. Si vous avez seulement besoin de contrôler la lecture d'un fichier audio, <audio> est probablement une meilleure solution, plus rapide. Si vous voulez procéder à un traitement audio plus complexe et à la lecture d'une source, la Web Audio API offre davantage de possibilités en termes de puissance et de contrôle.

- -

L'une des particularités de la Web Audio API est qu'elle n'a pas de limites au niveau de la programmation du son. Par exemple, le nombre de sons que l'on peut appeler en même temps n'est pas plafonnée. Certains processeurs sont potentiellement capables de jouer plus d'un millier de sons simultanément sans saccades.

-
- -

Exemples

- -

Afin d'expliquer l'utilisation de la Web Audio API, nous avons créé un certain nombre d'exemples qui seront étoffés au fur et à mesure. N'hésitez pas à en ajouter d'autres et à suggérer des améliorations !

- -

Notre premier exemple est Voice-change-O-matic, une application web de déformation de la voix, qui permet de choisir différents effets et modes de visualisation. Cette application est rudimentaire, mais elle permet de montrer l'utilisation de plusieurs fonctionnalités de la Web Audio API combinées ensemble  (run the Voice-change-O-matic live).

- -

Une boîte à rythme avec des contrôles pour la lecture, le volume et le pan

- -

Concepts de base

- -
-

Note : la plupart des extraits de code dans cette section viennent de l'exemple Violent Theremin.

-
- -

La Web Audio API impliqe de réaliser les opérations de traitement audio dans un contexte audio, et elle a été conçue pour permettre le routage modulaire. Les opérations de traitement de base sont réalisées par des noeuds audio, qui sont reliés entre eux pour former un graphe de routage audio. Plusieurs sources — avec différentes configuration de canaux — peuvent cohabiter dans un seul contexte. Ce design modulaire offre la flexibilité nécessaire pour créer des fonctions complexes avec des effets dynamiques.

- -

Les noeuds audio sont reliés au niveau de leurs entrées et sorties. Ils forment une chaîne qui commence avec une ou plusieurs sources, traverse un ou plusieurs noeuds de traitement, et se termine par une destination (bien qu'il ne soit pas néessaire d'avoir une destination si l'on souhaite simplement visualiser des données audio). Un scénario simple, représentatif de la Web Audio API, pourrait ressembler à ceci :

- -
    -
  1. Création d'un contexte audio
  2. -
  3. Dans ce contexte, création des sources — telles que <audio>, oscillateur, flux
  4. -
  5. Création des noeuds d'effets, tels que réverb, filtres biquad, balance,  compresseur
  6. -
  7. Choix final de la sortie audio, par exemple les enceintes du système 
  8. -
  9. Connection des sources aux effets, et des effets à la sortie.
  10. -
- -

Création d'un contexte audio

- -

Commencez par créer une instance de AudioContext sur laquelle vous allez créer un graphe audio. L'exemple le plus simple ressemblerait à ceci:

- -
var contexteAudio = new AudioContext();
-
- -
-

Note : On peut créer plusieurs contextes audio dans le même document, bien que ce soit probablement superflu dans la plupart des cas.

-
- -

Il faut rajouter une version préfixée pour les navigateurs Webkit/Blink browsers, tout en conservant la version non préfixée pour Firefox (desktop/mobile/OS). Ce qui donne :

- -
var contexteAudio = new (window.AudioContext || window.webkitAudioContext)();
-
- -
-

Note : Safari risque de planter si l'objet window n'est pas explicitement mentionné lors de la création d'un contexte audio

-
- -

Création d'une source audio

- -

Maintenant que nous avons créé un contexte, nous allons utiliser les méthodes de ce contexte pour quasiment tout ce qui nous reste à faire. La première étape consiste à créer une source audio. Les sources peuvent être de provenance diverse :

- - - -

Pour notre exemple nous nous contenterons de créer un oscillateur pour générer un son simple comme source, et un noeud de gain pour contrôler le volume:

- -
var oscillateur = contexteAudio.createOscillator();
-var noeudGain = contexteAudio.createGain();
-
- -
-

Note : Pour jouer un fichier audio directement, il faut charger le fichier en XHR, le décoder en mémoire tampon, puis associer le tampon à une source. Voir l'exemple Voice-change-O-matic.

-
- -
-

Note : Scott Michaud a écrit la librairie AudioSampleLoader, très pratique pour charger et décoder un ou plusieurs extraits audio. Elle peut aider à simplifier le processus de chargement XHR / mémoire tampon décrit dans la note précédente.

-
- -

Lien entre les noeuds source et destination

- -

Pour faire sortir le son dans vos enceintes, il faut relier la source et la destination. Pour cela on appelle la méthode connect sur le noeud source, le noeud de destination étant passé en argument. La méthode connect est disponible sur la plupart des types de noeuds.

- -

La sortie par défaut du matériel (en général les enceintes) est accessible via {{ domxref("AudioContext.destination") }}. Pour connecter l'oscillateur, le noeud de gain et la destination, on écrirait les lignes suivantes:

- -
oscillateur.connect(noeudGain);
-noeudGain.connect(contexteAudio.destination);
-
- -

On peut connecter autant de noeuds qu'on le souhaite (cf. Voice-change-O-matic). Par exemple:

- -
source = contexteAudio.createMediaStreamSource(stream);
-source.connect(analyser);
-analyser.connect(distortion);
-distortion.connect(biquadFilter);
-biquadFilter.connect(convolver);
-convolver.connect(noeudGain);
-noeudGain.connect(contexteAudio.destination);
-
- -

Ce code créerait le graphe audio suivant :

- -

Un graphe audio avec un élément audio source connecté à la destination par défaut

- -

Il est possible de connecter plusieurs noeuds à un seul noeud, par exemple pour mixer plusieurs sources ensemble, et les passer dans un seul noeud d'effet, tel qu'un noeud de gain.

- -
-

Note : Depuis Firefox 32, les outils de développement intégrés incluent un éditeur audio,  très utile pour débugger les graphes audio.

-
- -

Lecture du son et définition du pitch

- -

Maintenant que le graphe audio est en place, nous pouvons ajuster certains aspects du son en définissant la valeur de certaines propriétés ou en utilsant ses méthodes. L'exemple suivant spécifie un pitch en hertz pour un oscillateur, lui assigne un type, et demande à l'oscillateur de jouer le son.

- -
oscillateur.type = 'sine'; // onde sinusoïdale — les autres valeurs possible sont : 'square', 'sawtooth', 'triangle' et 'custom'
-oscillateur.frequency.value = 2500; // valeur en hertz
-oscillateur.start();
-
- -

Le code suivant, qui vient de l'exemple Violent Theremin, spécifie une valeur maximum pour le gain, et une valeur pour la fréquence:

- -
var largeur = window.innerWidth;
-var hauteur = window.innerHeight;
-
-var frequenceMax = 6000;
-var volumeMax = 1;
-
-var frequenceInitiale = 3000;
-var volumeInitial = 0.5;
-
-// paramètres de l'oscillateur
-
-oscillateur.type = 'sine'; // onde sinusoïdale — les autres valeurs possible sont : 'square', 'sawtooth', 'triangle' et 'custom'
-oscillateur.frequency.value = frequenceInitiale; // valeur en hertz
-oscillateur.start();
-
-noeudGain.gain.value = volumeInitial;
-
- -

On peut aussi réassigner les valeurs de fréquence et de pitch à chaque mouvement de la souris, en utilisant la position pour calculer un pourcentage des valeurs maximum de fréquence et de gain :

- -
// coordonnées de la souris
-
-var positionX;
-var positionY;
-
-// récupère les nouvelles coordonnées de la souris quand elle bouge
-// puis assigne les nouvelles valeurs de gain et de pitch
-
-document.onmousemove = updatePage;
-
-function updatePage(e) {
-    positionX = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
-    positionY = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
-
-    oscillateur.frequency.value = (positionX/largeur) * frequenceMax;
-    noeudGain.gain.value = (positionY/hauteur) * volumeMax;
-
-    canvasDraw();
-}
-
- -

Simple visualisation avec canvas

- -

On appelle une fonction canvasDraw() à chaque mouvement de la souris. Elle dessine une grappe de cercles à l'endroit où se trouve la souris, leur taille et couleur étant basées sur les valeurs de fréquence et de gain.

- -
function aleatoire(number1, number2) {
-  return number1 + (Math.floor(Math.random() * (number2 - number1)) + 1);
-}
-
-var canvas = document.querySelector('.canvas');
-canvas.width = largeur;
-canvas.height = hauteur;
-
-var contexteCanvas = canvas.getContext('2d');
-
-function canvasDraw() {
-  rX = positionX;
-  rY = positionY;
-  rC = Math.floor((noeudGain.gain.value / volumeMax) * 30);
-
-  canvasCtx.globalAlpha = 0.2;
-
-  for(i=1;i<=15;i=i+2) {
-    contexteCanvas.beginPath();
-    var chaineStyle = 'rgb(' + 100 + (i * 10) + ',' + Math.floor((noeudGain.gain.value / volumeMax) * 255);
-    chaineStyle += ',' + Math.floor((oscillateur.frequency.value / frequenceMax) * 255) + ')';
-    contexteCanvas.fillStyle = chaineStyle;
-    contexteCanvas.arc(rX + aleatoire(0, 50), rY + aleatoire(0, 50), rC / 2 + i, (Math.PI / 180) * 0, (Math.PI / 180) * 360, false);
-    contexteCanvas.fill();
-    contexteCanvas.closePath();
-  }
-}
- -

Couper le son du theremin

- -

Quand on appuie sur le bouton pour couper le son, la fonction ci-dessous est appelée, qui déconnecte le noeud de gain du noeud de destination, cassant ainsi le graphe de façon à ce qu'aucun son ne soit produit. Appuyer de nouveau sur le bouton a l'effet inverse.

- -
var coupeSon = document.querySelector('.mute');
-
-coupeSon.onclick = function() {
-  if(coupeSon.id == "") {
-    noeudGain.disconnect(contexteAudio.destination);
-    coupeSon.id = "activated";
-    coupeSon.innerHTML = "Unmute";
-  } else {
-    noeudGain.connect(contexteAudio.destination);
-    coupeSon.id = "";
-    coupeSon.innerHTML = "Mute";
-  }
-}
-
- -

Autres options des noeuds

- -

On peut créer un grand nombre d'autres noeuds avec la Web Audio API. De façon générale, ils fonctionnent de façon très similaire à ceux que nous venons de voir: on crée un noeud, le connecte avec d'autres noeuds, et on manipule ensuite ses propriétés et méthodes pour agir sur la source.

- -

Ce document passe en revue quelques-uns des outils et effets disponibles; vous trouverez davantage de détails sur les pages de référence de la {{ domxref("Web_Audio_API") }}.

- -

Noeuds modulateurs d'onde

- -

On peut créer un noeud modulatur d'onde avec la méthode {{ domxref("AudioContext.createWaveShaper") }} :

- -
var distortion = contexteAudio.createWaveShaper();
-
- -

On associe ensuite à cet objet une forme d'onde définie mathématiquement, qui est appliquée à l'onde de base pour créer un effet de distortion. Ecrire son propre algorithme n'est pas si simple, et pour commencer le mieux est encore d'en chercher un sur le Web. Par exemple, nous avons trouvé celui-ci sur Stack Overflow:

- -
function genererCourbeDistortion(amount) {
-  var k = typeof amount === 'number' ? amount : 50,
-    n_samples = 44100,
-    curve = new Float32Array(n_samples),
-    deg = Math.PI / 180,
-    i = 0,
-    x;
-  for ( ; i < n_samples; ++i ) {
-    x = i * 2 / n_samples - 1;
-    curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );
-  }
-  return curve;
-};
-
- -

L'exemple suivant, qui vient de Voice-change-O-matic, connecte un noeud de  distortion à un graphe audio, puis applique l'algorithme de forme d'onde précédent au noeud de distortion :

- -
source.connect(analyser);
-analyser.connect(distortion);
-distortion.connect(biquadFilter);
-
-...
-
-distortion.curve = genererCourbeDistortion(400);
-
- -

Filtre biquad

- -

Les filtres biquad ont de nombreuses options. Nous montrons ici comment créer un filtre biquad avec la méthode {{domxref("AudioContext.createBiquadFilter")}}.

- -
var filtreBiquad = contexteAudio.createBiquadFilter();
-
- -

Le filtre utilisé dans la démo Voice-change-o-matic est un filtre lowshelf, qui amplifie le son au niveau des basses. Ici on augmente de 25 décibels toutes les fréquences en dessous de 1000.

- -
filtreBiquad.type = "lowshelf";
-filtreBiquad.frequency.value = 1000;
-filtreBiquad.gain.value = 25;
-
- -

Autres usages de la Web Audio API

- -

La Web Audio API peut avoir bien d'autres applications que la visualisation ou la spatialisation audio (comme gérer la balance d'un son). Nous détaillerons d'autres options dans des articles séparés.

diff --git a/files/fr/web/api/web_audio_api/using_web_audio_api/index.md b/files/fr/web/api/web_audio_api/using_web_audio_api/index.md new file mode 100644 index 0000000000..26ea00da32 --- /dev/null +++ b/files/fr/web/api/web_audio_api/using_web_audio_api/index.md @@ -0,0 +1,277 @@ +--- +title: Utiliser la Web Audio API +slug: Web/API/Web_Audio_API/Using_Web_Audio_API +translation_of: Web/API/Web_Audio_API/Using_Web_Audio_API +--- + +

La Web Audio API offre un méchanisme à la fois simple et puissant pour implémenter et manipuler le contenu audio dans une application web. Elle permet de manipuler mixages audio, effets, balance, etc. Cet article donne les bases pour l'utiliser, à travers quelques exemples simples.

+ +
+

La Web Audio API ne vient pas remplacer l'élément <audio>, mais plutôt le compléter, de même que l'API Canvas 2D coexiste avec l'élément <video>. Si vous avez seulement besoin de contrôler la lecture d'un fichier audio, <audio> est probablement une meilleure solution, plus rapide. Si vous voulez procéder à un traitement audio plus complexe et à la lecture d'une source, la Web Audio API offre davantage de possibilités en termes de puissance et de contrôle.

+ +

L'une des particularités de la Web Audio API est qu'elle n'a pas de limites au niveau de la programmation du son. Par exemple, le nombre de sons que l'on peut appeler en même temps n'est pas plafonnée. Certains processeurs sont potentiellement capables de jouer plus d'un millier de sons simultanément sans saccades.

+
+ +

Exemples

+ +

Afin d'expliquer l'utilisation de la Web Audio API, nous avons créé un certain nombre d'exemples qui seront étoffés au fur et à mesure. N'hésitez pas à en ajouter d'autres et à suggérer des améliorations !

+ +

Notre premier exemple est Voice-change-O-matic, une application web de déformation de la voix, qui permet de choisir différents effets et modes de visualisation. Cette application est rudimentaire, mais elle permet de montrer l'utilisation de plusieurs fonctionnalités de la Web Audio API combinées ensemble  (run the Voice-change-O-matic live).

+ +

Une boîte à rythme avec des contrôles pour la lecture, le volume et le pan

+ +

Concepts de base

+ +
+

Note : la plupart des extraits de code dans cette section viennent de l'exemple Violent Theremin.

+
+ +

La Web Audio API impliqe de réaliser les opérations de traitement audio dans un contexte audio, et elle a été conçue pour permettre le routage modulaire. Les opérations de traitement de base sont réalisées par des noeuds audio, qui sont reliés entre eux pour former un graphe de routage audio. Plusieurs sources — avec différentes configuration de canaux — peuvent cohabiter dans un seul contexte. Ce design modulaire offre la flexibilité nécessaire pour créer des fonctions complexes avec des effets dynamiques.

+ +

Les noeuds audio sont reliés au niveau de leurs entrées et sorties. Ils forment une chaîne qui commence avec une ou plusieurs sources, traverse un ou plusieurs noeuds de traitement, et se termine par une destination (bien qu'il ne soit pas néessaire d'avoir une destination si l'on souhaite simplement visualiser des données audio). Un scénario simple, représentatif de la Web Audio API, pourrait ressembler à ceci :

+ +
    +
  1. Création d'un contexte audio
  2. +
  3. Dans ce contexte, création des sources — telles que <audio>, oscillateur, flux
  4. +
  5. Création des noeuds d'effets, tels que réverb, filtres biquad, balance,  compresseur
  6. +
  7. Choix final de la sortie audio, par exemple les enceintes du système 
  8. +
  9. Connection des sources aux effets, et des effets à la sortie.
  10. +
+ +

Création d'un contexte audio

+ +

Commencez par créer une instance de AudioContext sur laquelle vous allez créer un graphe audio. L'exemple le plus simple ressemblerait à ceci:

+ +
var contexteAudio = new AudioContext();
+
+ +
+

Note : On peut créer plusieurs contextes audio dans le même document, bien que ce soit probablement superflu dans la plupart des cas.

+
+ +

Il faut rajouter une version préfixée pour les navigateurs Webkit/Blink browsers, tout en conservant la version non préfixée pour Firefox (desktop/mobile/OS). Ce qui donne :

+ +
var contexteAudio = new (window.AudioContext || window.webkitAudioContext)();
+
+ +
+

Note : Safari risque de planter si l'objet window n'est pas explicitement mentionné lors de la création d'un contexte audio

+
+ +

Création d'une source audio

+ +

Maintenant que nous avons créé un contexte, nous allons utiliser les méthodes de ce contexte pour quasiment tout ce qui nous reste à faire. La première étape consiste à créer une source audio. Les sources peuvent être de provenance diverse :

+ + + +

Pour notre exemple nous nous contenterons de créer un oscillateur pour générer un son simple comme source, et un noeud de gain pour contrôler le volume:

+ +
var oscillateur = contexteAudio.createOscillator();
+var noeudGain = contexteAudio.createGain();
+
+ +
+

Note : Pour jouer un fichier audio directement, il faut charger le fichier en XHR, le décoder en mémoire tampon, puis associer le tampon à une source. Voir l'exemple Voice-change-O-matic.

+
+ +
+

Note : Scott Michaud a écrit la librairie AudioSampleLoader, très pratique pour charger et décoder un ou plusieurs extraits audio. Elle peut aider à simplifier le processus de chargement XHR / mémoire tampon décrit dans la note précédente.

+
+ +

Lien entre les noeuds source et destination

+ +

Pour faire sortir le son dans vos enceintes, il faut relier la source et la destination. Pour cela on appelle la méthode connect sur le noeud source, le noeud de destination étant passé en argument. La méthode connect est disponible sur la plupart des types de noeuds.

+ +

La sortie par défaut du matériel (en général les enceintes) est accessible via {{ domxref("AudioContext.destination") }}. Pour connecter l'oscillateur, le noeud de gain et la destination, on écrirait les lignes suivantes:

+ +
oscillateur.connect(noeudGain);
+noeudGain.connect(contexteAudio.destination);
+
+ +

On peut connecter autant de noeuds qu'on le souhaite (cf. Voice-change-O-matic). Par exemple:

+ +
source = contexteAudio.createMediaStreamSource(stream);
+source.connect(analyser);
+analyser.connect(distortion);
+distortion.connect(biquadFilter);
+biquadFilter.connect(convolver);
+convolver.connect(noeudGain);
+noeudGain.connect(contexteAudio.destination);
+
+ +

Ce code créerait le graphe audio suivant :

+ +

Un graphe audio avec un élément audio source connecté à la destination par défaut

+ +

Il est possible de connecter plusieurs noeuds à un seul noeud, par exemple pour mixer plusieurs sources ensemble, et les passer dans un seul noeud d'effet, tel qu'un noeud de gain.

+ +
+

Note : Depuis Firefox 32, les outils de développement intégrés incluent un éditeur audio,  très utile pour débugger les graphes audio.

+
+ +

Lecture du son et définition du pitch

+ +

Maintenant que le graphe audio est en place, nous pouvons ajuster certains aspects du son en définissant la valeur de certaines propriétés ou en utilsant ses méthodes. L'exemple suivant spécifie un pitch en hertz pour un oscillateur, lui assigne un type, et demande à l'oscillateur de jouer le son.

+ +
oscillateur.type = 'sine'; // onde sinusoïdale — les autres valeurs possible sont : 'square', 'sawtooth', 'triangle' et 'custom'
+oscillateur.frequency.value = 2500; // valeur en hertz
+oscillateur.start();
+
+ +

Le code suivant, qui vient de l'exemple Violent Theremin, spécifie une valeur maximum pour le gain, et une valeur pour la fréquence:

+ +
var largeur = window.innerWidth;
+var hauteur = window.innerHeight;
+
+var frequenceMax = 6000;
+var volumeMax = 1;
+
+var frequenceInitiale = 3000;
+var volumeInitial = 0.5;
+
+// paramètres de l'oscillateur
+
+oscillateur.type = 'sine'; // onde sinusoïdale — les autres valeurs possible sont : 'square', 'sawtooth', 'triangle' et 'custom'
+oscillateur.frequency.value = frequenceInitiale; // valeur en hertz
+oscillateur.start();
+
+noeudGain.gain.value = volumeInitial;
+
+ +

On peut aussi réassigner les valeurs de fréquence et de pitch à chaque mouvement de la souris, en utilisant la position pour calculer un pourcentage des valeurs maximum de fréquence et de gain :

+ +
// coordonnées de la souris
+
+var positionX;
+var positionY;
+
+// récupère les nouvelles coordonnées de la souris quand elle bouge
+// puis assigne les nouvelles valeurs de gain et de pitch
+
+document.onmousemove = updatePage;
+
+function updatePage(e) {
+    positionX = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
+    positionY = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
+
+    oscillateur.frequency.value = (positionX/largeur) * frequenceMax;
+    noeudGain.gain.value = (positionY/hauteur) * volumeMax;
+
+    canvasDraw();
+}
+
+ +

Simple visualisation avec canvas

+ +

On appelle une fonction canvasDraw() à chaque mouvement de la souris. Elle dessine une grappe de cercles à l'endroit où se trouve la souris, leur taille et couleur étant basées sur les valeurs de fréquence et de gain.

+ +
function aleatoire(number1, number2) {
+  return number1 + (Math.floor(Math.random() * (number2 - number1)) + 1);
+}
+
+var canvas = document.querySelector('.canvas');
+canvas.width = largeur;
+canvas.height = hauteur;
+
+var contexteCanvas = canvas.getContext('2d');
+
+function canvasDraw() {
+  rX = positionX;
+  rY = positionY;
+  rC = Math.floor((noeudGain.gain.value / volumeMax) * 30);
+
+  canvasCtx.globalAlpha = 0.2;
+
+  for(i=1;i<=15;i=i+2) {
+    contexteCanvas.beginPath();
+    var chaineStyle = 'rgb(' + 100 + (i * 10) + ',' + Math.floor((noeudGain.gain.value / volumeMax) * 255);
+    chaineStyle += ',' + Math.floor((oscillateur.frequency.value / frequenceMax) * 255) + ')';
+    contexteCanvas.fillStyle = chaineStyle;
+    contexteCanvas.arc(rX + aleatoire(0, 50), rY + aleatoire(0, 50), rC / 2 + i, (Math.PI / 180) * 0, (Math.PI / 180) * 360, false);
+    contexteCanvas.fill();
+    contexteCanvas.closePath();
+  }
+}
+ +

Couper le son du theremin

+ +

Quand on appuie sur le bouton pour couper le son, la fonction ci-dessous est appelée, qui déconnecte le noeud de gain du noeud de destination, cassant ainsi le graphe de façon à ce qu'aucun son ne soit produit. Appuyer de nouveau sur le bouton a l'effet inverse.

+ +
var coupeSon = document.querySelector('.mute');
+
+coupeSon.onclick = function() {
+  if(coupeSon.id == "") {
+    noeudGain.disconnect(contexteAudio.destination);
+    coupeSon.id = "activated";
+    coupeSon.innerHTML = "Unmute";
+  } else {
+    noeudGain.connect(contexteAudio.destination);
+    coupeSon.id = "";
+    coupeSon.innerHTML = "Mute";
+  }
+}
+
+ +

Autres options des noeuds

+ +

On peut créer un grand nombre d'autres noeuds avec la Web Audio API. De façon générale, ils fonctionnent de façon très similaire à ceux que nous venons de voir: on crée un noeud, le connecte avec d'autres noeuds, et on manipule ensuite ses propriétés et méthodes pour agir sur la source.

+ +

Ce document passe en revue quelques-uns des outils et effets disponibles; vous trouverez davantage de détails sur les pages de référence de la {{ domxref("Web_Audio_API") }}.

+ +

Noeuds modulateurs d'onde

+ +

On peut créer un noeud modulatur d'onde avec la méthode {{ domxref("AudioContext.createWaveShaper") }} :

+ +
var distortion = contexteAudio.createWaveShaper();
+
+ +

On associe ensuite à cet objet une forme d'onde définie mathématiquement, qui est appliquée à l'onde de base pour créer un effet de distortion. Ecrire son propre algorithme n'est pas si simple, et pour commencer le mieux est encore d'en chercher un sur le Web. Par exemple, nous avons trouvé celui-ci sur Stack Overflow:

+ +
function genererCourbeDistortion(amount) {
+  var k = typeof amount === 'number' ? amount : 50,
+    n_samples = 44100,
+    curve = new Float32Array(n_samples),
+    deg = Math.PI / 180,
+    i = 0,
+    x;
+  for ( ; i < n_samples; ++i ) {
+    x = i * 2 / n_samples - 1;
+    curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );
+  }
+  return curve;
+};
+
+ +

L'exemple suivant, qui vient de Voice-change-O-matic, connecte un noeud de  distortion à un graphe audio, puis applique l'algorithme de forme d'onde précédent au noeud de distortion :

+ +
source.connect(analyser);
+analyser.connect(distortion);
+distortion.connect(biquadFilter);
+
+...
+
+distortion.curve = genererCourbeDistortion(400);
+
+ +

Filtre biquad

+ +

Les filtres biquad ont de nombreuses options. Nous montrons ici comment créer un filtre biquad avec la méthode {{domxref("AudioContext.createBiquadFilter")}}.

+ +
var filtreBiquad = contexteAudio.createBiquadFilter();
+
+ +

Le filtre utilisé dans la démo Voice-change-o-matic est un filtre lowshelf, qui amplifie le son au niveau des basses. Ici on augmente de 25 décibels toutes les fréquences en dessous de 1000.

+ +
filtreBiquad.type = "lowshelf";
+filtreBiquad.frequency.value = 1000;
+filtreBiquad.gain.value = 25;
+
+ +

Autres usages de la Web Audio API

+ +

La Web Audio API peut avoir bien d'autres applications que la visualisation ou la spatialisation audio (comme gérer la balance d'un son). Nous détaillerons d'autres options dans des articles séparés.

diff --git a/files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.html b/files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.html deleted file mode 100644 index 8a128b4d81..0000000000 --- a/files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.html +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: Visualisations avec la Web Audio API -slug: Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API -translation_of: Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API ---- -

L'une des fonctionnalités les plus intéressantes de la Web Audio API est la possibilité d'extraire de la source audio la fréquence, la forme d'onde et d'autres données, qui permettent de créer des visualisations. Cet article explique comment, et fournit quelques exemples basiques.

- -
-

Note : Vous pouvez trouver des exemples de tous les extraits de the code dans notre démo Voice-change-O-matic.

-
- -

Concepts de base

- -

Pour extraire les données d'une source audio, il faut un {{ domxref("AnalyserNode") }}, que l'on peut créer à l'aide de la méthode {{ domxref("AudioContext.createAnalyser()") }}, par exemple:

- -
var contexteAudio = new (window.AudioContext || window.webkitAudioContext)();
-var analyseur = contexteAudio.createAnalyser();
- -

Ce noeud est ensuite connecté à la source audio :

- -
source = contexteAudio.createMediaStreamSource(stream);
-source.connect(analyseur);
-analyseur.connect(distortion);
-// etc.
- -
-

Note : il n'est pas nécessaire de connecter la sortie de l'analyseur à un noeud pour qu'il fonctionne, il suffit que l'entrée soit connectée à la source, directement ou via un autre noeud.

-
- -

L'analyseur va alors capturer les données audio en usant une Transformation de Fourier Rapide (fft) à une certaine fréquence, en fonction de ce qui est spécifié dans la propriété {{ domxref("AnalyserNode.fftSize") }} (la valeur par défaut est 2048).

- -
-

Note : Vous pouvez aussi spécifier des valeurs de puissance minimum et maximum pour la plage de mise à l'échelle fft, en utilisant {{ domxref("AnalyserNode.minDecibels") }} et {{ domxref("AnalyserNode.maxDecibels") }}, et plusieurs valeurs de transition en utilisant {{ domxref("AnalyserNode.smoothingTimeConstant") }}.

-
- -

Pour capturer des données, il faut utiliser les méthodes {{ domxref("AnalyserNode.getFloatFrequencyData()") }} et {{ domxref("AnalyserNode.getByteFrequencyData()") }} pour la fréquence, et {{ domxref("AnalyserNode.getByteTimeDomainData()") }} et {{ domxref("AnalyserNode.getFloatTimeDomainData()") }} pour la forme d'onde.

- -

Ces méthodes copient les données dans le tableau passé en paramètre, il faut donc créer un tableau avant de les invoquer. La première produit des nombres flottants à simple précision de 32 bits, qui ne peuvent être stockées dans un simple tableau javascript. Vous devez créer un domxref("Float32Array") }} ou un {{ domxref("Uint8Array") }}, en fonction du type de données que vous traitez.

- -

Par exemple, disons que nous manipulons une fft de fréquence 2048. Nous retournons la valeur {{ domxref("AnalyserNode.frequencyBinCount") }}, qui correspond à la moitié de la fréquence, puis nous appelons la méthode  Uint8Array() en passant frequencyBinCount comme argument pour la taille — c'est le nombre de points de données qui seront collectées pour cette fréquence.

- -
analyseur.fftSize = 2048;
-var tailleMemoireTampon = analyseur.frequencyBinCount;
-var tableauDonnees = new Uint8Array(tailleMemoireTampon);
- -

Pour récupérer les données et les copier dans notre tableau, nous appelons ensuite la méthode de notre choix, en passant le tableau comme argument. Par exemple :

- -
analyseur.getByteTimeDomainData(tableauDonnees);
- -

Nous avons maintenant les données audio qui correspondent à ce laps de temps capturées dans notre tableau, et pouvons procéder à la visualisation, par exemple en les dessinant dans un élément HTML5 {{ htmlelement("canvas") }}.

- -

Regardons quelques exemples précis.

- -

Création d'une forme d'onde / oscilloscope

- -

Pour visualiser un oscilloscope (chapeau à Soledad Penadés pour le code original sur Voice-change-O-matic), nous commençons par suivre la procédure standard décrite dans le paragraphe précédent pour mettre en place le tampon :

- -
analyseur.fftSize = 2048;
-var tailleMemoireTampon = analyseur.frequencyBinCount;
-var tableauDonnees = new Uint8Array(tailleMemoireTampon);
- -

Ensuite nous effaçons ce qui est dessiné sur le canvas , avant le nouvel affichage :

- -
contexteCanvas.clearRect(0, 0, LARGEUR, HAUTEUR);
- -

Puis nous définissons la fonction dessiner() :

- -
function dessiner() {
- -

Dans cette fonction, nous utilisons requestAnimationFrame() pour faire boucler la fonction une fois qu'elle a été appelée :

- -
      dessin = requestAnimationFrame(dessiner);
- -

Ensuite, nous récupérons les données et les passons dans notre tableau :

- -
      analyseur.getByteTimeDomainData(tableauDonnees);
- -

Nous remplissons le canvas avec une couleur de fond :

- -
      contexteCanvas.fillStyle = 'rgb(200, 200, 200)';
-      contexteCanvas.fillRect(0, 0, LARGEUR, HAUTEUR);
- -

Nous définissons l'épaisseur et la couleur du trait pour la forme d'onde que nous allons dessiner, et commençons le tracé :

- -
      contexteCanvas.lineWidth = 2;
-      contexteCanvas.strokeStyle = 'rgb(0, 0, 0)';
-
-      contexteCanvas.beginPath();
- -

Pour déterminer la largeur de chacun des segments qui composent la ligne, nous divisons la largeur du canvas par la taille du tableau de données (laquelle est égale à FrequencyBinCount, comme nous l'avons dit plus haut), puis nous définissons une variable x pour stocker la position à laquelle il faut se déplacer pour chaque segment.

- -
      var largeurSegment = LARGEUR * 1.0 / tailleMemoireTampon;
-      var x = 0;
- -

Nous parcourons une boucle, qui définit la position du segment de l'onde pour chaque valeur du tableau: la hauteur (y) est basée sur cette valeur, tandis que la position en x correspond à une largeur de segment supplémentaire à chaque itération :

- -
      for(var i = 0; i < tailleMemoireTampon; i++) {
-
-        var v = tableauDonnees[i] / 128.0;
-        var y = v * HAUTEUR/2;
-
-        if(i === 0) {
-          contexteCanvas.moveTo(x, y);
-        } else {
-          contexteCanvas.lineTo(x, y);
-        }
-
-        x += largeurSegment;
-      }
- -

Finally, quand le tracé de la ligne a atteint le bord droit du canvas, nous l'affichons:

- -
      contexteCanvas.lineTo(canvas.width, canvas.height/2);
-      contexteCanvas.stroke();
-    };
- -

Nous pouvons maintenant appeler la fonction draw() que nous venons de définir pour lancer le processus:

- -
    dessiner();
- -

Ce qui nous donne un affichage de forme d'onde, actualisé plusieurs fois par seconde :

- -

Une ligne d'oscilloscope noire, illustrant la forme d'onde d'un signal audio

- -

Création d'un graphique à barres représentant la fréquence

- -

Un autre exemple de visualisation assez simple à créer est le graphique à barres dans le style de Winamp. Il y en a un dans la démo Voice-change-O-matic; regardons comment il est fait.

- -

Tout d'abord, nous mettons de nouveau en place notre analyseur et notre tableau de données, et nous effaçons le contenu du canvas avec clearRect(). La seule différence est que la valeur de la propriété fftSize est beaucoup plus petite, de façon à ce que chaque barre soit assez grosse pour ressembler à une barre et non à un fil.

- -
    analyseur.fftSize = 256;
-    var tailleMemoireTampon = analyseur.frequencyBinCount;
-    console.log(tailleMemoireTampon);
-    var tableauDonnees = new Uint8Array(tailleMemoireTampon);
-
-    canvasCtx.clearRect(0, 0, LARGEUR, HAUTEUR);
- -

Ensuite, nous passons à la fonction dessiner(), là encore avec une boucle requestAnimationFrame() qui efface l'affichage et le met à jour.

- -
    function dessiner() {
-      dessin = requestAnimationFrame(dessiner);
-
-      analyseur.getByteFrequencyData(tableauDonnees);
-
-      contexteCanvas.fillStyle = 'rgb(0, 0, 0)';
-      contexteCanvas.fillRect(0, 0, LARGEUR, HAUTEUR);
- -

A présent nous calculons la largeur d'une barre, à savoir la largeur du canvas divisée par le nombre de barres (par la taille du buffer). Et nous multiplions cette valeur par 2.5, en prévision du fait que la plupart des fréquences ne contiendront pas de son, car les sons que nous entendons se situent dans un intervalle de fréquence plutôt bas. Nous ne voulons pas afficher des barres vides, nous ne gardons donc que celles qui ont une hauteur suffisante.

- -

Nous déclarons une variable hauteurBarre, ainsi qu'une variable x pour mémoriser la posiiton à laquelle il faudra dessiner la barre.

- -
      var largeurBarre = (LARGEUR / tailleMemoireTampon) * 2.5;
-      var hauteurBarre;
-      var x = 0;
- -

Nous créons maintenant une boucle et itérons sur chaque valeur de tableauDonnees : hauteurBarre correspond à la valeur du tableau, la couleur de fond est aussi basée sur cette valeur (plus elle est grande plus la barre est lumineuse), et la barre est placée à x pixels du bord gauche du canvas, sa largeur est largeurBarre et sa hauteur est hauteurBarre/2 (nous avons finalement décidé de diviser cette valeur par deux pour que les barres rentrent mieux dans le canvas).

- -

La position verticale de la barre est calculée comme tel : HAUTEUR-hauteurBarre/2, parce que nous voulons que les barres s'alignent en bas du canvas, et non pas en haut (auquel cas nous aurions positionné la barre à 0).

- -
      for(var i = 0; i < tailleMemoireTampon; i++) {
-        hauteurBarre = tableauDonnees[i]/2;
-
-        contexteCanvas.fillStyle = 'rgb(' + (hauteurBarre+100) + ',50,50)';
-        contexteCanvas.fillRect(x,HAUTEUR-hauteurBarre/2,largeurBarre,hauteurBarre);
-
-        x += largeurBarre + 1;
-      }
-    };
- -

Là encore, nous invoquons la fonction dessiner() pour lancer le processus.

- -
    dessiner();
- -

Ce code donne le résultat suivant:

- -

Une série de barres rouges dans un barre-graphe qui illustre l'intensité des différentes fréquences d'un signal audio

- -
-

Note : Les examples de cet article montrent l'utilisation de {{ domxref("AnalyserNode.getByteFrequencyData()") }} et {{ domxref("AnalyserNode.getByteTimeDomainData()") }}. Pour des exemples montrant {{ domxref("AnalyserNode.getFloatFrequencyData()") }} et {{ domxref("AnalyserNode.getFloatTimeDomainData()") }}, voir notre démo Voice-change-O-matic-float-data (et son code source) — elle est identique à la Voice-change-O-matic originale, à ceci près qu'elle utilise des données à virgule flottante, au lieu de données non signées.

-
\ No newline at end of file diff --git a/files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.md b/files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.md new file mode 100644 index 0000000000..8a128b4d81 --- /dev/null +++ b/files/fr/web/api/web_audio_api/visualizations_with_web_audio_api/index.md @@ -0,0 +1,180 @@ +--- +title: Visualisations avec la Web Audio API +slug: Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API +translation_of: Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API +--- +

L'une des fonctionnalités les plus intéressantes de la Web Audio API est la possibilité d'extraire de la source audio la fréquence, la forme d'onde et d'autres données, qui permettent de créer des visualisations. Cet article explique comment, et fournit quelques exemples basiques.

+ +
+

Note : Vous pouvez trouver des exemples de tous les extraits de the code dans notre démo Voice-change-O-matic.

+
+ +

Concepts de base

+ +

Pour extraire les données d'une source audio, il faut un {{ domxref("AnalyserNode") }}, que l'on peut créer à l'aide de la méthode {{ domxref("AudioContext.createAnalyser()") }}, par exemple:

+ +
var contexteAudio = new (window.AudioContext || window.webkitAudioContext)();
+var analyseur = contexteAudio.createAnalyser();
+ +

Ce noeud est ensuite connecté à la source audio :

+ +
source = contexteAudio.createMediaStreamSource(stream);
+source.connect(analyseur);
+analyseur.connect(distortion);
+// etc.
+ +
+

Note : il n'est pas nécessaire de connecter la sortie de l'analyseur à un noeud pour qu'il fonctionne, il suffit que l'entrée soit connectée à la source, directement ou via un autre noeud.

+
+ +

L'analyseur va alors capturer les données audio en usant une Transformation de Fourier Rapide (fft) à une certaine fréquence, en fonction de ce qui est spécifié dans la propriété {{ domxref("AnalyserNode.fftSize") }} (la valeur par défaut est 2048).

+ +
+

Note : Vous pouvez aussi spécifier des valeurs de puissance minimum et maximum pour la plage de mise à l'échelle fft, en utilisant {{ domxref("AnalyserNode.minDecibels") }} et {{ domxref("AnalyserNode.maxDecibels") }}, et plusieurs valeurs de transition en utilisant {{ domxref("AnalyserNode.smoothingTimeConstant") }}.

+
+ +

Pour capturer des données, il faut utiliser les méthodes {{ domxref("AnalyserNode.getFloatFrequencyData()") }} et {{ domxref("AnalyserNode.getByteFrequencyData()") }} pour la fréquence, et {{ domxref("AnalyserNode.getByteTimeDomainData()") }} et {{ domxref("AnalyserNode.getFloatTimeDomainData()") }} pour la forme d'onde.

+ +

Ces méthodes copient les données dans le tableau passé en paramètre, il faut donc créer un tableau avant de les invoquer. La première produit des nombres flottants à simple précision de 32 bits, qui ne peuvent être stockées dans un simple tableau javascript. Vous devez créer un domxref("Float32Array") }} ou un {{ domxref("Uint8Array") }}, en fonction du type de données que vous traitez.

+ +

Par exemple, disons que nous manipulons une fft de fréquence 2048. Nous retournons la valeur {{ domxref("AnalyserNode.frequencyBinCount") }}, qui correspond à la moitié de la fréquence, puis nous appelons la méthode  Uint8Array() en passant frequencyBinCount comme argument pour la taille — c'est le nombre de points de données qui seront collectées pour cette fréquence.

+ +
analyseur.fftSize = 2048;
+var tailleMemoireTampon = analyseur.frequencyBinCount;
+var tableauDonnees = new Uint8Array(tailleMemoireTampon);
+ +

Pour récupérer les données et les copier dans notre tableau, nous appelons ensuite la méthode de notre choix, en passant le tableau comme argument. Par exemple :

+ +
analyseur.getByteTimeDomainData(tableauDonnees);
+ +

Nous avons maintenant les données audio qui correspondent à ce laps de temps capturées dans notre tableau, et pouvons procéder à la visualisation, par exemple en les dessinant dans un élément HTML5 {{ htmlelement("canvas") }}.

+ +

Regardons quelques exemples précis.

+ +

Création d'une forme d'onde / oscilloscope

+ +

Pour visualiser un oscilloscope (chapeau à Soledad Penadés pour le code original sur Voice-change-O-matic), nous commençons par suivre la procédure standard décrite dans le paragraphe précédent pour mettre en place le tampon :

+ +
analyseur.fftSize = 2048;
+var tailleMemoireTampon = analyseur.frequencyBinCount;
+var tableauDonnees = new Uint8Array(tailleMemoireTampon);
+ +

Ensuite nous effaçons ce qui est dessiné sur le canvas , avant le nouvel affichage :

+ +
contexteCanvas.clearRect(0, 0, LARGEUR, HAUTEUR);
+ +

Puis nous définissons la fonction dessiner() :

+ +
function dessiner() {
+ +

Dans cette fonction, nous utilisons requestAnimationFrame() pour faire boucler la fonction une fois qu'elle a été appelée :

+ +
      dessin = requestAnimationFrame(dessiner);
+ +

Ensuite, nous récupérons les données et les passons dans notre tableau :

+ +
      analyseur.getByteTimeDomainData(tableauDonnees);
+ +

Nous remplissons le canvas avec une couleur de fond :

+ +
      contexteCanvas.fillStyle = 'rgb(200, 200, 200)';
+      contexteCanvas.fillRect(0, 0, LARGEUR, HAUTEUR);
+ +

Nous définissons l'épaisseur et la couleur du trait pour la forme d'onde que nous allons dessiner, et commençons le tracé :

+ +
      contexteCanvas.lineWidth = 2;
+      contexteCanvas.strokeStyle = 'rgb(0, 0, 0)';
+
+      contexteCanvas.beginPath();
+ +

Pour déterminer la largeur de chacun des segments qui composent la ligne, nous divisons la largeur du canvas par la taille du tableau de données (laquelle est égale à FrequencyBinCount, comme nous l'avons dit plus haut), puis nous définissons une variable x pour stocker la position à laquelle il faut se déplacer pour chaque segment.

+ +
      var largeurSegment = LARGEUR * 1.0 / tailleMemoireTampon;
+      var x = 0;
+ +

Nous parcourons une boucle, qui définit la position du segment de l'onde pour chaque valeur du tableau: la hauteur (y) est basée sur cette valeur, tandis que la position en x correspond à une largeur de segment supplémentaire à chaque itération :

+ +
      for(var i = 0; i < tailleMemoireTampon; i++) {
+
+        var v = tableauDonnees[i] / 128.0;
+        var y = v * HAUTEUR/2;
+
+        if(i === 0) {
+          contexteCanvas.moveTo(x, y);
+        } else {
+          contexteCanvas.lineTo(x, y);
+        }
+
+        x += largeurSegment;
+      }
+ +

Finally, quand le tracé de la ligne a atteint le bord droit du canvas, nous l'affichons:

+ +
      contexteCanvas.lineTo(canvas.width, canvas.height/2);
+      contexteCanvas.stroke();
+    };
+ +

Nous pouvons maintenant appeler la fonction draw() que nous venons de définir pour lancer le processus:

+ +
    dessiner();
+ +

Ce qui nous donne un affichage de forme d'onde, actualisé plusieurs fois par seconde :

+ +

Une ligne d'oscilloscope noire, illustrant la forme d'onde d'un signal audio

+ +

Création d'un graphique à barres représentant la fréquence

+ +

Un autre exemple de visualisation assez simple à créer est le graphique à barres dans le style de Winamp. Il y en a un dans la démo Voice-change-O-matic; regardons comment il est fait.

+ +

Tout d'abord, nous mettons de nouveau en place notre analyseur et notre tableau de données, et nous effaçons le contenu du canvas avec clearRect(). La seule différence est que la valeur de la propriété fftSize est beaucoup plus petite, de façon à ce que chaque barre soit assez grosse pour ressembler à une barre et non à un fil.

+ +
    analyseur.fftSize = 256;
+    var tailleMemoireTampon = analyseur.frequencyBinCount;
+    console.log(tailleMemoireTampon);
+    var tableauDonnees = new Uint8Array(tailleMemoireTampon);
+
+    canvasCtx.clearRect(0, 0, LARGEUR, HAUTEUR);
+ +

Ensuite, nous passons à la fonction dessiner(), là encore avec une boucle requestAnimationFrame() qui efface l'affichage et le met à jour.

+ +
    function dessiner() {
+      dessin = requestAnimationFrame(dessiner);
+
+      analyseur.getByteFrequencyData(tableauDonnees);
+
+      contexteCanvas.fillStyle = 'rgb(0, 0, 0)';
+      contexteCanvas.fillRect(0, 0, LARGEUR, HAUTEUR);
+ +

A présent nous calculons la largeur d'une barre, à savoir la largeur du canvas divisée par le nombre de barres (par la taille du buffer). Et nous multiplions cette valeur par 2.5, en prévision du fait que la plupart des fréquences ne contiendront pas de son, car les sons que nous entendons se situent dans un intervalle de fréquence plutôt bas. Nous ne voulons pas afficher des barres vides, nous ne gardons donc que celles qui ont une hauteur suffisante.

+ +

Nous déclarons une variable hauteurBarre, ainsi qu'une variable x pour mémoriser la posiiton à laquelle il faudra dessiner la barre.

+ +
      var largeurBarre = (LARGEUR / tailleMemoireTampon) * 2.5;
+      var hauteurBarre;
+      var x = 0;
+ +

Nous créons maintenant une boucle et itérons sur chaque valeur de tableauDonnees : hauteurBarre correspond à la valeur du tableau, la couleur de fond est aussi basée sur cette valeur (plus elle est grande plus la barre est lumineuse), et la barre est placée à x pixels du bord gauche du canvas, sa largeur est largeurBarre et sa hauteur est hauteurBarre/2 (nous avons finalement décidé de diviser cette valeur par deux pour que les barres rentrent mieux dans le canvas).

+ +

La position verticale de la barre est calculée comme tel : HAUTEUR-hauteurBarre/2, parce que nous voulons que les barres s'alignent en bas du canvas, et non pas en haut (auquel cas nous aurions positionné la barre à 0).

+ +
      for(var i = 0; i < tailleMemoireTampon; i++) {
+        hauteurBarre = tableauDonnees[i]/2;
+
+        contexteCanvas.fillStyle = 'rgb(' + (hauteurBarre+100) + ',50,50)';
+        contexteCanvas.fillRect(x,HAUTEUR-hauteurBarre/2,largeurBarre,hauteurBarre);
+
+        x += largeurBarre + 1;
+      }
+    };
+ +

Là encore, nous invoquons la fonction dessiner() pour lancer le processus.

+ +
    dessiner();
+ +

Ce code donne le résultat suivant:

+ +

Une série de barres rouges dans un barre-graphe qui illustre l'intensité des différentes fréquences d'un signal audio

+ +
+

Note : Les examples de cet article montrent l'utilisation de {{ domxref("AnalyserNode.getByteFrequencyData()") }} et {{ domxref("AnalyserNode.getByteTimeDomainData()") }}. Pour des exemples montrant {{ domxref("AnalyserNode.getFloatFrequencyData()") }} et {{ domxref("AnalyserNode.getFloatTimeDomainData()") }}, voir notre démo Voice-change-O-matic-float-data (et son code source) — elle est identique à la Voice-change-O-matic originale, à ceci près qu'elle utilise des données à virgule flottante, au lieu de données non signées.

+
\ No newline at end of file diff --git a/files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.html b/files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.html deleted file mode 100644 index d0de8755ec..0000000000 --- a/files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.html +++ /dev/null @@ -1,261 +0,0 @@ ---- -title: Web audio spatialization basics -slug: Web/API/Web_Audio_API/Web_audio_spatialization_basics -translation_of: Web/API/Web_Audio_API/Web_audio_spatialization_basics ---- -

En plus de sa grande variété de fonctionnalités et d'options, la Web Audio API permet aussi d'émuler la différence dans l'écoute d'un son lorsqu'un auditeur se déplace par rapport à une source, par exemple un panoramique lorsqu'il se déplace de gauche à droite de la source. On parle alors de spatialisation. Cet article expose les notions de base pour implémenter ce type de système.

- -

Le cas d'utilisation le plus simple est la simulation des altérations d'un son de façon réaliste pour imaginer comment une source se comportera pour un personnage qui se déplace dans un environnement 3D.

- -

Concepts de base

- -

Créer une spatialisation audio comporte deux principaux aspects :

- -
    -
  1. L'objet {{ domxref("AudioListener") }} représente la position dans l'espace 3D d'une personne qui écoute la source audio; on y accède avec la propriété {{ domxref("AudioContext.listener") }}. On peut paramétrer la position et l'orientation de l'auditeur, entre autres.
  2. -
  3. L'objet {{ domxref("PannerNode") }} représente la position dans l'espace 3D d'une source audio; on le crée avec la méthode {{ domxref("AudioContext.createPanner()") }}. On peut paramétrer un certain nombre d'options comme la position, l'orientation, la vitesse, et l'angle s'un cône qui indique dans quelle direction le son peut être entendu (s'il n'est pas omnidirectionnel).
  4. -
- -

Dans cet article nous allons nous concentrer sur la position de l'auditeur et du panoramique, tous deux paramétrés à l'aide de la méthode setPosition(). Celle-co accepte trois valeurs qui correspondent à X, Y, et Z dans un système de coordonnées cartésien.

- -
-

Note : Trouver les bonnes valeurs pour que le cas d'utilisation fonctionne bien et semble réaliste n'est pas toujours évident et peur prendre du temps, et il faut souvent continuer à modifier les valeurs par la suite. Nous discuterons ceci plus en détail en parcourant le code qui suit.

-
- -

Les autres options  disponibles, que nous ne traiterons pas ici, sont :

- - - -

A simple demo: Room of metal

- -

In our demo, you can move left and right past a 2.5D stereo that can be made to play a groovy tune, and you can also move towards the stereo. As you move left and right, the tune will pan to emulate how the tune will sound as you change your position proportional to the sound source. When you zoom in and out, the sound will get louder and quieter to suit.

- -
-

Note : You can see this example running live, and view the source code.

-
- -

Let's walk through the code and see how this was actually done.

- -

Defining basic variables

- -

First we define a new audio context, panner, listener, and source:

- -
var AudioContext = window.AudioContext || window.webkitAudioContext;
-var audioCtx = new AudioContext();
-
-var panner = audioCtx.createPanner();
-var listener = audioCtx.listener;
-var source;
- -

Next we grab the objects on the page we are using for our demo. First the play and stop buttons to control the audio, then the boomBox, which is just the graphic of the stereo that we are moving around. After that, we grab a reference to two paragraphs that are used to output the position of the listener and panner, for debugging purposes.

- -
var play = document.querySelector('.play');
-var stop = document.querySelector('.stop');
-
-var boomBox = document.querySelector('.boom-box');
-
-var listenerData = document.querySelector('.listener-data');
-var pannerData = document.querySelector('.panner-data');
- -

Working out listener and panner positions

- -

Next comes a little bit of slightly fiddly maths. We want to make the boomBox, listener, and panner appear in the center of the screen initially, so we work out the width and height of the viewport, and divide both by two to get our X and Y values for those things. The zPos is only used on the panner, and is updated as the zoom controls are used (see later on); the initial value of 295 was decided on fairly arbitrarily — it sounded good. As long as you set the position of the panner appropriately in relation to the listener position, you will be ok.

- -

Next for this section, we set a leftBound and rightBound, which is the furthest we want our stereo graph to travel left and right. For the layout, we are using Flexbox to initially place the boomBox right in the center of the viewport, after which we then use iterative transforms and {{domxref("window.requestAnimationFrame()")}} to apply the boomBox movement. Therefore the "0" position is in the center of the viewport so the rightmost position is that position plus half the viewport, but minus 50 (pixels) so the boomBox can't shoot all the way off the right of the screen, and the leftmost position is that position minus half the viewport, but plus 50 (pixels), so the boomBox can't shoot all the way off the left of the screen.

- -

The last part of this code is the xIterator — we set this to a 150th of the screen width, and then move the boomBox left and right by this amount when the left and right controls are pressed. We use this rather than a constant so that the app is a little more responsive.

- -
var WIDTH = window.innerWidth;
-var HEIGHT = window.innerHeight;
-
-var xPos = WIDTH/2;
-var yPos = HEIGHT/2;
-var zPos = 295;
-
-leftBound = (-xPos) + 50;
-rightBound = xPos - 50;
-
-xIterator = WIDTH/150;
- -

Next we set the position of the listener and output the coordinates to the listenerData paragraph. It is always going to be in the same place, in a good position relative to the panner.

- -
listener.setPosition(xPos,yPos,300);
-listenerData.innerHTML = 'Listener data: X ' + xPos + ' Y ' + yPos + ' Z ' + 300;
- -

In the positionPanner() function, we set the position of the panner, and output the coordinates to the pannerData paragraph. This function is called with each animation frame as the boomBox is moved, so the panner position updates accordingly:

- -
function positionPanner() {
-  panner.setPosition(xPos,yPos,zPos);
-  pannerData.innerHTML = 'Panner data: X ' + xPos + ' Y ' + yPos + ' Z ' + zPos;
-}
- -

Loading and playing our music

- -

Next we use XHR to load an audio track, and decodeAudioData() to decode it and stick it in a buffer. Then we put the buffer into an {{domxref("AudioBufferSourceNode") }}:

- -
function getData() {
-  source = audioCtx.createBufferSource();
-  request = new XMLHttpRequest();
-
-  request.open('GET', 'viper.ogg', true);
-
-  request.responseType = 'arraybuffer';
-
-
-  request.onload = function() {
-    var audioData = request.response;
-
-    audioCtx.decodeAudioData(audioData, function(buffer) {
-        myBuffer = buffer;
-        source.buffer = myBuffer;
-
-        source.connect(panner);
-        panner.connect(audioCtx.destination);
-        positionPanner();
-        source.loop = true;
-      },
-
-      function(e){"Error with decoding audio data" + e.err});
-
-  }
-
-  request.send();
-}
- -

The next stage is to wire up the buttons to stop and play the audio. The pulse wrapper is an extra wrapper {{ htmlelement("div") }} wrapped around the boomBox. We apply the pulsating (scaleY) animation to this element when the play button is clicked, not the boomBox itself, because the boomBox already has animations applied to it throughout the course of the app's running.

- -
var pulseWrapper = document.querySelector('.pulse-wrapper');
-
-play.onclick = function() {
-  getData();
-  source.start(0);
-  play.setAttribute('disabled', 'disabled');
-  pulseWrapper.classList.add('pulsate');
-}
-
-stop.onclick = function() {
-  source.stop(0);
-  play.removeAttribute('disabled');
-  pulseWrapper.classList.remove('pulsate');
-}
- -

Moving the boom box and the panner

- -

The next section of code grabs references to the left, right, zoom in, and zoom out buttons, and defines initial X, Y, and scale amounts for the boomBox to be positioned by when the transforms first start to be applied.

- -
var leftButton = document.querySelector('.left');
-var rightButton = document.querySelector('.right');
-var zoomInButton = document.querySelector('.zoom-in');
-var zoomOutButton = document.querySelector('.zoom-out');
-
-var boomX = 0;
-var boomY = 0;
-var boomZoom = 0.25;
- -

Now we get to the four functions that control the left, right, zoom in, and zoom out functionality: moveRight(), moveLeft(), zoomIn(), and zoomOut(). Each is a little different, but works in a similar way:

- -
    -
  1. The boomX or boomZoom variables are updated in order to change the boomBox's position on the screen.
  2. -
  3. The xPos or zPos variables are updated in order to change the {{domxref("PannerNode") }}'s position in 3D space. The changes are quite small, but these are the values we found to work.
  4. -
  5. A check is done to see if the upper bounds of movement have been reached (a boomX equal or less than leftBound or greater than rightBound, or a boomZoom greater than 4 or equal or less than 0.25.) If so, the values are updated to force the boomBox to stay in certain constraints, and to force the xPos and zPos variables to also stay within certain constrants. These are, respectively, 5 greater or less than WIDTH/2, and a zPos between 295 and 299.9. These are the values we found produced a relatively realistic sounding panning and volume adjustment as the boomBox was moved around.
  6. -
  7. boomBox is transformed (translated and scaled) by the new values of boomX, boomY, and boomZoom to move it around the screen.
  8. -
  9. The positionPanner() function is run to update the position of the panner.
  10. -
  11. A {{domxref("window.requestAnimationFrame") }} instance is called to keep running the function for as long as the mouse button is pressed down.
  12. -
  13. The requestAnimationFrame ID is returned out of the function so that it can be cancelled when the mouse button is released.
  14. -
- -
function moveRight() {
-  boomX += -xIterator;
-  xPos += -0.066;
-
-  if(boomX <= leftBound) {
-    boomX = leftBound;
-    xPos = (WIDTH/2) - 5;
-  }
-
-  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  positionPanner();
-  rightLoop = requestAnimationFrame(moveRight);
-  return rightLoop;
-}
-
-function moveLeft() {
-  boomX += xIterator;
-  xPos += 0.066;
-
-  if(boomX > rightBound) {
-    boomX = rightBound;
-    xPos = (WIDTH/2) + 5;
-  }
-
-  positionPanner();
-  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  leftLoop = requestAnimationFrame(moveLeft);
-  return leftLoop;
-}
-
-function zoomIn() {
-  boomZoom += 0.05;
-  zPos += 0.066;
-
-  if(boomZoom > 4) {
-    boomZoom = 4;
-    zPos = 299.9;
-  }
-
-  positionPanner();
-  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  zoomInLoop = requestAnimationFrame(zoomIn);
-  return zoomInLoop;
-}
-
-function zoomOut() {
-  boomZoom += -0.05;
-  zPos += -0.066;
-
-  if(boomZoom <= 0.25) {
-    boomZoom = 0.25;
-    zPos = 295;
-  }
-
-  positionPanner();
-  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
-  zoomOutLoop = requestAnimationFrame(zoomOut);
-  return zoomOutLoop;
-}
- -

In the final block of code, we simply wire up event handlers to control the movement when the buttons are pressed. For each button, the relevant function is invoked onmousedown; then onmouseup, {{domxref("window.cancelAnimationFrame") }} is called along with the returned requestAnimationFrame() ID to stop the animation happening.

- -
leftButton.onmousedown = moveLeft;
-leftButton.onmouseup = function () {
-  window.cancelAnimationFrame(leftLoop);
-}
-
-rightButton.onmousedown = moveRight;
-rightButton.onmouseup = function () {
-  window.cancelAnimationFrame(rightLoop);
-}
-
-zoomInButton.onmousedown = zoomIn;
-zoomInButton.onmouseup = function () {
-  window.cancelAnimationFrame(zoomInLoop);
-}
-
-zoomOutButton.onmousedown = zoomOut;
-zoomOutButton.onmouseup = function () {
-  window.cancelAnimationFrame(zoomOutLoop);
-}
- -

As you can see, the actual panner code is pretty simple — specify the positions, and the browser takes care of the rest. It is working out the surrounding code, and the values to use for positioning, which takes a bit more time.

- -
-

Note : You are probably thinking "why didn't you move the listener and keep the panner still instead: surely that is a bit more obvious?" Well, perhaps, but we felt that since the panner has more methods and properties available to it, moving it would allow more control in the long term.

-
\ No newline at end of file diff --git a/files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.md b/files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.md new file mode 100644 index 0000000000..d0de8755ec --- /dev/null +++ b/files/fr/web/api/web_audio_api/web_audio_spatialization_basics/index.md @@ -0,0 +1,261 @@ +--- +title: Web audio spatialization basics +slug: Web/API/Web_Audio_API/Web_audio_spatialization_basics +translation_of: Web/API/Web_Audio_API/Web_audio_spatialization_basics +--- +

En plus de sa grande variété de fonctionnalités et d'options, la Web Audio API permet aussi d'émuler la différence dans l'écoute d'un son lorsqu'un auditeur se déplace par rapport à une source, par exemple un panoramique lorsqu'il se déplace de gauche à droite de la source. On parle alors de spatialisation. Cet article expose les notions de base pour implémenter ce type de système.

+ +

Le cas d'utilisation le plus simple est la simulation des altérations d'un son de façon réaliste pour imaginer comment une source se comportera pour un personnage qui se déplace dans un environnement 3D.

+ +

Concepts de base

+ +

Créer une spatialisation audio comporte deux principaux aspects :

+ +
    +
  1. L'objet {{ domxref("AudioListener") }} représente la position dans l'espace 3D d'une personne qui écoute la source audio; on y accède avec la propriété {{ domxref("AudioContext.listener") }}. On peut paramétrer la position et l'orientation de l'auditeur, entre autres.
  2. +
  3. L'objet {{ domxref("PannerNode") }} représente la position dans l'espace 3D d'une source audio; on le crée avec la méthode {{ domxref("AudioContext.createPanner()") }}. On peut paramétrer un certain nombre d'options comme la position, l'orientation, la vitesse, et l'angle s'un cône qui indique dans quelle direction le son peut être entendu (s'il n'est pas omnidirectionnel).
  4. +
+ +

Dans cet article nous allons nous concentrer sur la position de l'auditeur et du panoramique, tous deux paramétrés à l'aide de la méthode setPosition(). Celle-co accepte trois valeurs qui correspondent à X, Y, et Z dans un système de coordonnées cartésien.

+ +
+

Note : Trouver les bonnes valeurs pour que le cas d'utilisation fonctionne bien et semble réaliste n'est pas toujours évident et peur prendre du temps, et il faut souvent continuer à modifier les valeurs par la suite. Nous discuterons ceci plus en détail en parcourant le code qui suit.

+
+ +

Les autres options  disponibles, que nous ne traiterons pas ici, sont :

+ + + +

A simple demo: Room of metal

+ +

In our demo, you can move left and right past a 2.5D stereo that can be made to play a groovy tune, and you can also move towards the stereo. As you move left and right, the tune will pan to emulate how the tune will sound as you change your position proportional to the sound source. When you zoom in and out, the sound will get louder and quieter to suit.

+ +
+

Note : You can see this example running live, and view the source code.

+
+ +

Let's walk through the code and see how this was actually done.

+ +

Defining basic variables

+ +

First we define a new audio context, panner, listener, and source:

+ +
var AudioContext = window.AudioContext || window.webkitAudioContext;
+var audioCtx = new AudioContext();
+
+var panner = audioCtx.createPanner();
+var listener = audioCtx.listener;
+var source;
+ +

Next we grab the objects on the page we are using for our demo. First the play and stop buttons to control the audio, then the boomBox, which is just the graphic of the stereo that we are moving around. After that, we grab a reference to two paragraphs that are used to output the position of the listener and panner, for debugging purposes.

+ +
var play = document.querySelector('.play');
+var stop = document.querySelector('.stop');
+
+var boomBox = document.querySelector('.boom-box');
+
+var listenerData = document.querySelector('.listener-data');
+var pannerData = document.querySelector('.panner-data');
+ +

Working out listener and panner positions

+ +

Next comes a little bit of slightly fiddly maths. We want to make the boomBox, listener, and panner appear in the center of the screen initially, so we work out the width and height of the viewport, and divide both by two to get our X and Y values for those things. The zPos is only used on the panner, and is updated as the zoom controls are used (see later on); the initial value of 295 was decided on fairly arbitrarily — it sounded good. As long as you set the position of the panner appropriately in relation to the listener position, you will be ok.

+ +

Next for this section, we set a leftBound and rightBound, which is the furthest we want our stereo graph to travel left and right. For the layout, we are using Flexbox to initially place the boomBox right in the center of the viewport, after which we then use iterative transforms and {{domxref("window.requestAnimationFrame()")}} to apply the boomBox movement. Therefore the "0" position is in the center of the viewport so the rightmost position is that position plus half the viewport, but minus 50 (pixels) so the boomBox can't shoot all the way off the right of the screen, and the leftmost position is that position minus half the viewport, but plus 50 (pixels), so the boomBox can't shoot all the way off the left of the screen.

+ +

The last part of this code is the xIterator — we set this to a 150th of the screen width, and then move the boomBox left and right by this amount when the left and right controls are pressed. We use this rather than a constant so that the app is a little more responsive.

+ +
var WIDTH = window.innerWidth;
+var HEIGHT = window.innerHeight;
+
+var xPos = WIDTH/2;
+var yPos = HEIGHT/2;
+var zPos = 295;
+
+leftBound = (-xPos) + 50;
+rightBound = xPos - 50;
+
+xIterator = WIDTH/150;
+ +

Next we set the position of the listener and output the coordinates to the listenerData paragraph. It is always going to be in the same place, in a good position relative to the panner.

+ +
listener.setPosition(xPos,yPos,300);
+listenerData.innerHTML = 'Listener data: X ' + xPos + ' Y ' + yPos + ' Z ' + 300;
+ +

In the positionPanner() function, we set the position of the panner, and output the coordinates to the pannerData paragraph. This function is called with each animation frame as the boomBox is moved, so the panner position updates accordingly:

+ +
function positionPanner() {
+  panner.setPosition(xPos,yPos,zPos);
+  pannerData.innerHTML = 'Panner data: X ' + xPos + ' Y ' + yPos + ' Z ' + zPos;
+}
+ +

Loading and playing our music

+ +

Next we use XHR to load an audio track, and decodeAudioData() to decode it and stick it in a buffer. Then we put the buffer into an {{domxref("AudioBufferSourceNode") }}:

+ +
function getData() {
+  source = audioCtx.createBufferSource();
+  request = new XMLHttpRequest();
+
+  request.open('GET', 'viper.ogg', true);
+
+  request.responseType = 'arraybuffer';
+
+
+  request.onload = function() {
+    var audioData = request.response;
+
+    audioCtx.decodeAudioData(audioData, function(buffer) {
+        myBuffer = buffer;
+        source.buffer = myBuffer;
+
+        source.connect(panner);
+        panner.connect(audioCtx.destination);
+        positionPanner();
+        source.loop = true;
+      },
+
+      function(e){"Error with decoding audio data" + e.err});
+
+  }
+
+  request.send();
+}
+ +

The next stage is to wire up the buttons to stop and play the audio. The pulse wrapper is an extra wrapper {{ htmlelement("div") }} wrapped around the boomBox. We apply the pulsating (scaleY) animation to this element when the play button is clicked, not the boomBox itself, because the boomBox already has animations applied to it throughout the course of the app's running.

+ +
var pulseWrapper = document.querySelector('.pulse-wrapper');
+
+play.onclick = function() {
+  getData();
+  source.start(0);
+  play.setAttribute('disabled', 'disabled');
+  pulseWrapper.classList.add('pulsate');
+}
+
+stop.onclick = function() {
+  source.stop(0);
+  play.removeAttribute('disabled');
+  pulseWrapper.classList.remove('pulsate');
+}
+ +

Moving the boom box and the panner

+ +

The next section of code grabs references to the left, right, zoom in, and zoom out buttons, and defines initial X, Y, and scale amounts for the boomBox to be positioned by when the transforms first start to be applied.

+ +
var leftButton = document.querySelector('.left');
+var rightButton = document.querySelector('.right');
+var zoomInButton = document.querySelector('.zoom-in');
+var zoomOutButton = document.querySelector('.zoom-out');
+
+var boomX = 0;
+var boomY = 0;
+var boomZoom = 0.25;
+ +

Now we get to the four functions that control the left, right, zoom in, and zoom out functionality: moveRight(), moveLeft(), zoomIn(), and zoomOut(). Each is a little different, but works in a similar way:

+ +
    +
  1. The boomX or boomZoom variables are updated in order to change the boomBox's position on the screen.
  2. +
  3. The xPos or zPos variables are updated in order to change the {{domxref("PannerNode") }}'s position in 3D space. The changes are quite small, but these are the values we found to work.
  4. +
  5. A check is done to see if the upper bounds of movement have been reached (a boomX equal or less than leftBound or greater than rightBound, or a boomZoom greater than 4 or equal or less than 0.25.) If so, the values are updated to force the boomBox to stay in certain constraints, and to force the xPos and zPos variables to also stay within certain constrants. These are, respectively, 5 greater or less than WIDTH/2, and a zPos between 295 and 299.9. These are the values we found produced a relatively realistic sounding panning and volume adjustment as the boomBox was moved around.
  6. +
  7. boomBox is transformed (translated and scaled) by the new values of boomX, boomY, and boomZoom to move it around the screen.
  8. +
  9. The positionPanner() function is run to update the position of the panner.
  10. +
  11. A {{domxref("window.requestAnimationFrame") }} instance is called to keep running the function for as long as the mouse button is pressed down.
  12. +
  13. The requestAnimationFrame ID is returned out of the function so that it can be cancelled when the mouse button is released.
  14. +
+ +
function moveRight() {
+  boomX += -xIterator;
+  xPos += -0.066;
+
+  if(boomX <= leftBound) {
+    boomX = leftBound;
+    xPos = (WIDTH/2) - 5;
+  }
+
+  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  positionPanner();
+  rightLoop = requestAnimationFrame(moveRight);
+  return rightLoop;
+}
+
+function moveLeft() {
+  boomX += xIterator;
+  xPos += 0.066;
+
+  if(boomX > rightBound) {
+    boomX = rightBound;
+    xPos = (WIDTH/2) + 5;
+  }
+
+  positionPanner();
+  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  leftLoop = requestAnimationFrame(moveLeft);
+  return leftLoop;
+}
+
+function zoomIn() {
+  boomZoom += 0.05;
+  zPos += 0.066;
+
+  if(boomZoom > 4) {
+    boomZoom = 4;
+    zPos = 299.9;
+  }
+
+  positionPanner();
+  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  zoomInLoop = requestAnimationFrame(zoomIn);
+  return zoomInLoop;
+}
+
+function zoomOut() {
+  boomZoom += -0.05;
+  zPos += -0.066;
+
+  if(boomZoom <= 0.25) {
+    boomZoom = 0.25;
+    zPos = 295;
+  }
+
+  positionPanner();
+  boomBox.style.webkitTransform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  boomBox.style.transform = "translate(" + boomX + "px , " + boomY + "px) scale(" + boomZoom + ")";
+  zoomOutLoop = requestAnimationFrame(zoomOut);
+  return zoomOutLoop;
+}
+ +

In the final block of code, we simply wire up event handlers to control the movement when the buttons are pressed. For each button, the relevant function is invoked onmousedown; then onmouseup, {{domxref("window.cancelAnimationFrame") }} is called along with the returned requestAnimationFrame() ID to stop the animation happening.

+ +
leftButton.onmousedown = moveLeft;
+leftButton.onmouseup = function () {
+  window.cancelAnimationFrame(leftLoop);
+}
+
+rightButton.onmousedown = moveRight;
+rightButton.onmouseup = function () {
+  window.cancelAnimationFrame(rightLoop);
+}
+
+zoomInButton.onmousedown = zoomIn;
+zoomInButton.onmouseup = function () {
+  window.cancelAnimationFrame(zoomInLoop);
+}
+
+zoomOutButton.onmousedown = zoomOut;
+zoomOutButton.onmouseup = function () {
+  window.cancelAnimationFrame(zoomOutLoop);
+}
+ +

As you can see, the actual panner code is pretty simple — specify the positions, and the browser takes care of the rest. It is working out the surrounding code, and the values to use for positioning, which takes a bit more time.

+ +
+

Note : You are probably thinking "why didn't you move the listener and keep the panner still instead: surely that is a bit more obvious?" Well, perhaps, but we felt that since the panner has more methods and properties available to it, moving it would allow more control in the long term.

+
\ No newline at end of file -- cgit v1.2.3-54-g00ecf