const DEBUG = false;
/**
* AudioEngine class.
* Creates an WebAudio audio context and manages a Switchboard AudioWorkletNode.
*/
class AudioEngine {
/**
* AudioEngine constructor.
*/
constructor() {
if (DEBUG) console.log("[SB] [AudioEngine] constructor");
this._audioContext = new AudioContext();
this._workletNode = null;
}
/**
* Initializes the audio engine with a worklet node.
* @param {AudioWorkletNode} workletNode The audio worklet node that does the audio processing.
*/
initialize(workletNode) {
if (DEBUG) console.log("[SB] [AudioEngine] initialize", workletNode);
if (workletNode.numberOfOutputs > 0) {
workletNode.connect(this._audioContext.destination);
}
this._audioContext.suspend();
this._workletNode = workletNode;
}
/**
* Loads and decodes audio from a URL.
* @param {String} url The URL of the audio to load.
* @returns {Promise} A promise for the loading and decoding process that provides an audio buffer.
*/
loadAudio(url) {
if (DEBUG) console.log("[SB] [AudioEngine] loadAudio", url);
let audioEngine = this;
return new Promise((resolve, reject) => {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
audioEngine.getAudioContext().decodeAudioData(
request.response,
function(buffer) {
resolve(buffer);
},
function() {
console.error("[SB] [AudioEngine] Could not load " + url);
reject();
}
);
}
request.send();
})
}
/**
* Gets the user audio stream
* @param {Object} constraints Constraints for the user media.
* @returns The user media.
*/
async getUserAudioStream(constraints) {
if (DEBUG) console.log("[SB] [AudioEngine] getUserAudioStream", constraints);
const defaultContraints = {
audio: {
echoCancellation: false,
autoGainControl: false,
noiseSuppression: false
}
}
return await navigator.mediaDevices.getUserMedia(constraints ? constraints : defaultContraints);
}
/**
* Gets the WebAudio audio context.
* @returns {AudioContext} The WebAudio audio context.
*/
getAudioContext() {
return this._audioContext;
}
/**
* Gets the AudioWorkletNode instance.
* @returns {AudioWorkletNode} The AudioWorkletNode instance.
*/
getAudioWorkletNode() {
return this._workletNode;
}
/**
* Starts the audio engine. Resumes the audio context.
*/
start() {
this._audioContext.resume();
}
/**
* Stops the audio engine. Suspends the audio context.
*/
stop() {
this._audioContext.suspend();
}
/**
* Posts a message to the worklet node's port.
* @param {Object} message The message to send to the worklet node.
*/
postMessage(message) {
this._workletNode.port.postMessage(message)
}
}
export default AudioEngine;