Les concepts de base de la 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. Dans ce contexte, création des sources — telles que `<audio>`, oscillateur, flux
3. Création des noeuds d'effets, tels que réverb, filtres biquad, balance, compresseur
4. Choix final de la sortie audio, par exemple les enceintes du système
5. Connection des sources aux effets, et des effets à la sortie.

![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.](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/webaudioapi_en.svg)

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.](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/audionodes.svg)

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

* générées directement en JavaScript avec un noeud audio (tel qu'un oscillateur)
* créées à partir de données PCM brutes (le contexte audio a des méthodes pour décoder les formats audio supportés)
* fournies par une balise HTML media (telle que `<video>` ou `<audio>`)
* récupérées directement avec WebRTC `MediaStream` (une webcam ou un microphone)
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 Wikipédia Echantillonage (signal).

Mémoire tampon : trames, échantillons et canaux
-----------------------------------------------

Un `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 `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 mono aura 44100 échantillons, et 44100 trames. Sa propriété `length` vaudra 44100.
* le stéréo aura 88200 échantillons, et 44100 trames. Sa propriété `length` vaudra aussi 44100, puisqu'elle correspond au nombre de trames.

![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.](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/sampleframe.svg)

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:


```js
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.


```js
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 :

|  |  |
| --- | --- |
| *Mono* | `0: M: mono` |
| *Stereo* | `0: L: gauche1: R: droit` |
| *Quad* | `0: L: gauche1: R: droit2: SL: surround gauche3: SR:
surround droit` |
| *5.1* | `0: L: gauche1: R: droit2: C: centre3: LFE:
subwoofer4: SL: surround gauche5: 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é `AudioNode.channelInterpretation` (en-US) .

| Interprétation | Canaux d'entrée | Canaux de sortie | Règles de conversion |
| --- | --- | --- | --- |
| `speakers` | `1` *(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.Moutput.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.Moutput.R = input.Moutput.SL = 0output.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 = 0output.R = 0``output.C = input.Moutput.LFE = 0output.SL = 0output.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.Loutput.R = input.Routput.SL = 0output.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.Loutput.R = input.Routput.C = 0output.LFE
= 0output.SL = 0output.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.Loutput.R = input.Routput.C = 0output.LFE
= 0output.SL = input.SLoutput.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.Coutput.R = input.R +
0.7071 * input.C`output.SL = input.SLoutput.SR = input.SR`` |
| Autres configurations non-standard | 
 Les 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.
  |
| `discrete` | tout (`x`) | tout (`y`) pour lequel `x<y` | *Conversion 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>y` | *Conversion 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 `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 `<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](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/fttaudiodata.svg)

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

`AnalyserNode.getFloatFrequencyData()`

Copie les données de fréquence dans le tableau `Float32Array` (en-US) passé en argument.


`AnalyserNode.getByteFrequencyData()`

Copies les données de fréquence dans le tableau d'octets non signés `Uint8Array` (en-US) passé en argument.


`AnalyserNode.getFloatTimeDomainData()`

Copie les données de l'onde de forme, ou domaine temporel, dans le `Float32Array` (en-US) passé en argument.

`AnalyserNode.getByteTimeDomainData()`

Copie les données de l'onde de forme, ou domaine temporel, dans le tableau d'octets non signés `Uint8Array` (en-US) 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 `PannerNode` (en-US) et `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é](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/pannernode.svg)

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°](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/listener.svg)

**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 `ChannelMergerNode` (en-US) prend une série d'entrées mono entrée et restitue un seul signal multi-canaux :

![](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/fanin.svg)

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

![](/fr/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/fanout.svg)