UNPKG

@simbi/standardized-audio-context

Version:

A cross-browser implementation of the AudioContext which aims to closely follow the standard.

69 lines 3.42 kB
import { deactivateAudioGraph } from '../helpers/deactivate-audio-graph'; import { testPromiseSupport } from '../helpers/test-promise-support'; const DEFAULT_OPTIONS = { numberOfChannels: 1 }; export const createMinimalOfflineAudioContextConstructor = (cacheTestResult, createInvalidStateError, createNativeOfflineAudioContext, minimalBaseAudioContextConstructor, startRendering) => { return class MinimalOfflineAudioContext extends minimalBaseAudioContextConstructor { constructor(options) { const { length, numberOfChannels, sampleRate } = { ...DEFAULT_OPTIONS, ...options }; const nativeOfflineAudioContext = createNativeOfflineAudioContext(numberOfChannels, length, sampleRate); // #21 Safari does not support promises and therefore would fire the statechange event before the promise can be resolved. if (!cacheTestResult(testPromiseSupport, () => testPromiseSupport(nativeOfflineAudioContext))) { nativeOfflineAudioContext.addEventListener('statechange', (() => { let i = 0; const delayStateChangeEvent = (event) => { if (this._state === 'running') { if (i > 0) { nativeOfflineAudioContext.removeEventListener('statechange', delayStateChangeEvent); event.stopImmediatePropagation(); this._waitForThePromiseToSettle(event); } else { i += 1; } } }; return delayStateChangeEvent; })()); } super(nativeOfflineAudioContext, numberOfChannels); this._length = length; this._nativeOfflineAudioContext = nativeOfflineAudioContext; this._state = null; } get length() { // Bug #17: Safari does not yet expose the length. if (this._nativeOfflineAudioContext.length === undefined) { return this._length; } return this._nativeOfflineAudioContext.length; } get state() { return this._state === null ? this._nativeOfflineAudioContext.state : this._state; } startRendering() { /* * Bug #9 & #59: It is theoretically possible that startRendering() will first render a partialOfflineAudioContext. Therefore * the state of the nativeOfflineAudioContext might no transition to running immediately. */ if (this._state === 'running') { return Promise.reject(createInvalidStateError()); } this._state = 'running'; return startRendering(this.destination, this._nativeOfflineAudioContext).finally(() => { this._state = null; deactivateAudioGraph(this); }); } _waitForThePromiseToSettle(event) { if (this._state === null) { this._nativeOfflineAudioContext.dispatchEvent(event); } else { setTimeout(() => this._waitForThePromiseToSettle(event)); } } }; }; //# sourceMappingURL=minimal-offline-audio-context-constructor.js.map