From c8392cb541e27535d0848757cff5bc7849cd10dd Mon Sep 17 00:00:00 2001 From: chrisguttandin Date: Wed, 28 Mar 2018 22:53:59 +0200 Subject: [PATCH] feat: implement buffer singulartiy --- src/audio-nodes/audio-buffer-source-node.ts | 38 ++++++++++++++-- .../create-native-audio-buffer-source-node.ts | 8 ++-- ...rce-node-start-method-consecutive-calls.ts | 17 ++++--- .../firefox/any/audio-context-constructor.js | 13 ++++++ .../any/offline-audio-context-constructor.js | 13 ++++++ .../safari/audio-context-constructor.js | 13 ++++++ .../offline-audio-context-constructor.js | 13 ++++++ .../audio-nodes/audio-buffer-source-node.js | 45 ++++++++++++++++++- 8 files changed, 143 insertions(+), 17 deletions(-) diff --git a/src/audio-nodes/audio-buffer-source-node.ts b/src/audio-nodes/audio-buffer-source-node.ts index 35c068bdd..848e2ae17 100644 --- a/src/audio-nodes/audio-buffer-source-node.ts +++ b/src/audio-nodes/audio-buffer-source-node.ts @@ -1,4 +1,5 @@ import { Injector } from '@angular/core'; +import { INVALID_STATE_ERROR_FACTORY_PROVIDER, InvalidStateErrorFactory } from '../factories/invalid-state-error'; import { AUDIO_NODE_RENDERER_STORE } from '../globals'; import { createNativeAudioBufferSourceNode } from '../helpers/create-native-audio-buffer-source-node'; import { getNativeContext } from '../helpers/get-native-context'; @@ -11,11 +12,13 @@ import { NoneAudioDestinationNode } from './none-audio-destination-node'; const injector = Injector.create({ providers: [ - AUDIO_PARAM_WRAPPER_PROVIDER + AUDIO_PARAM_WRAPPER_PROVIDER, + INVALID_STATE_ERROR_FACTORY_PROVIDER ] }); const audioParamWrapper = injector.get(AudioParamWrapper); +const invalidStateErrorFactory = injector.get(InvalidStateErrorFactory); const DEFAULT_OPTIONS: IAudioBufferSourceOptions = { buffer: null, @@ -31,6 +34,10 @@ const DEFAULT_OPTIONS: IAudioBufferSourceOptions = { export class AudioBufferSourceNode extends NoneAudioDestinationNode implements IAudioBufferSourceNode { + private _isBufferNullified: boolean; + + private _isBufferSet: boolean; + constructor (context: IMinimalBaseAudioContext, options: Partial = DEFAULT_OPTIONS) { const nativeContext = getNativeContext(context); const mergedOptions = { ...DEFAULT_OPTIONS, ...options }; @@ -46,15 +53,40 @@ export class AudioBufferSourceNode extends NoneAudioDestinationNode(AudioScheduledSourceNodeStartMethodConsecutiveCallsWrapper); + .get(AudioBufferSourceNodeStartMethodConsecutiveCallsWrapper); const startMethodNegativeParametersSupportTester = injector.get(AudioScheduledSourceNodeStartMethodNegativeParametersSupportTester); const startMethodNegativeParametersWrapper = injector.get(AudioScheduledSourceNodeStartMethodNegativeParametersWrapper); const stopMethodConsecutiveCallsSupportTester = injector.get(AudioScheduledSourceNodeStopMethodConsecutiveCallsSupportTester); diff --git a/src/wrappers/audio-buffer-source-node-start-method-consecutive-calls.ts b/src/wrappers/audio-buffer-source-node-start-method-consecutive-calls.ts index 308dac332..3a26502e5 100644 --- a/src/wrappers/audio-buffer-source-node-start-method-consecutive-calls.ts +++ b/src/wrappers/audio-buffer-source-node-start-method-consecutive-calls.ts @@ -1,15 +1,14 @@ import { Injectable } from '@angular/core'; import { InvalidStateErrorFactory } from '../factories/invalid-state-error'; -import { INativeConstantSourceNode } from '../interfaces'; -import { TNativeAudioBufferSourceNode, TNativeOscillatorNode } from '../types'; +import { TNativeAudioBufferSourceNode } from '../types'; @Injectable() -export class AudioScheduledSourceNodeStartMethodConsecutiveCallsWrapper { +export class AudioBufferSourceNodeStartMethodConsecutiveCallsWrapper { constructor (private _invalidStateErrorFactory: InvalidStateErrorFactory) { } - public wrap (audioScheduledSourceNode: TNativeAudioBufferSourceNode | INativeConstantSourceNode | TNativeOscillatorNode) { - audioScheduledSourceNode.start = ((start) => { + public wrap (audioBufferSourceNode: TNativeAudioBufferSourceNode) { + audioBufferSourceNode.start = ((start) => { let isScheduled = false; return (when = 0, offset = 0, duration?: number) => { @@ -17,16 +16,16 @@ export class AudioScheduledSourceNodeStartMethodConsecutiveCallsWrapper { throw this._invalidStateErrorFactory.create(); } - start.call(audioScheduledSourceNode, when, offset, duration); + start.call(audioBufferSourceNode, when, offset, duration); isScheduled = true; }; - })(audioScheduledSourceNode.start); + })(audioBufferSourceNode.start); } } -export const AUDIO_SCHEDULED_SOURCE_NODE_START_METHOD_CONSECUTIVE_CALLS_WRAPPER_PROVIDER = { +export const AUDIO_BUFFER_SOURCE_NODE_START_METHOD_CONSECUTIVE_CALLS_WRAPPER_PROVIDER = { deps: [ InvalidStateErrorFactory ], - provide: AudioScheduledSourceNodeStartMethodConsecutiveCallsWrapper + provide: AudioBufferSourceNodeStartMethodConsecutiveCallsWrapper }; diff --git a/test/expectation/firefox/any/audio-context-constructor.js b/test/expectation/firefox/any/audio-context-constructor.js index d45da0a8d..d7685d5b3 100644 --- a/test/expectation/firefox/any/audio-context-constructor.js +++ b/test/expectation/firefox/any/audio-context-constructor.js @@ -124,6 +124,19 @@ describe('audioContextConstructor', () => { describe('createBufferSource()', () => { + describe('buffer', () => { + + // bug #72 + + it('should allow to assign the buffer multiple times', () => { + const bufferSourceNode = audioContext.createBufferSource(); + + bufferSourceNode.buffer = audioContext.createBuffer(2, 100, 44100); + bufferSourceNode.buffer = audioContext.createBuffer(2, 100, 44100); + }); + + }); + describe('playbackRate', () => { // bug #45 diff --git a/test/expectation/firefox/any/offline-audio-context-constructor.js b/test/expectation/firefox/any/offline-audio-context-constructor.js index 45a02ef11..510ec761b 100644 --- a/test/expectation/firefox/any/offline-audio-context-constructor.js +++ b/test/expectation/firefox/any/offline-audio-context-constructor.js @@ -55,6 +55,19 @@ describe('offlineAudioContextConstructor', () => { describe('createBufferSource()', () => { + describe('buffer', () => { + + // bug #72 + + it('should allow to assign the buffer multiple times', () => { + const bufferSourceNode = offlineAudioContext.createBufferSource(); + + bufferSourceNode.buffer = offlineAudioContext.createBuffer(2, 100, 44100); + bufferSourceNode.buffer = offlineAudioContext.createBuffer(2, 100, 44100); + }); + + }); + describe('start()', () => { // bug #44 diff --git a/test/expectation/safari/audio-context-constructor.js b/test/expectation/safari/audio-context-constructor.js index 23b7f6f05..c74542f46 100644 --- a/test/expectation/safari/audio-context-constructor.js +++ b/test/expectation/safari/audio-context-constructor.js @@ -208,6 +208,19 @@ describe('audioContextConstructor', () => { audioBufferSourceNode.stop(); }); + describe('buffer', () => { + + // bug #72 + + it('should allow to assign the buffer multiple times', () => { + const bufferSourceNode = audioContext.createBufferSource(); + + bufferSourceNode.buffer = audioContext.createBuffer(2, 100, 44100); + bufferSourceNode.buffer = audioContext.createBuffer(2, 100, 44100); + }); + + }); + describe('playbackRate', () => { // bug #45 diff --git a/test/expectation/safari/offline-audio-context-constructor.js b/test/expectation/safari/offline-audio-context-constructor.js index 18faa3117..4cc515948 100644 --- a/test/expectation/safari/offline-audio-context-constructor.js +++ b/test/expectation/safari/offline-audio-context-constructor.js @@ -262,6 +262,19 @@ describe('offlineAudioContextConstructor', () => { offlineAudioContext.startRendering(); }); + describe('buffer', () => { + + // bug #72 + + it('should allow to assign the buffer multiple times', () => { + const bufferSourceNode = offlineAudioContext.createBufferSource(); + + bufferSourceNode.buffer = offlineAudioContext.createBuffer(2, 100, 44100); + bufferSourceNode.buffer = offlineAudioContext.createBuffer(2, 100, 44100); + }); + + }); + describe('start()', () => { // bug #44 diff --git a/test/unit/audio-nodes/audio-buffer-source-node.js b/test/unit/audio-nodes/audio-buffer-source-node.js index 95c42de15..1f4bf91dc 100644 --- a/test/unit/audio-nodes/audio-buffer-source-node.js +++ b/test/unit/audio-nodes/audio-buffer-source-node.js @@ -287,7 +287,50 @@ describe('AudioBufferSourceNode', () => { describe('buffer', () => { - // @todo + let audioBufferSourceNode; + + beforeEach(() => { + audioBufferSourceNode = createAudioBufferSourceNode(context); + }); + + describe('without a previously assigned AudioBuffer', () => { + + it('should be assignable to an AudioBuffer', () => { + const audioBuffer = new AudioBuffer({ length: 5, sampleRate: context.sampleRate }); + + audioBufferSourceNode.buffer = audioBuffer; + + expect(audioBufferSourceNode.buffer).to.equal(audioBuffer); + }); + + }); + + describe('with a previously assigned AudioBuffer', () => { + + beforeEach(() => { + audioBufferSourceNode.buffer = new AudioBuffer({ length: 5, sampleRate: context.sampleRate }); + }); + + it('should throw an InvalidStateError', (done) => { + const audioBuffer = new AudioBuffer({ length: 5, sampleRate: context.sampleRate }); + + try { + audioBufferSourceNode.buffer = audioBuffer; + } catch (err) { + expect(err.code).to.equal(11); + expect(err.name).to.equal('InvalidStateError'); + + done(); + } + }); + + it('should be assignable to null', () => { + audioBufferSourceNode.buffer = null; + + expect(audioBufferSourceNode.buffer).to.be.null; + }); + + }); });