In Chrome wird die Unterstützung der Web Audio API kontinuierlich und unbemerkt verbessert. In Chrome 49 (Betaversion seit Februar 2016, voraussichtlich stabile Version im März 2016) haben wir mehrere Funktionen aktualisiert, um die Spezifikation zu erfüllen, und einen neuen Knoten hinzugefügt.
decodeAudioData() gibt jetzt ein Versprechen zurück
Die Methode decodeAudioData() von AudioContext
gibt jetzt eine Promise
zurück, wodurch eine Promise-basierte asynchrone Musterverarbeitung möglich ist. Die Methode decodeAudioData()
hat immer Erfolg- und Fehler-Callback-Funktionen als Parameter akzeptiert:
context.decodeAudioData( arraybufferData, onSuccess, onError);
Jetzt kannst du stattdessen die Standard-Promise-Methode verwenden, um die asynchrone Dekodierung von Audiodaten zu verarbeiten:
context.decodeAudioData( arraybufferData ).then(
(buffer) => { /* store the buffer */ },
(reason) => { console.log("decode failed! " + reason) });
In einem einzelnen Beispiel sieht das zwar etwas umständlicher aus, aber Promises machen die asynchrone Programmierung einfacher und konsistenter. Aus Gründen der Abwärtskompatibilität werden die Rückruffunktionen „Success“ und „Error“ gemäß der Spezifikation weiterhin unterstützt.
OfflineAudioContext unterstützt jetzt suspend() und resume()
Auf den ersten Blick mag es seltsam erscheinen, suspend() für einen OfflineAudioContext zu verwenden.
Schließlich wurde suspend()
zu AudioContext
hinzugefügt, um die Audiohardware in den Standby-Modus versetzen zu können. Das ist in Szenarien, in denen in einen Puffer gerendert wird, sinnlos. Dafür ist natürlich OfflineAudioContext
da.
Der Sinn dieser Funktion besteht jedoch darin, jeweils nur einen Teil eines „Werts“ zu berechnen, um die Speichernutzung zu minimieren. Sie können weitere Knoten erstellen, während ein Rendervorgang pausiert ist.
Beethovens Mondscheinsonate enthält beispielsweise etwa 6.500 Noten.
Jede „Note“ wird wahrscheinlich in mindestens ein paar Audiograph-Knoten zerlegt (z.B. einen AudioBuffer und einen Gain-Knoten). Wenn du die gesamten siebeneinhalb Minuten mit OfflineAudioContext
in einen Puffer rendern möchtest, solltest du wahrscheinlich nicht alle diese Knoten gleichzeitig 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();
}
So können Sie die Anzahl der Knoten minimieren, die zu Beginn des Renderings vorab erstellt werden müssen, und den Speicherbedarf verringern.
IIRFilterNode
Die Spezifikation enthält einen Knoten für Audiophile, die ihre eigene genau spezifizierte unendliche Impulsantwort erstellen möchten: den IIRFilterNode.
Dieser Filter ergänzt den BiquadFilterNode, ermöglicht aber eine vollständige Angabe der Filterantwortparameter (anstelle der BiquadFilterNode
-AudioParams
für Typ, Frequenz, Q usw.). Mit der IIRFilterNode
können Filter genau spezifiziert werden, die zuvor nicht erstellt werden konnten, z. B. Filter mit einer Ordnung. Die Verwendung des IIRFilterNodes erfordert jedoch ein fundiertes Wissen über die Funktionsweise von IIR-Filtern. Außerdem können sie nicht wie BiquadFilterNodes geplant werden.
Vorherige Änderungen
Ich möchte auch einige Verbesserungen erwähnen, die bereits implementiert wurden: In Chrome 48 wurde die BiquadFilter
-Knotenautomatisierung mit der Audiorate ausgeführt. Die API hat sich dadurch nicht geändert, aber deine Filtersweeps klingen jetzt noch glatter. Außerdem haben wir in Chrome 48 die AudioNode.connect()
-Methode um eine Verknüpfung erweitert, indem wir den Knoten zurückgeben, mit dem eine Verbindung hergestellt wird. So lassen sich leichter Knotenketten erstellen, wie in diesem Beispiel:
sourceNode.connect(gainNode).connect(filterNode).connect(context.destination);
Das war's fürs Erste.