Die Web-Audio-API ist ein vollständig von der
Siehe Pen WebAudio API mit Oszilloskop von Dennis Gaebel (@dennisgaebel) auf CodePen.
Unsere obige Demo enthält drei Radioeingänge, bei deren Auswahl das entsprechende Audio abgespielt wird, auf das sich jeder bezieht. Wenn ein Kanal ausgewählt ist, wird unser Audio abgespielt und das Frequenzdiagramm angezeigt.
Ich werde nicht jede Zeile des Codes der Demo erklären. Ich erkläre jedoch die primären Bits, die zur Anzeige der Audioquelle und ihres Frequenzdiagramms beitragen. Um zu beginnen, benötigen wir ein kleines Markup.
Der wichtigste Teil des Markups ist der Segeltuch
, Dies ist das Element, das unser Oszilloskop anzeigt. Wenn Sie nicht vertraut sind Segeltuch
, Ich schlage vor, diesen Artikel mit dem Titel "Eine Einführung in die Arbeit mit Canvas" zu lesen.
Mit dem Bühnenbild für die Anzeige der Grafik müssen wir das Audio erstellen.
Wir beginnen mit der Definition einiger wichtiger Variablen für den Audiokontext und die Verstärkung. Diese Variablen werden zu einem späteren Zeitpunkt im Code verwendet.
lassen Sie audioContext, masterGain;
Das audioContext
repräsentiert einen Audiobearbeitungsgraph (eine vollständige Beschreibung eines Audiosignalverarbeitungsnetzwerks), der aus miteinander verbundenen Audiomodulen aufgebaut ist. Jeder wird durch ein dargestellt AudioNode
, Wenn sie miteinander verbunden sind, erstellen sie ein Audio-Routing-Diagramm. Dieser Audiokontext steuert sowohl die Erstellung der darin enthaltenen Knoten als auch die Ausführung der Audiobearbeitung und -dekodierung.
Das AudioContext
muss vor allem anderen erstellt werden, da alles in einem Kontext geschieht.
Unsere masterGain
akzeptiert eine Eingabe von einer oder mehreren Audioquellen und gibt die Lautstärke des Audiosignals aus, deren Verstärkung auf einen vom Knoten festgelegten Pegel eingestellt wurde GainNode.gain
a-rate-parameter. Sie können sich die Master-Verstärkung als Lautstärke vorstellen. Jetzt erstellen wir eine Funktion, um die Wiedergabe über den Browser zu ermöglichen.
function audioSetup () let source = 'http://ice1.somafm.com/seventies-128-aac'; audioContext = new (window.AudioContext || window.webkitAudioContext) ();
Ich beginne mit der Definition eines Quelle
Variable, die zum Referenzieren der Audiodatei verwendet wird. In diesem Fall verwende ich eine URL zu einem Streaming-Dienst, es könnte sich jedoch auch um eine Audiodatei handeln. Das audioContext
line definiert ein Audioobjekt und ist der Kontext, den wir zuvor besprochen haben. Ich überprüfe auch die Kompatibilität mit der WebKit
Präfix, aber die Unterstützung ist derzeit weit verbreitet mit Ausnahme von IE11 und Opera Mini.
function audioSetup () masterGain = audioContext.createGain (); masterGain.connect (audioContext.destination);
Nachdem die anfänglichen Einstellungen abgeschlossen sind, müssen wir das erstellen und verbinden masterGain
zum Audio-Ziel. Für diesen Job verwenden wir die verbinden()
Methode, mit der Sie einen der Ausgänge des Knotens mit einem Ziel verbinden können.
function audioSetup () let song = neues Audio (Quelle), songSource = audioContext.createMediaElementSource (song); songSource.connect (masterGain); song.play ();
Das Lied
Variable erstellt ein neues Audioobjekt mit der Audio()
Konstrukteur. Sie benötigen ein Audioobjekt, damit der Kontext eine Quelle für die Wiedergabe von Hörern hat.
Das songSource
variabel ist die magische Soße, die das Audio spielt, und in der wir unsere Audioquelle übergeben. Durch die Nutzung createMediaElementSource ()
, Das Audio kann wie gewünscht abgespielt und bearbeitet werden. Die letzte Variable verbindet unsere Audioquelle mit der Master-Verstärkung (Lautstärke). Die letzte Zeile song.play ()
ist der Aufruf, um tatsächlich die Erlaubnis zu geben, das Audio abzuspielen.
lassen Sie 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); lass song = new Audio (source), songSource = audioContext.createMediaElementSource (song); songSource.connect (masterGain); song.play (); Audio-Setup();
Hier ist unser Endergebnis mit allen Codezeilen, die wir bisher besprochen haben. Ich stelle auch sicher, dass der Aufruf dieser Funktion in der letzten Zeile erfolgt. Als Nächstes erstellen wir die Audiowellenform.
Um die Frequenzwelle für die von Ihnen gewählte Audioquelle anzuzeigen, müssen Sie die Wellenform erstellen.
const analyzer = audioContext.createAnalyser (); masterGain.connect (Analysator);
Der erste Hinweis auf createAnalyser ()
legt die Audiozeit- und -frequenzdaten frei, um Datenvisualisierungen zu erstellen. Bei dieser Methode wird ein AnalyserNode erstellt, der den Audiostrom von der Eingabe zur Ausgabe überträgt, aber Sie können die erzeugten Daten erfassen, verarbeiten und Audiovisualisierungen erstellen, die genau einen Eingang und einen Ausgang haben. Der Analysatorknoten wird mit der Master-Verstärkung verbunden, die der Ausgang unseres Signalpfads ist, und ermöglicht die Analyse einer Quelle.
const Wellenform = neuer Float32Array (analyser.frequencyBinCount); analyser.getFloatTimeDomainData (Wellenform);
Diese Float32Array ()
Konstruktor repräsentiert ein Array mit einer 32-Bit-Gleitkommazahl. Das frequencyBinCount
Eigentum der AnalyserNode
Die Schnittstelle ist ein vorzeichenloser langer Wert, der nur halb so groß ist wie die Größe der FFT (Fast Fourier Transform). Dies entspricht im Allgemeinen der Anzahl der Datenwerte, die Sie für die Visualisierung verwenden werden. Wir verwenden diesen Ansatz, um unsere Frequenzdaten wiederholt zu erfassen.
Die endgültige Methode getFloatTimeDomainData
kopiert die aktuelle Wellenform oder die Zeitbereichsdaten in eine Float32Array
Array weitergegeben.
function updateWaveform () requestAnimationFrame (updateWaveform); analyser.getFloatTimeDomainData (Wellenform);
Diese gesamte Daten- und Verarbeitungsmenge verwendet requestAnimationFrame ()
Zeitbereichsdaten sammeln wiederholt und zeichnen Sie einen "Oszilloskopstil" -Ausgang des aktuellen Audioeingangs. Ich rufe auch noch mal an getFloatTimeDomainData ()
da dies ständig aktualisiert werden muss, da die Audioquelle dynamisch ist.
const analyzer = audioContext.createAnalyser (); masterGain.connect (Analysator); const Wellenform = neuer Float32Array (analyser.frequencyBinCount); analyser.getFloatTimeDomainData (Wellenform); function updateWaveform () requestAnimationFrame (updateWaveform); analyser.getFloatTimeDomainData (Wellenform);
Die Kombination aller bisher besprochenen Codes führt zur gesamten Funktion. Der Aufruf zu dieser Funktion wird in unsere gestellt Audio-Setup
Funktion direkt darunter song.play ()
. Wenn die Wellenform vorhanden ist, müssen wir diese Informationen immer noch mit unserem auf den Bildschirm ziehen Segeltuch
Element, und dies ist der nächste Teil unserer Diskussion.
Nachdem wir unsere Wellenform erstellt haben und die erforderlichen Daten besitzen, müssen wir sie auf den Bildschirm zeichnen. das ist, wo die Segeltuch
Element wird eingeführt.
function drawOscilloscope () requestAnimationFrame (drawOscilloscope); const scopeCanvas = document.getElementById ('Oszilloskop'); const scopeContext = scopeCanvas.getContext ('2d');
Der Code oben greift einfach auf Segeltuch
Element, so dass wir in unserer Funktion darauf verweisen können. Der Anruf an requestAnimationFrame
Oben in dieser Funktion wird der nächste Animationsrahmen geplant. Dies steht an erster Stelle, damit wir so nahe wie möglich an 60FPS herankommen können.
function drawOscilloscope () scopeCanvas.width = Waveform.length; scopeCanvas.height = 200;
Ich habe ein grundlegendes Styling implementiert, das die Breite und Höhe der Farbe zeichnet Segeltuch
. Die Höhe ist auf einen absoluten Wert eingestellt, während die Breite der Länge der Wellenform entspricht, die von der Audioquelle erzeugt wird.
function drawOscilloscope () scopeContext.clearRect (0, 0, scopeCanvas.width, scopeCanvas.height); scopeContext.beginPath ();
Das clearRect (x, y, Breite, Höhe)
Mit dieser Methode werden alle zuvor gezeichneten Inhalte gelöscht, sodass der Frequenzgraph kontinuierlich gezeichnet werden kann. Sie müssen auch sicherstellen, dass Sie anrufen beginPath ()
bevor Sie mit dem Zeichnen des neuen Rahmens beginnen clearRect ()
. Diese Methode startet einen neuen Pfad, indem die Liste aller Subpfade geleert wird. Das letzte Stück in diesem Rätsel ist eine Schleife, um die erhaltenen Daten zu durchlaufen, damit wir diese Frequenzkurve kontinuierlich auf den Bildschirm zeichnen können.
Funktion drawOscilloscope () für (sei 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();
Diese Schleife oben zieht unsere Wellenform an Segeltuch
Element. Wenn wir die Wellenformlänge (während der Audiowiedergabe) auf der Konsole protokollieren, wird 1024 wiederholt angezeigt. Dies entspricht im Allgemeinen der Anzahl der Datenwerte, mit denen Sie für die Visualisierung spielen müssen. Wenn Sie sich zur Erstellung der Wellenform aus dem vorherigen Abschnitt zurückrufen, erhalten Sie diesen Wert von Float32Array (analyser.frequencyBinCount)
. So können wir auf den 1024-Wert verweisen, den wir durchlaufen.
Das ziehen nach()
Die Methode verschiebt den Startpunkt eines neuen Unterpfads buchstäblich zum aktualisierten (x, y)
Koordinaten. Das lineTo ()
Methode verbindet den letzten Punkt im Unterpfad mit dem x, y
koordiniert mit einer geraden Linie (zeichnet sie jedoch nicht) Das letzte Stück ruft Schlaganfall()
zur Verfügung gestellt von Segeltuch
so können wir tatsächlich die Frequenzlinie zeichnen. Ich lasse den Teil, der die Mathematik enthält, als Leserherausforderung, also posten Sie Ihre Antwort in den Kommentaren unten.
function drawOscilloscope () requestAnimationFrame (drawOscilloscope); const scopeCanvas = document.getElementById ('Oszilloskop'); const scopeContext = scopeCanvas.getContext ('2d'); scopeCanvas.width = Waveform.length; scopeCanvas.height = 200; scopeContext.clearRect (0, 0, scopeCanvas.width, scopeCanvas.height); scopeContext.beginPath (); für (sei 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();
Dies ist die gesamte Funktion, die wir erstellt haben, um die Wellenform zu zeichnen, die wir danach aufrufen werden song.play ()
in unserem platziert Audio-Setup
Funktion, die auch unsere umfasst updateWaveForm
Funktionsaufruf auch.
Ich habe nur die wichtigen Teile für die Demo erklärt, aber lesen Sie sich die anderen Teile meiner Demo durch, um besser zu verstehen, wie die Radioknöpfe und der Startknopf in Bezug auf den obigen Code funktionieren, einschließlich des CSS-Stylings.
Die Web-Audio-API macht wirklich Spaß für alle, die sich für Audio jeglicher Art interessieren. Ich habe auch einige wirklich lustige Beispiele aus CodePen gesammelt, die die Web Audio API verwenden, um einige wirklich interessante Beispiele zu erstellen. Genießen!