import AudioRecorder from "./audioRecorder";
import visualize from "./visualize";
import MlsGenInterface from "./mlsGen/mlsGenInterface";
/**
* Provides methods for calibrating the user's speakers
* @extends AudioRecorder
*/
class AudioCalibrator extends AudioRecorder {
/** @private */
#isCalibrating = false;
/** @private */
#sourceAudio;
/** @private */
#sourceAudioContext;
/** @private */
#sourceAudioAnalyser;
/** @private */
#sinkAudioContext;
/** @private */
#sinkAudioAnalyser;
/** @private */
#mlsGenInterface;
/**
* Creates an instance of AudioCalibrator
* Makes a call to the super constructor, and initializes MLSGenInterface
*/
constructor() {
super();
this.#mlsGenInterface = new MlsGenInterface();
}
/**
* Called when a call is received.
* Creates a local audio DOM element and attaches it to the page.
*/
createLocalAudio = (targetElement) => {
const localAudio = document.createElement("audio");
localAudio.setAttribute("id", "localAudio");
targetElement.appendChild(localAudio);
};
/**
* Creates an audio context and plays it for a few seconds.
* @private
* @returns {Promise} - Resolves when the audio is done playing.
*/
#playCalibrationAudio = () => {
// const buffer = new ArrayBuffer(this.#mlsData.length);
// const view = new Uint8Array(buffer);
// const duration = 2000;
// for (let i; i < this.#mlsData.length; i += 1) {
// view[i] = this.#mlsData[i];
// }
// this.#sourceAudioContext = new AudioContext();
// // TODO: Uncaught (in promise) DOMException: Unable to decode audio data
// // Possibly to do with the type of audio data being passed in.
// this.#sourceAudioContext.decodeAudioData(buffer).then((buf) => {
// // Create a source node from the buffer
// this.#sourceAudio = this.#sourceAudioContext.createBufferSource();
// this.#sourceAudio.buffer = buf;
// // Connect to the final output node (the speakers)
// this.#sourceAudio.connect(this.#sourceAudioContext.destination);
// // Play immediately
// this.#sourceAudio.start(0);
// });
// let's return a promise so we can await the end of each track
return new Promise((resolve) => {
setTimeout(resolve, duration * 2);
});
};
/**
* Getter for the isCalibrating property.
* @public
* @returns {Boolean} - True if the audio is being calibrated, false otherwise.
*/
getCalibrationStatus = () => this.#isCalibrating;
setSinkAudio = (stream) => {
this.#sinkAudioContext = new AudioContext();
this.#sinkAudioAnalyser = this.#sinkAudioContext.createAnalyser();
const source = this.#sinkAudioContext.createMediaStreamSource(stream);
source.connect(this.#sinkAudioAnalyser);
visualize(this.#sinkAudioAnalyser);
};
/**
* Method to start the calibration process.
* @public
* @param {MediaStream} stream - The stream of audio from the Listener.
*/
startCalibration = async (stream) => {
this.setSinkAudio(stream);
this.#mlsGenInterface.getMls();
let numRounds = 0;
while (!this.#isCalibrating && numRounds <= 2) {
// start recording
this.startRecording(stream);
// play calibration audio
// eslint-disable-next-line no-await-in-loop
await this.#playCalibrationAudio().then(() => {
// when done, stop recording
this.stopRecording();
});
numRounds += 1;
}
};
}
export default AudioCalibrator;