Die Unterstützung der Web Audio API in Chrome wurde kontinuierlich verbessert. In Chrome 49 (Beta seit Februar 2016 und voraussichtlich im März 2016 stabil) haben wir mehrere Funktionen aktualisiert, um die Spezifikation zu verfolgen. Außerdem wurde ein neuer Knoten hinzugefügt.
„decodeAudioData()“ gibt jetzt ein Promise zurück.
Die Methode decodeAudioData() für AudioContext
gibt jetzt ein Promise
zurück, wodurch die Promise-basierte asynchrone Musterverarbeitung aktiviert wird. Für die Methode decodeAudioData()
wurden Erfolgs- und Fehler-Callback-Funktionen immer als Parameter verwendet:
context.decodeAudioData( arraybufferData, onSuccess, onError);
Jetzt können Sie jedoch die Promise-Methode verwenden, um die asynchrone Natur der Decodierung von Audiodaten zu verarbeiten:
context.decodeAudioData( arraybufferData ).then(
(buffer) => { /* store the buffer */ },
(reason) => { console.log("decode failed! " + reason) });
Obwohl dies in einem einzigen Beispiel ausführlicher aussieht, wird die asynchrone Programmierung mit Promise-Objekten einfacher und einheitlicher. Aus Kompatibilitätsgründen werden die Callback-Funktionen für Erfolg und Fehler gemäß der Spezifikation weiterhin unterstützt.
„OfflineAudioContext“ unterstützt jetzt „pause()“ und „resume()“.
Auf den ersten Blick mag es seltsam vorkommen, dass wir „pause()“ für einen OfflineAudioContext verwenden.
Schließlich wurde suspend()
zu AudioContext
hinzugefügt, um die Audiohardware in den Standby-Modus zu versetzen. Dies scheint in Szenarien beim Rendern in einen Zwischenspeicher sinnlos zu sein (wofür natürlich OfflineAudioContext
vorgesehen ist).
Der Sinn dieses Features besteht jedoch darin, jeweils nur einen Teil eines "Scores" zu erstellen, um die Speichernutzung zu minimieren. Sie können weitere Knoten erstellen, während
der Vorgang mitten im Rendering angehalten wird.
Die Mondlichtsonate von Beethoven enthält etwa 6.500 Noten.
Wahrscheinlich wird jede "Notiz" in mindestens zwei Audiodiagrammknoten zerlegt (z.B. einen AudioBuffer und einen Gain-Knoten). Wenn Sie die gesamten siebeneinhalb Minuten in einem Puffer mit OfflineAudioContext
rendern möchten, sollten Sie nicht alle Knoten auf einmal erstellen. Stattdessen können Sie sie in Zeitblöcken erstellen:
var context = new OfflineAudioContext(2, length, sampleRate);
scheduleNextBlock();
context.startRendering().then( (buffer) => { /* store the buffer */ } );
function scheduleNextBlock() {
// create any notes for the next blockSize number of seconds here
// ...
// make sure to tell the context to suspend again after this block;
context.suspend(context.currentTime + blockSize).then( scheduleNextBlock );
context.resume();
}
Auf diese Weise können Sie die Anzahl der Knoten, die zu Beginn des Renderings vorab erstellt werden müssen, minimieren und den Speicherbedarf verringern.
IIRFilterNode
In der Spezifikation wurde ein Knoten für Audiophile hinzugefügt, die ihre eigene, genau festgelegte infinite-impulse-response erstellen möchten: den IIRFilterNode.
Dieser Filter ergänzt den BiquadFilterNode, ermöglicht jedoch die vollständige Spezifikation der Filterantwortparameter (im Gegensatz zum benutzerfreundlichen AudioParams
des BiquadFilterNode
für Typ, Häufigkeit, Q usw.). Der IIRFilterNode
ermöglicht die präzise Spezifikation von Filtern, die zuvor nicht erstellt werden konnten, z. B. Filter für eine einzelne Reihenfolge. Die Verwendung des IIRFilterNode erfordert jedoch ein gewisses Verständnis der Funktionsweise von IIR-Filtern. Außerdem sind sie wie BiquadFilterNodes nicht planbar.
Vorherige Änderungen
Ich möchte auch einige Verbesserungen erwähnen, die in der Vergangenheit vorgenommen wurden: In Chrome 48 wurde die BiquadFilter
-Knotenautomatisierung mit der Audiorate ausgeführt. Die API hat sich hierfür überhaupt nicht geändert, aber dies bedeutet jedoch, dass Ihre Filter-Sweeps noch gleichmäßiger klingen. Ebenfalls in Chrome 48 haben wir eine Verkettung zur Methode AudioNode.connect()
hinzugefügt, indem der Knoten zurückgegeben wird, mit dem eine Verbindung hergestellt wird. Dies vereinfacht das Erstellen von Knotenketten, wie in diesem Beispiel:
sourceNode.connect(gainNode).connect(filterNode).connect(context.destination);
Das ist im Moment erstmal alles und rocke weiter!