Emscripten liefert seine eigene Implementierung der OpenAL 1.1 API, die die Web Audio API als Backend verwendet.
Sie können vernünftigerweise erwarten, dass portierte OpenAL-Anwendungen ohne zusätzlichen Aufwand „einfach funktionieren“. Verknüpfen Sie einfach mit dem Linker-Flag -lopenal.
Es gibt einige implementierungsspezifische Aspekte, die es wert sind, berücksichtigt zu werden und hier dokumentiert sind.
Warnung
Es gab früher kein zusätzliches Flag, das an den Compiler übergeben werden musste, um OpenAL zu verwenden. Die Angabe von -lopenal, wie oben erwähnt, sollte jedoch als obligatorisch angesehen werden (irgendwann in der Zukunft wird sie es sein)!
Die folgenden Erweiterungen werden von Emscriptens OpenAL-Implementierung unterstützt.
ALC_SOFT_pause_device;
ALC_SOFT_HRTF;
AL_EXT_float32;
AL_SOFT_loop_points;
AL_SOFT_source_length;
AL_EXT_source_distance_model;
AL_SOFT_source_spatialize;
Warnung
Das bedeutet nicht, dass Sie einfach ihre Anwesenheit annehmen sollten! Zur Korrektheit sollten Sie immer prüfen, ob eine Erweiterung unterstützt wird, bevor Sie sie verwenden, wie es eine gute Anwendung tun würde.
Beachten Sie, dass Ihre Anwendung der Javascript-Hauptschleife für die Audioverarbeitung weichen muss (siehe Browser-Hauptschleife). Einfach ausgedrückt, blockiert diese Art von Code auf unbestimmte Zeit
while(nframes < THE_NUMBER_OF_FRAMES_WE_WANT)
alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, 1, &nframes);
Der obige Schnipsel funktioniert normalerweise in nativen Anwendungen, da die meisten OpenAL-Implementierungen einen oder mehrere separate Threads besitzen und verwalten. Dies ist in Emscripten nicht der Fall. Stattdessen müssen Sie jede solche Abfrage nur einmal pro „Hauptschleifen-Iteration“ durchführen (d.h. den Callback, den Sie über emscripten_set_main_loop() oder emscripten_set_main_loop_arg() bereitstellen).
Ein weiteres Problem, das Sie möglicherweise erfahren, ist, dass Browser die Audiowiedergabe vor Benutzereingaben nicht zulassen. Dies verhindert das automatische Abspielen von Medien auf Seiten, was ärgerlich sein kann, wenn Sie das nicht wollten. Emscriptens OpenAL-Implementierung (und auch SDL1) wird automatisch auf einen Benutzerklick oder Tastendruck auf dem Dokument und der Canvas lauschen und das Audio für Sie fortsetzen. Das bedeutet, dass die Audiowiedergabe beginnen sollte, sobald der Benutzer etwas auf der Seite tut. (Siehe autoResumeAudioContext(), wie dies intern geschieht.)
Der Versuch, einen Eingabestream zum Audioaufnahmegerät des Benutzers zu öffnen, führt zum asynchronen Erscheinen eines kleinen browserspezifischen Dialogs, der um die Erlaubnis des Benutzers fragt und bei einigen Browsern um die Wahl des Aufnahmegeräts.
Vor diesem Hintergrund wird, wenn alcCaptureOpenDevice() mit gültigen und unterstützten Parametern aufgerufen wird, ein „Proxy“-Gerät zurückgegeben, das keine Samples erfolgreich erfasst, bis der Benutzer im besagten Dialog auf „Zulassen“ klickt.
Das bedeutet, wenn alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, 1, &nframes) aufgerufen wird, bleibt nframes auf Null gesetzt, bis der Benutzer auf „Zulassen“ klickt. Sie möchten möglicherweise, dass Ihre App dieses spezifische Verhalten handhabt.
Wenn der Benutzer auf „Verweigern“ klickt, wird das Gerät ungültig (da dies dem Abziehen des physischen Geräts ähnelt) und Aufrufe an alcCapture*-Funktionen auf diesem Gerät schlagen dann konsequent mit ALC_INVALID_DEVICE fehl. Ihre Anwendung sollte darauf vorbereitet sein, dies ordnungsgemäß zu behandeln.
Hinweis
Einige Browser „merken“ sich diese Wahl und wenden sie stattdessen jedes Mal automatisch an, wenn sie erneut gefragt würde. Es gibt keine Möglichkeit für die Implementierung, dieses Verhalten zu erkennen.
Intern werden die Erfassungsdaten von Web Audio immer von einem Javascript Float32Array unterstützt. Daher sind AL_FORMAT_MONO_FLOAT32 und AL_FORMAT_STEREO_FLOAT32 die einzigen Formate, die keine Konvertierung der erfassten Samples von ihrem ursprünglichen Typ in einen anderen erfordern.
Auch die tatsächliche Abtastrate, mit der Samples vom Gerät erfasst werden, wird derzeit vom Browser und der Hardware diktiert, anstatt vom Benutzercode. Wenn diese Abtastrate nicht mit der von Ihrer App angeforderten übereinstimmt, muss die Implementierung in Ihrem Namen ein Resampling durchführen.
Diese Abtastrate wird durch audioCtx.sampleRate gegeben, wobei audioCtx das AudioContext-Objekt ist, das intern vom relevanten Erfassungs- ALCdevice verwendet wird. Derzeit bietet Emscripten Anwendungen keinen direkten Zugriff auf diesen Wert, dies könnte jedoch durch eine Emscripten-spezifische OpenAL-Erweiterung bereitgestellt werden (die noch nicht existiert, da sie eine Registrierung erfordert).
Im Moment gibt es jedoch eine schnelle und de facto zuverlässige Methode dafür (C-Beispiel)
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
// Avoid calling this more than once! Caching the value is up to you.
unsigned query_sample_rate_of_audiocontexts() {
return EM_ASM_INT({
var AudioContext = window.AudioContext || window.webkitAudioContext;
var ctx = new AudioContext();
var sr = ctx.sampleRate;
ctx.close();
return sr;
});
}
#endif
Es ist vernünftig zu erwarten, dass diese Abtastrate entweder 44100Hz oder 48000Hz beträgt. Sie können es jetzt testen, indem Sie den Javascript-Teil in die Konsole Ihres Browsers kopieren, wenn Sie neugierig sind.
Derzeit führt die OpenAL-Erfassungsimplementierung ein naives lineares Resampling durch, da es einfach ist und der geringe Qualitätsverlust als akzeptabel erachtet wurde.
Sie können dies jedoch gerne verbessern, indem Sie beitragen, wenn Sie möchten! Siehe zum Beispiel dieses Problem.
Ebenso, wenn Sie eine bestimmte Erweiterung implementiert sehen möchten (ob sie registriert ist oder nicht), ist Ihre beste Wahl, entweder ein Problem zu melden (vorausgesetzt, es gab kein verwandtes früheres Problem dafür) oder beizutragen! Siehe Beitragen für Richtlinien.