| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import logger from '../logger';
- import { RecordingAdapter } from './RecordingAdapter';
-
- /**
- * Base class for {@code AudioContext}-based recording adapters.
- */
- export class AbstractAudioContextAdapter extends RecordingAdapter {
- /**
- * The {@code AudioContext} instance.
- */
- _audioContext = null;
-
- /**
- * The {@code ScriptProcessorNode} instance.
- */
- _audioProcessingNode = null;
-
- /**
- * The {@code MediaStreamAudioSourceNode} instance.
- */
- _audioSource = null;
-
- /**
- * The {@code MediaStream} instance, representing the current audio device.
- */
- _stream = null;
-
- /**
- * Sample rate.
- */
- _sampleRate = 44100;
-
- /**
- * Constructor.
- */
- constructor() {
- super();
-
- // sampleRate is browser and OS dependent.
- // Setting sampleRate explicitly is in the specs but not implemented
- // by browsers.
- // See: https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/
- // AudioContext#Browser_compatibility
- // And https://bugs.chromium.org/p/chromium/issues/detail?id=432248
-
- this._audioContext = new AudioContext();
- this._sampleRate = this._audioContext.sampleRate;
- logger.log(`Current sampleRate ${this._sampleRate}.`);
- }
-
- /**
- * Sets up the audio graph in the AudioContext.
- *
- * @protected
- * @param {string} micDeviceId - The current microphone device ID.
- * @param {Function} callback - Callback function to
- * handle AudioProcessingEvents.
- * @returns {Promise}
- */
- _initializeAudioContext(micDeviceId, callback) {
- if (typeof callback !== 'function') {
- return Promise.reject('a callback function is required.');
- }
-
- return this._getAudioStream(micDeviceId)
- .then(stream => {
- this._stream = stream;
- this._audioSource
- = this._audioContext.createMediaStreamSource(stream);
- this._audioProcessingNode
- = this._audioContext.createScriptProcessor(4096, 1, 1);
- this._audioProcessingNode.onaudioprocess = callback;
- logger.debug('AudioContext is set up.');
- })
- .catch(err => {
- logger.error(`Error calling getUserMedia(): ${err}`);
-
- return Promise.reject(err);
- });
- }
-
- /**
- * Connects the nodes in the {@code AudioContext} to start the flow of
- * audio data.
- *
- * @protected
- * @returns {void}
- */
- _connectAudioGraph() {
- this._audioSource.connect(this._audioProcessingNode);
- this._audioProcessingNode.connect(this._audioContext.destination);
- }
-
- /**
- * Disconnects the nodes in the {@code AudioContext}.
- *
- * @protected
- * @returns {void}
- */
- _disconnectAudioGraph() {
- this._audioProcessingNode.onaudioprocess = undefined;
- this._audioProcessingNode.disconnect();
- this._audioSource.disconnect();
- }
-
- /**
- * Replaces the current microphone MediaStream.
- *
- * @protected
- * @param {string} micDeviceId - New microphone ID.
- * @returns {Promise}
- */
- _replaceMic(micDeviceId) {
- if (this._audioContext && this._audioProcessingNode) {
- return this._getAudioStream(micDeviceId).then(newStream => {
- const newSource = this._audioContext
- .createMediaStreamSource(newStream);
-
- this._audioSource.disconnect();
- newSource.connect(this._audioProcessingNode);
- this._stream = newStream;
- this._audioSource = newSource;
- });
- }
-
- return Promise.resolve();
- }
- }
|