L’API Web Audio est un modèle complètement distinct de la
Voir l'API Pen WebAudio avec Oscilloscope de Dennis Gaebel (@dennisgaebel) sur CodePen.
Notre démo ci-dessus contient trois entrées radio qui, une fois sélectionnées, liront l’audio correspondant auquel chacune fait référence. Quand un canal est sélectionné, notre audio sera joué et le graphique de fréquence sera affiché.
Je ne vais pas expliquer chaque ligne du code de la démo; Cependant, je vais expliquer les bits principaux qui aident à afficher la source audio et son graphe de fréquence. Pour commencer, nous aurons besoin d'un peu de balisage.
La partie la plus importante du balisage est le Toile
, qui sera l'élément qui affiche notre oscilloscope. Si vous n'êtes pas familier avec Toile
, Je suggère de lire cet article intitulé "Une introduction à l'utilisation de Canvas".
Avec la scène pour l'affichage du graphique, nous devons créer l'audio.
Nous allons commencer par définir quelques variables importantes pour le contexte audio et le gain. Ces variables seront utilisées pour référencer ultérieurement dans le code.
laissez audioContext, masterGain;
le audioContext
représente un graphe de traitement audio (description complète d'un réseau de traitement de signal audio) construit à partir de modules audio reliés entre eux. Chacun est représenté par un AudioNode
, et lorsqu'ils sont connectés ensemble, ils créent un graphe de routage audio. Ce contexte audio contrôle à la fois la création du ou des nœuds qu’il contient et l’exécution du traitement et du décodage audio..
le AudioContext
doit être créé avant tout, car tout se passe dans un contexte.
Notre masterGain
accepte une entrée d'une ou de plusieurs sources audio et génère le volume de l'audio, dont le gain a été réglé à un niveau spécifié par le nœud GainNode.gain
paramètre a-rate. Vous pouvez considérer le gain principal comme le volume. Nous allons maintenant créer une fonction pour permettre la lecture par le navigateur.
function audioSetup () let source = 'http://ice1.somafm.com/seventies-128-aac'; audioContext = new (window.AudioContext || window.webkitAudioContext) ();
Je commence par définir un la source
variable qui sera utilisée pour référencer le fichier audio. Dans ce cas, j'utilise une URL vers un service de streaming, mais il pourrait aussi s'agir d'un fichier audio. le audioContext
line définit un objet audio et constitue le contexte dont nous avons discuté auparavant. Je vérifie également la compatibilité en utilisant le WebKit
préfixe, mais le support est largement adopté à l'heure actuelle à l'exception de IE11 et Opera Mini.
fonction audioSetup () masterGain = audioContext.createGain (); masterGain.connect (audioContext.destination);
Une fois notre configuration initiale terminée, nous devrons créer et connecter le masterGain
à la destination audio. Pour ce travail, nous utiliserons le relier()
méthode, qui vous permet de connecter l'une des sorties du nœud à une cible.
function audioSetup () let song = new Audio (source), songSource = audioContext.createMediaElementSource (song); songSource.connect (masterGain); song.play ();
le chanson
variable crée un nouvel objet audio en utilisant le L'audio()
constructeur. Vous aurez besoin d'un objet audio pour que le contexte ait une source à lire pour les auditeurs..
le songSource
variable est la sauce magique qui joue l’audio et c’est là que nous allons passer à notre source audio. En utilisant createMediaElementSource ()
, l'audio peut être joué et manipulé comme vous le souhaitez. La dernière variable connecte notre source audio au gain principal (volume). La ligne finale song.play ()
est l'appel à donner réellement la permission de lire l'audio.
laissez audioContext, masterGain; function audioSetup () let source = 'http://ice1.somafm.com/seventies-128-aac'; audioContext = new (window.AudioContext || window.webkitAudioContext) (); masterGain = audioContext.createGain (); masterGain.connect (audioContext.destination); let song = new Audio (source), songSource = audioContext.createMediaElementSource (song); songSource.connect (masterGain); song.play (); Configuration audio();
Voici notre résultat final contenant toutes les lignes de code dont nous avons parlé jusqu'à présent. Je m'assure également de faire l'appel à cette fonction écrite sur la dernière ligne. Ensuite, nous allons créer la forme d'onde audio.
Afin d’afficher l’onde de fréquence de la source audio choisie, nous devons créer la forme d’onde..
analyseur const = audioContext.createAnalyser (); masterGain.connect (analyseur);
La première référence à createAnalyser ()
expose les données de temps et de fréquence audio afin de générer des visualisations de données. Cette méthode génère un AnalyserNode qui transmet le flux audio de l’entrée à la sortie, mais vous permet d’acquérir les données générées, de les traiter et de créer des visualisations audio qui ont exactement une entrée et une sortie. Le nœud d’analyseur sera connecté au gain principal qui est la sortie de notre chemin de signal et donne la possibilité d’analyser une source..
forme d'onde const = new Float32Array (analyser.frequencyBinCount); analyser.getFloatTimeDomainData (forme d'onde);
Ce Float32Array ()
constructeur représente un tableau d'un nombre à virgule flottante de 32 bits. le fréquenceBinCount
propriété du AnalyserNode
interface est une valeur longue non signée correspondant à la moitié de la taille de la transformée rapide de Fourier (FFT). Cela équivaut généralement au nombre de valeurs de données que vous aurez à utiliser avec la visualisation. Nous utilisons cette approche pour collecter nos données de fréquence à plusieurs reprises.
La méthode finale getFloatTimeDomainData
copie la forme d'onde actuelle, ou les données de domaine temporel, dans une Float32Array
tableau passé en elle.
function updateWaveform () requestAnimationFrame (updateWaveform); analyser.getFloatTimeDomainData (forme d'onde);
Toute cette quantité de données et d’usages de traitement requestAnimationFrame ()
collecter des données de domaine temporel à plusieurs reprises et dessinez une sortie "style oscilloscope" de l'entrée audio actuelle. Je fais aussi un autre appel à getFloatTimeDomainData ()
puisque cela doit être mis à jour continuellement car la source audio est dynamique.
analyseur const = audioContext.createAnalyser (); masterGain.connect (analyseur); forme d'onde const = new Float32Array (analyser.frequencyBinCount); analyser.getFloatTimeDomainData (forme d'onde); function updateWaveform () requestAnimationFrame (updateWaveform); analyser.getFloatTimeDomainData (forme d'onde);
La combinaison de tout le code discuté jusqu’à présent a pour résultat la fonction entière ci-dessus. L’appel à cette fonction sera placé dans notre Configuration audio
fonction juste en dessous song.play ()
. Avec la forme d'onde en place, nous avons toujours besoin de dessiner cette information à l'écran en utilisant notre Toile
élément, et ceci est la prochaine partie de notre discussion.
Maintenant que nous avons créé notre forme d'onde et que nous possédons les données dont nous avons besoin, nous devons les dessiner à l'écran. c'est là que le Toile
l'élément est introduit.
fonction drawOscilloscope () requestAnimationFrame (drawOscilloscope); const scopeCanvas = document.getElementById ('oscilloscope'); const scopeContext = scopeCanvas.getContext ('2d');
Le code ci-dessus saisit simplement le Toile
élément afin que nous puissions le référencer dans notre fonction. L'appel à requestAnimationFrame
en haut de cette fonction planifiera la prochaine image d'animation. Ceci est placé en premier afin que nous puissions être aussi proches que possible de 60 images par seconde.
function drawOscilloscope () scopeCanvas.width = waveform.length; scopeCanvas.height = 200;
J'ai mis en place un style de base qui dessinera la largeur et la hauteur du Toile
. La hauteur est définie sur une valeur absolue, tandis que la largeur correspond à la longueur de la forme d'onde produite par la source audio..
function drawOscilloscope () scopeContext.clearRect (0, 0, scopeCanvas.width, scopeCanvas.height); scopeContext.beginPath ();
le clearRect (x, y, largeur, hauteur)
Cette méthode effacera tout contenu précédemment dessiné afin que nous puissions dessiner continuellement le graphe de fréquence. Vous devrez également vous assurer d'appeler beginPath ()
avant de commencer à dessiner le nouveau cadre après avoir appelé clearRect ()
. Cette méthode commence un nouveau chemin en vidant la liste de tous les sous-chemins. La dernière pièce de ce puzzle est une boucle permettant de parcourir les données que nous avons obtenues afin que nous puissions continuellement dessiner ce graphique de fréquence à l'écran..
fonction drawOscilloscope () for (let i = 0; i < waveform.length; i++) const x = i; const y = ( 0.5 + (waveform[i] / 2) ) * scopeCanvas.height; if(i == 0) scopeContext.moveTo(x, y); else scopeContext.lineTo(x, y); scopeContext.stroke();
Cette boucle ci-dessus attire notre forme d'onde vers le Toile
élément. Si nous enregistrons la longueur de la forme d'onde sur la console (pendant la lecture de l'audio), 1024 signaleront à plusieurs reprises. Cela équivaut généralement au nombre de valeurs de données que vous devrez utiliser pour la visualisation. Si vous vous souvenez de la section précédente pour la création de la forme d'onde, nous obtenons cette valeur de Float32Array (analyser.frequencyBinCount)
. Voici comment nous pouvons référencer la valeur 1024 que nous allons parcourir en boucle.
le déménager à()
Cette méthode déplacera littéralement le point de départ d’un nouveau sous-chemin vers la mise à jour. (x, y)
coordonnées. le lineTo ()
méthode connecte le dernier point du sous-chemin à la x, y
coordonne avec une ligne droite (mais ne la dessine pas réellement). La dernière pièce appelle accident vasculaire cérébral()
fourni par Toile
afin que nous puissions réellement tracer la ligne de fréquence. Je vais laisser la partie contenant le calcul en tant que défi de lecteur, alors assurez-vous de poster votre réponse dans les commentaires ci-dessous.
fonction drawOscilloscope () requestAnimationFrame (drawOscilloscope); const scopeCanvas = document.getElementById ('oscilloscope'); const scopeContext = scopeCanvas.getContext ('2d'); scopeCanvas.width = waveform.length; scopeCanvas.height = 200; scopeContext.clearRect (0, 0, scopeCanvas.width, scopeCanvas.height); scopeContext.beginPath (); pour (soit i = 0; i < waveform.length; i++) const x = i; const y = ( 0.5 + (waveform[i] / 2) ) * scopeCanvas.height; if(i == 0) scopeContext.moveTo(x, y); else scopeContext.lineTo(x, y); scopeContext.stroke();
C’est toute la fonction que nous avons créée pour dessiner la forme d’onde que nous appellerons après song.play ()
placé dans notre Configuration audio
fonction, qui comprend également notre updateWaveForm
appel de fonction aussi bien.
J'ai seulement expliqué les éléments importants de la démo, mais assurez-vous de lire les autres parties de ma démo pour mieux comprendre le fonctionnement des boutons radio et du bouton Démarrer par rapport au code ci-dessus, y compris le style CSS..
L'API Web Audio est vraiment amusant pour quiconque s'intéresse à l'audio de toutes sortes, et je vous encourage à aller plus loin. J'ai également rassemblé des exemples très amusants de CodePen qui utilisent l'API Web Audio pour construire des exemples très intéressants. Prendre plaisir!