Dans les navigateurs, y’a une API super cool qui s'appelle AudioContext. En gros, ça permet de mumuse de façons très avancée avec du son : distorsion, réverbération, spatialisation, synchronisation sonore au micropoil près, etc.
Et ce qui est rigolo, c’est que le code donne vraiment l'impression de jouer à l'apprenti ingénieur son en train de brancher ses câbles, genre « alors, on demande à notre centrale sonore de choper le son MACHIN, tu me le décodes et le connectes au buffer BIDULE, puis tu l'alignes juste après tel autre câble », etc.
C’est vraiment monstrueux et ça défonce.
Exemples :
- des boîte à rythmes :
https://codepen.io/teropa/pen/JLjXGK https://codepen.io/sgput/full/vGRvMW
-
spatialisation
- visualisation en fonction du rythme :winamp: :
https://codepen.io/soulwire/full/Dscga
- un oscillateur (il a son API dédié) :
https://webaudioapi.com/samples/oscillator/
Là je suis en train de dév. un petit truc qui utilise la fonction la plus basique du monde : t'appuies sur un bouton, ça joue le son. Ça, on peut aussi le faire sans cette API spécifique,
mais sans cette API, impossible d'avoir dans Safari une synchro parfaite entre le moment où on tape le bouton et le moment où la lecture du son est effective.
Parmi les fonctions de « branchements », y’a
decodeAudioData. C’est le morceau de l’API qui doit être utilisé pour transformer les octets qui composent un son en un AudioBuffer qu’on va ensuite connecter à la sortie audio (grosso merdo).
Donc typiquement, pour gagner en lisibilité, j'ai écrit une fonction qui va grouper quelques étapes :
- choper le son sur base de son URL
- le décoder
- retourner l’AudioBuffer obtenu.
Ça marche nickel, tout le monde est content. J’ai au final une classe nommée Sfx qui au final limite l’usage à Sfx.makeFrom(url) pour initialiser, et Sfx.play(bufferSourceNode, delay) pour le jouer autant de fois qu'on veut.
Sauf que Safari fait chier ! Normalement :
- decodeAudioData est asynchrone mais, contrairement aux autres, Safari ne retourne pas une Promise : il faut tout gérer dans le callback

;
- le buffer décodé peut être cloné pour être réutilisé plus tard, mais pas dans Safari qui le tue dès la fin du callback (mon but était d’éviter la cascade de callbacks) ;
- au lieu de retourner une erreur parce qu'il a pas géré le buffer, Safari retourne null

;
- et j'en passe.
Je vais d’abord voir si je peux changer l’architecture de ma classe, quitte à avoir du #callbackception, mais c'est juste super pénible comme juste une seule méthode de l’API peut être foutue à ce point et avoir des implications sur l'architecture du code

.
Si ça marche pas, je vais tenter la librairie que quelqu’un a écrite pour standardiser AudioContext.
Son adaptation de decodeAudioData fait 100 lignes (soit ma classe Sfx entière

) + appel à d’autre trucs, donc ça alourdira probablement mon projet de manière considérable

.