import { IAnalyserNode, IAudioBuffer, IAudioBufferSourceNode, IAudioContext, IAudioContextOptions, IAudioDestinationNode, IAudioListener, IAudioNode, IAudioWorklet, IBiquadFilterNode, IConstantSourceNode, IConvolverNode, IDelayNode, IDynamicsCompressorNode, IGainNode, IIIRFilterNode, IMediaElementAudioSourceNode, IMediaStreamAudioDestinationNode, IMediaStreamAudioSourceNode, IMediaStreamTrackAudioSourceNode, IOscillatorNode, IPannerNode, IPeriodicWave, IStereoPannerNode, IWaveShaperNode, TAudioContextState, TContext, TEventHandler } from 'standardized-audio-context'; import { DeLorean } from 'vehicles'; import { AudioBufferMock } from './audio-buffer-mock'; import { AudioBufferSourceNodeMock } from './audio-buffer-source-node-mock'; import { BiquadFilterNodeMock } from './biquad-filter-node-mock'; import { DynamicsCompressorNodeMock } from './dynamics-compressor-node-mock'; import { EventTarget } from './event-target'; import { GainNodeMock } from './gain-node-mock'; import { MediaElementAudioSourceNodeMock } from './media-element-audio-source-node-mock'; import { MediaStreamAudioDestinationNodeMock } from './media-stream-audio-destination-node-mock'; import { MediaStreamAudioSourceNodeMock } from './media-stream-audio-source-node-mock'; import { OscillatorNodeMock } from './oscillator-node-mock'; import { PannerNodeMock } from './panner-node-mock'; import { registrar } from './registrar'; import { StereoPannerNodeMock } from './stereo-panner-node-mock'; export class AudioContextMock extends EventTarget implements IAudioContext { private _deLorean: DeLorean; private _onstatechange: null | TEventHandler; private _options: IAudioContextOptions; private _state: TAudioContextState; constructor(options: IAudioContextOptions = {}) { super(); this._deLorean = new DeLorean(); this._onstatechange = null; this._options = options; this._state = 'suspended'; registrar.setDeLorean(this, this._deLorean); } get audioWorklet(): IAudioWorklet { return {}; } get baseLatency(): number { return 512 / this.sampleRate; } get currentTime(): number { return this._deLorean.position; } get destination(): IAudioDestinationNode { return >{}; } get listener(): IAudioListener { return {}; } get onstatechange(): null | TEventHandler { return this._onstatechange; } set onstatechange(value) { this._onstatechange = typeof value === 'function' ? value : null; } get sampleRate(): number { return this._options.sampleRate === undefined ? 44100 : this._options.sampleRate; } get state(): TAudioContextState { return this._state; } public close(): Promise { this._state = 'closed'; return Promise.resolve(); } // @todo This is a lazy hack. public createAnalyser(): IAnalyserNode { const analyserNode = new GainNodeMock(this); (analyserNode).fftSize = 2048; return >(analyserNode); } public createBiquadFilter(): IBiquadFilterNode { return new BiquadFilterNodeMock(this); } public createBuffer(numberOfChannels: number, length: number, sampleRate: number): IAudioBuffer { return new AudioBufferMock({ length, numberOfChannels, sampleRate }); } public createBufferSource(): IAudioBufferSourceNode { return new AudioBufferSourceNodeMock(this); } public createChannelMerger(): IAudioNode { // @todo return >{}; } public createChannelSplitter(): IAudioNode { // @todo return >{}; } public createConstantSource(): IConstantSourceNode { // @todo return >{}; } public createConvolver(): IConvolverNode { // @todo return >{}; } public createDelay(): IDelayNode { // @todo return >{}; } public createDynamicsCompressor(): IDynamicsCompressorNode { return new DynamicsCompressorNodeMock(this); } public createGain(): IGainNode { return new GainNodeMock(this); } public createIIRFilter(): IIIRFilterNode { // @todo return >{}; } public createMediaElementSource(mediaElement: HTMLMediaElement): IMediaElementAudioSourceNode { return new MediaElementAudioSourceNodeMock(this, { mediaElement }); } public createMediaStreamDestination(): IMediaStreamAudioDestinationNode { return new MediaStreamAudioDestinationNodeMock(this); } public createMediaStreamSource(mediaStream: MediaStream): IMediaStreamAudioSourceNode { return new MediaStreamAudioSourceNodeMock(this, { mediaStream }); } public createMediaStreamTrackSource(): IMediaStreamTrackAudioSourceNode { // @todo return >{}; } public createOscillator(): IOscillatorNode { return new OscillatorNodeMock(this); } public createPanner(): IPannerNode { return new PannerNodeMock(this); } public createPeriodicWave(): IPeriodicWave { // @todo return {}; } public createStereoPanner(): IStereoPannerNode { return new StereoPannerNodeMock(this); } public createWaveShaper(): IWaveShaperNode { // @todo return >{}; } public decodeAudioData(): Promise { return Promise.resolve(new AudioBufferMock({ length: 10, sampleRate: this.sampleRate })); } public resume(): Promise { this._state = 'running'; return Promise.resolve(); } public suspend(): Promise { this._state = 'suspended'; return Promise.resolve(); } }