From 9a3ded2a851a21190a8038dd3acad7f50add697e Mon Sep 17 00:00:00 2001 From: Abhijay Jain Date: Sat, 14 Jan 2023 23:57:36 +0530 Subject: [PATCH 01/11] (Docs): Updated various fields in the p5.AudioIn reference Signed-off-by: Abhijay Jain --- src/audioin.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/audioin.js b/src/audioin.js index 07c63630..0f09020d 100644 --- a/src/audioin.js +++ b/src/audioin.js @@ -55,7 +55,10 @@ class AudioIn { * @property {GainNode} input */ this.input = p5sound.audiocontext.createGain(); + /** + * Get audio from an input, i.e. your computer's microphone. + * * @property {GainNode} output */ this.output = p5sound.audiocontext.createGain(); @@ -64,10 +67,12 @@ class AudioIn { * @property {MediaStream|null} stream */ this.stream = null; + /** * @property {MediaStreamAudioSourceNode|null} mediaStream */ this.mediaStream = null; + /** * @property {Number|null} currentSource */ From c2142f035eade193647e70bb649fe2d196c4930e Mon Sep 17 00:00:00 2001 From: Abhijay Jain Date: Tue, 17 Jan 2023 23:54:20 +0530 Subject: [PATCH 02/11] (Docs): added more info about certain fields Signed-off-by: Abhijay Jain --- src/audioin.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/audioin.js b/src/audioin.js index 0f09020d..11e19bbb 100644 --- a/src/audioin.js +++ b/src/audioin.js @@ -50,30 +50,45 @@ p5sound.inputSources = []; */ class AudioIn { constructor(errorCallback) { - // set up audio input /** + * set up audio input + * * @property {GainNode} input */ this.input = p5sound.audiocontext.createGain(); /** - * Get audio from an input, i.e. your computer's microphone. - * + * send audio as an output, i.e. your computer's speaker. + * * @property {GainNode} output */ this.output = p5sound.audiocontext.createGain(); /** + * used to store the MediaStream object that is returned from the getUserMedia() API, + * which allows access to the user's microphone. The stream is used to create a MediaStreamAudioSourceNode, + * which is used as the audio source for the input and output gain nodes. + * The stream is also used to check if the browser supports the MediaStreamTrack and mediaDevices API, + * and if not, an errorCallback function is called or an alert is displayed. + * * @property {MediaStream|null} stream */ this.stream = null; /** + * used to access the "audio input" from the user's microphone. + * It creates a MediaStream object that can be used to start and stop the mic and measure its volume using the getLevel() method or by connecting it to an FFT object. + * MediaStream object can also be use to check if the browser supports MediaStreamTrack and mediaDevices and to add the AudioIn object to the soundArray for disposal on close. + * * @property {MediaStreamAudioSourceNode|null} mediaStream */ this.mediaStream = null; - + /** + * use to store the "current source of audio input", such as the user's microphone. + * initially set to "null" and can be updated as the user selects different audio sources. + * also used in conjunction with the "input" and "mediaStream" properties to control audio input. + * * @property {Number|null} currentSource */ this.currentSource = null; From 2c8d2344a1f4fdc47e7c67a9f98a4f9d50a29237 Mon Sep 17 00:00:00 2001 From: Abhijay Jain Date: Tue, 17 Jan 2023 23:59:07 +0530 Subject: [PATCH 03/11] (Docs): Updated various fields in the p5.MonoSynth reference Signed-off-by: Abhijay Jain --- src/monosynth.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/monosynth.js b/src/monosynth.js index d0f2750f..6e5c1f4f 100644 --- a/src/monosynth.js +++ b/src/monosynth.js @@ -77,6 +77,9 @@ class MonoSynth extends AudioVoice { * @for p5.MonoSynth */ /** + * used to set the decay time of the envelope (ADSR) of the MonoSynth class. + * It is a getter and setter that can be used to retrieve or change the decay time. + * It is used in conjunction with the attack, sustain, and release fields/functions to set the full envelope of the synthesizer. * @property {Number} decay * @for p5.MonoSynth */ From 23a277e72ee5b2fb3cfc9abbc087313ea20ed0a6 Mon Sep 17 00:00:00 2001 From: Abhijay Jain Date: Wed, 18 Jan 2023 00:06:06 +0530 Subject: [PATCH 04/11] (Docs): added more info about certain fields Signed-off-by: Abhijay Jain --- src/monosynth.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/monosynth.js b/src/monosynth.js index 6e5c1f4f..00512799 100644 --- a/src/monosynth.js +++ b/src/monosynth.js @@ -77,17 +77,21 @@ class MonoSynth extends AudioVoice { * @for p5.MonoSynth */ /** - * used to set the decay time of the envelope (ADSR) of the MonoSynth class. - * It is a getter and setter that can be used to retrieve or change the decay time. - * It is used in conjunction with the attack, sustain, and release fields/functions to set the full envelope of the synthesizer. + * allow user to set the decay time of the envelope (ADSR) of the MonoSynth class. + * It is a getter and setter that can be used to retrieve or change the decay time. + * used in conjunction with the attack, sustain, and release fields/functions to set the full envelope of the synthesizer. * @property {Number} decay * @for p5.MonoSynth */ /** + * allows the user to retrieve and adjust the sustain level of the envelope, + * which controls the level at which the sound is sustained during the sustain phase of the envelope. + * The default sustain level is set to 0.15. * @property {Number} sustain * @for p5.MonoSynth */ /** + * allows the user to access and change the release time of the envelope. * @property {Number} release * @for p5.MonoSynth */ From a4e656b14658c288149171ddb6968bd253fd7e52 Mon Sep 17 00:00:00 2001 From: Abhijay Jain Date: Sun, 22 Jan 2023 22:36:38 +0530 Subject: [PATCH 05/11] resolved minor typos and text capitalization Signed-off-by: Abhijay Jain --- src/monosynth.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/monosynth.js b/src/monosynth.js index 00512799..a2e7b8d6 100644 --- a/src/monosynth.js +++ b/src/monosynth.js @@ -77,21 +77,21 @@ class MonoSynth extends AudioVoice { * @for p5.MonoSynth */ /** - * allow user to set the decay time of the envelope (ADSR) of the MonoSynth class. + * Allows user to set the decay time of the envelope (ADSR) of the MonoSynth class. * It is a getter and setter that can be used to retrieve or change the decay time. - * used in conjunction with the attack, sustain, and release fields/functions to set the full envelope of the synthesizer. + * Used in conjunction with the attack, sustain, and release fields/functions to set the full envelope of the synthesizer. * @property {Number} decay * @for p5.MonoSynth */ /** - * allows the user to retrieve and adjust the sustain level of the envelope, + * Allows the user to retrieve and adjust the sustain level of the envelope, * which controls the level at which the sound is sustained during the sustain phase of the envelope. * The default sustain level is set to 0.15. * @property {Number} sustain * @for p5.MonoSynth */ /** - * allows the user to access and change the release time of the envelope. + * Allows the user to access and change the release time of the envelope. * @property {Number} release * @for p5.MonoSynth */ From 04a3c794dff2adb8c1d17e16386abf49b0a6f6e5 Mon Sep 17 00:00:00 2001 From: Abhijay Jain Date: Sun, 22 Jan 2023 22:41:59 +0530 Subject: [PATCH 06/11] resolved minor typos and text capitalization Signed-off-by: Abhijay Jain --- src/audioin.js | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/audioin.js b/src/audioin.js index 11e19bbb..7200f5fc 100644 --- a/src/audioin.js +++ b/src/audioin.js @@ -51,59 +51,46 @@ p5sound.inputSources = []; class AudioIn { constructor(errorCallback) { /** - * set up audio input - * + * Set up audio input * @property {GainNode} input */ this.input = p5sound.audiocontext.createGain(); - /** - * send audio as an output, i.e. your computer's speaker. - * + * Send audio as an output, i.e. your computer's speaker. * @property {GainNode} output */ this.output = p5sound.audiocontext.createGain(); - /** - * used to store the MediaStream object that is returned from the getUserMedia() API, + * Used to store the MediaStream object that is returned from the getUserMedia() API, * which allows access to the user's microphone. The stream is used to create a MediaStreamAudioSourceNode, * which is used as the audio source for the input and output gain nodes. * The stream is also used to check if the browser supports the MediaStreamTrack and mediaDevices API, * and if not, an errorCallback function is called or an alert is displayed. - * * @property {MediaStream|null} stream */ this.stream = null; - /** - * used to access the "audio input" from the user's microphone. + * Used to access the "audio input" from the user's microphone. * It creates a MediaStream object that can be used to start and stop the mic and measure its volume using the getLevel() method or by connecting it to an FFT object. * MediaStream object can also be use to check if the browser supports MediaStreamTrack and mediaDevices and to add the AudioIn object to the soundArray for disposal on close. - * * @property {MediaStreamAudioSourceNode|null} mediaStream */ this.mediaStream = null; - /** - * use to store the "current source of audio input", such as the user's microphone. - * initially set to "null" and can be updated as the user selects different audio sources. - * also used in conjunction with the "input" and "mediaStream" properties to control audio input. - * + * Used to store the "current source of audio input", such as the user's microphone. + * Initially set to "null" and can be updated as the user selects different audio sources. + * Also used in conjunction with the "input" and "mediaStream" properties to control audio input. * @property {Number|null} currentSource */ this.currentSource = null; - /** * Client must allow browser to access their microphone / audioin source. * Default: false. Will become true when the client enables access. - * * @property {Boolean} enabled */ this.enabled = false; - /** * Input amplitude, connect to it by default but not to master out - * * @property {p5.Amplitude} amplitude */ this.amplitude = new Amplitude(); From 726cbdc6ba8b8f6d63deb6b0e66aa806966f993d Mon Sep 17 00:00:00 2001 From: KevinGrajeda Date: Sun, 22 Jan 2023 19:14:34 -0600 Subject: [PATCH 07/11] update panner.js to extend effect.js --- src/oscillator.js | 17 ++++++++++------- src/panner.js | 47 +++++++++++++++++++++++++++++------------------ src/soundfile.js | 13 ++++++++----- 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/oscillator.js b/src/oscillator.js index 9bd17a40..cfb1e3e5 100644 --- a/src/oscillator.js +++ b/src/oscillator.js @@ -133,10 +133,14 @@ class Oscillator { this.oscillator.connect(this.output); // stereo panning - this.panPosition = 0.0; this.connection = p5sound.input; // connect to p5sound by default - this.panner = new Panner(this.output, this.connection, 1); + if (typeof p5sound.audiocontext.createStereoPanner !== 'undefined') { + this.panner = new Panner(); + this.output.connect(this.panner); + } else { + this.panner = new Panner(this.output, this.connection, 1); + } //array of math operation signal chaining this.mathOps = [this.output]; @@ -415,21 +419,20 @@ class Oscillator { * seconds from now */ pan(pval, tFromNow) { - this.panPosition = pval; this.panner.pan(pval, tFromNow); } /** - * Returns the current value of panPosition , between Left (-1) and Right (1) + * Returns the current value of pan position , between Left (-1) and Right (1) * * @method getPan * @for p5.Oscillator * - * @returns {number} panPosition of oscillator , between Left (-1) and Right (1) + * @returns {number} pan position of oscillator , between Left (-1) and Right (1) */ getPan() { - return this.panPosition; + return this.panner.getPan(); } // get rid of the oscillator @@ -442,7 +445,7 @@ class Oscillator { var now = p5sound.audiocontext.currentTime; this.stop(now); this.disconnect(); - this.panner = null; + this.panner.dispose(); this.oscillator = null; } // if it is a Pulse diff --git a/src/panner.js b/src/panner.js index e946f788..f54e4ee3 100644 --- a/src/panner.js +++ b/src/panner.js @@ -1,38 +1,49 @@ +import Effect from './effect.js'; + import p5sound from './main'; var ac = p5sound.audiocontext; var panner; // Stereo panner // if there is a stereo panner node use it if (typeof ac.createStereoPanner !== 'undefined') { - class Panner { - constructor(input, output) { - this.stereoPanner = this.input = ac.createStereoPanner(); - input.connect(this.stereoPanner); - this.stereoPanner.connect(output); + class Panner extends Effect { + constructor() { + super(); + this.stereoPanner = this.ac.createStereoPanner(); + + this.input.connect(this.stereoPanner); + this.stereoPanner.connect(this.wet); } pan(val, tFromNow) { - var time = tFromNow || 0; - var t = ac.currentTime + time; - - this.stereoPanner.pan.linearRampToValueAtTime(val, t); + if (typeof val === 'number') { + let time = tFromNow || 0; + this.stereoPanner.pan.linearRampToValueAtTime( + val, + this.ac.currentTime + 0.02 + time + ); + } else if (typeof val !== 'undefined') { + val.connect(this.stereoPanner.pan); + } } - //not implemented because stereopanner - //node does not require this and will automatically - //convert single channel or multichannel to stereo. - //tested with single and stereo, not with (>2) multichannel - inputChannels() {} - - connect(obj) { - this.stereoPanner.connect(obj); + getPan() { + return this.stereoPanner.pan.value; } - disconnect() { + dispose() { + super.dispose(); if (this.stereoPanner) { this.stereoPanner.disconnect(); + delete this.stereoPanner; } } + + //not implemented because stereopanner + //node does not require this and will automatically + //convert single channel or multichannel to stereo. + //tested with single and stereo, not with (>2) multichannel + inputChannels() {} } panner = Panner; diff --git a/src/soundfile.js b/src/soundfile.js index 11e2517c..602c5471 100644 --- a/src/soundfile.js +++ b/src/soundfile.js @@ -182,8 +182,12 @@ class SoundFile { this.startMillis = null; // stereo panning - this.panPosition = 0.0; - this.panner = new Panner(this.output, p5sound.input, 2); + if (typeof p5sound.audiocontext.createStereoPanner !== 'undefined') { + this.panner = new Panner(); + this.output.connect(this.panner); + } else { + this.panner = new Panner(this.output, p5sound.input, 2); + } // it is possible to instantiate a soundfile with no path if (this.url || this.file) { @@ -795,7 +799,6 @@ class SoundFile { * */ pan(pval, tFromNow) { - this.panPosition = pval; this.panner.pan(pval, tFromNow); } @@ -809,7 +812,7 @@ class SoundFile { * 0.0 is center and default. */ getPan() { - return this.panPosition; + return this.panner.getPan(); } /** @@ -1264,7 +1267,7 @@ class SoundFile { this.output = null; } if (this.panner) { - this.panner.disconnect(); + this.panner.dispose(); this.panner = null; } } From 1c303fb62aa910e0e13bd16dbcdafcbf83cf7a04 Mon Sep 17 00:00:00 2001 From: KevinGrajeda Date: Sun, 22 Jan 2023 20:07:17 -0600 Subject: [PATCH 08/11] add Panner.getPan to safari fallback --- src/panner.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/panner.js b/src/panner.js index f54e4ee3..cc82f9d4 100644 --- a/src/panner.js +++ b/src/panner.js @@ -56,6 +56,7 @@ if (typeof ac.createStereoPanner !== 'undefined') { this.input = ac.createGain(); input.connect(this.input); + this.panValue = 0; this.left = ac.createGain(); this.right = ac.createGain(); this.left.channelInterpretation = 'discrete'; @@ -81,6 +82,7 @@ if (typeof ac.createStereoPanner !== 'undefined') { // -1 is left, +1 is right pan(val, tFromNow) { + this.panValue = val; var time = tFromNow || 0; var t = ac.currentTime + time; var v = (val + 1) / 2; @@ -90,6 +92,10 @@ if (typeof ac.createStereoPanner !== 'undefined') { this.right.gain.linearRampToValueAtTime(rightVal, t); } + getPan() { + return this.panValue; + } + inputChannels(numChannels) { if (numChannels === 1) { this.input.disconnect(); From e1a9d07be3d7a1c598821546b70b2f981e8ac2d0 Mon Sep 17 00:00:00 2001 From: KevinGrajeda Date: Sun, 22 Jan 2023 23:05:28 -0600 Subject: [PATCH 09/11] add docs and tests to panner --- src/effect.js | 1 + src/panner.js | 36 ++++++++++++++++++++++++++++++++++++ test/tests/p5.Oscillator.js | 9 ++------- test/tests/p5.Panner.js | 24 +++++++++++++++--------- test/tests/p5.SoundFile.js | 8 ++++---- 5 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/effect.js b/src/effect.js index fee75547..fd17e01c 100644 --- a/src/effect.js +++ b/src/effect.js @@ -13,6 +13,7 @@ import CrossFade from 'Tone/component/CrossFade.js'; * p5.Filter, * p5.Reverb, * p5.EQ, + * p5.Panner. * p5.Panner3D. * * @class p5.Effect diff --git a/src/panner.js b/src/panner.js index cc82f9d4..7a3ec20d 100644 --- a/src/panner.js +++ b/src/panner.js @@ -6,6 +6,19 @@ var panner; // Stereo panner // if there is a stereo panner node use it if (typeof ac.createStereoPanner !== 'undefined') { + /** + * The Panner class allows you to control the stereo + * panning of a sound source. It uses the [StereoPannerNode](https://developer.mozilla.org/en-US/docs/Web/API/StereoPannerNode), + * which allows you to adjust the balance between the left and right channels of a sound source. + * + * This class extends p5.Effect. + * Methods amp(), chain(), + * drywet(), connect(), and + * disconnect() are available. + * + * @class p5.Panner + * @extends p5.Effect + */ class Panner extends Effect { constructor() { super(); @@ -15,6 +28,16 @@ if (typeof ac.createStereoPanner !== 'undefined') { this.stereoPanner.connect(this.wet); } + /** + * Set the stereo pan position, a value of -1 means the sound will be fully panned + * to the left, a value of 0 means the sound will be centered, and a value of 1 means + * the sound will be fully panned to the right. + * @method pan + * @for p5.Panner + * @param {Number} value A value between -1 and 1 that sets the pan position. + * + * @param {Number} [time] time in seconds that it will take for the panning to change to the specified value. + */ pan(val, tFromNow) { if (typeof val === 'number') { let time = tFromNow || 0; @@ -27,10 +50,23 @@ if (typeof ac.createStereoPanner !== 'undefined') { } } + /** + * Return the current panning value. + * + * @method getPan + * @for p5.Panner + * @return {Number} current panning value, number between -1 (left) and 1 (right). + */ getPan() { return this.stereoPanner.pan.value; } + /** + * Get rid of the Panner and free up its resources / memory. + * + * @method dispose + * @for p5.Panner + */ dispose() { super.dispose(); if (this.stereoPanner) { diff --git a/test/tests/p5.Oscillator.js b/test/tests/p5.Oscillator.js index 045d8c0b..92d9440b 100644 --- a/test/tests/p5.Oscillator.js +++ b/test/tests/p5.Oscillator.js @@ -216,11 +216,8 @@ describe('p5.Oscillator', function () { it('can be panned without any delay', function (done) { let osc = new p5.Oscillator(); let panner = osc.panner; - expect(osc.panPosition).to.equal(0); //default value expect(osc.getPan()).to.equal(0); osc.pan(-0.3); - expect(osc.panPosition).to.equal(-0.3); - expect(osc.getPan()).to.equal(-0.3); if (typeof p5.soundOut.audiocontext.createStereoPanner !== 'undefined') { setTimeout(() => { expect(panner.stereoPanner.pan.value).to.be.approximately(-0.3, 0.01); @@ -238,8 +235,6 @@ describe('p5.Oscillator', function () { let osc = new p5.Oscillator(); osc.pan(0.7, 0.1); let panner = osc.panner; - expect(osc.panPosition).to.equal(0.7); - expect(osc.getPan()).to.equal(0.7); if (typeof p5.soundOut.audiocontext.createStereoPanner !== 'undefined') { setTimeout(() => { expect(panner.stereoPanner.pan.value).to.not.be.approximately( @@ -252,7 +247,7 @@ describe('p5.Oscillator', function () { 0.01 ); done(); - }, 50); + }, 60); }, 50); } else { setTimeout(() => { @@ -268,7 +263,7 @@ describe('p5.Oscillator', function () { expect(panner.left.gain.value).to.be.approximately(0.972, 0.001); expect(panner.right.gain.value).to.be.approximately(0.233, 0.001); done(); - }, 100); + }, 60); }, 50); } }); diff --git a/test/tests/p5.Panner.js b/test/tests/p5.Panner.js index 8c16e0a4..9b223bd5 100644 --- a/test/tests/p5.Panner.js +++ b/test/tests/p5.Panner.js @@ -1,4 +1,4 @@ -// const expect = chai.expect; +const expect = chai.expect; describe('p5.Panner', function () { let ac, output, input; @@ -8,22 +8,28 @@ describe('p5.Panner', function () { input = ac.createGain(); }); it('can be created', function () { - new p5.Panner(input, output); + new p5.Panner(); }); it('can be connected and disconnected', function () { - let panner = new p5.Panner(input, output); + let panner = new p5.Panner(); panner.connect(input); panner.disconnect(); }); - it('can be panned without a delay', function () { - let panner = new p5.Panner(input, output); + it('can be panned without a delay', function (done) { + let panner = new p5.Panner(); panner.pan(0.4); - panner.pan(0.3, 0); - //TODO: to check the value of left gain/ right gain (or) the stereoPanner.pan + setTimeout(() => { + expect(panner.getPan()).to.be.approximately(0.4, 0.01); + done(); + }, 25); }); - it('can be panned with a delay', function () { + it('can be panned with a delay', function (done) { let panner = new p5.Panner(input, output); - panner.pan(0.4, 10); + panner.pan(-0.7, 0.1); + setTimeout(() => { + expect(panner.getPan()).to.be.approximately(-0.7, 0.01); + done(); + }, 125); }); it('can take inputChannels as 1 or 2', function () { let panner = new p5.Panner(input, output); diff --git a/test/tests/p5.SoundFile.js b/test/tests/p5.SoundFile.js index da745162..ba872b9a 100644 --- a/test/tests/p5.SoundFile.js +++ b/test/tests/p5.SoundFile.js @@ -30,7 +30,7 @@ describe('p5.SoundFile', function () { expect(sf.pauseTime).to.equal(0); expect(sf.mode).to.equal('sustain'); expect(sf.startMillis).to.be.null; - expect(sf.panPosition).to.equal(0); + expect(sf.getPan()).to.equal(0); expect(sf.panner).to.have.property('stereoPanner'); expect(p5.soundOut.soundArray).to.include(sf); @@ -507,13 +507,13 @@ describe('p5.SoundFile', function () { let sf = new p5.SoundFile(); expect(sf.getPan()).to.equal(0); sf.pan(0.32); - expect(sf.panPosition).to.equal(0.32); - expect(sf.getPan()).to.equal(0.32); + setTimeout(() => { + expect(sf.getPan()).to.equal(0.32); + }, 5); //with delay let sf2 = new p5.SoundFile(); sf2.pan(-0.89, 0.1); setTimeout(() => { - expect(sf2.panPosition).to.equal(-0.89); expect(sf2.getPan()).to.equal(-0.89); }, 100); }); From 24b1bc1db249860622ea69079dfe0fb24103c234 Mon Sep 17 00:00:00 2001 From: Abhijay Jain Date: Mon, 23 Jan 2023 11:46:56 +0530 Subject: [PATCH 10/11] (Docs) : added missing fields in p5.PeakDetect reference Signed-off-by: Abhijay Jain --- src/peakDetect.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/peakDetect.js b/src/peakDetect.js index 02db7f61..744eda1e 100644 --- a/src/peakDetect.js +++ b/src/peakDetect.js @@ -111,10 +111,11 @@ class PeakDetect { this.currentValue = 0; /** - * isDetected is set to true when a peak is detected. - * + * It returns a boolean indicating whether a peak in the audio frequency spectrum has been detected or not. * @attribute isDetected {Boolean} * @default false + * @property {Number} isDetected + * @for p5.PeakDetect */ this.isDetected = false; From f302c0d5714369d0fbfb43d8d6aafb62039888fa Mon Sep 17 00:00:00 2001 From: KevinGrajeda Date: Tue, 24 Jan 2023 19:07:04 -0600 Subject: [PATCH 11/11] add dispose to panner fallback --- src/oscillator.js | 1 + src/panner.js | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/oscillator.js b/src/oscillator.js index cfb1e3e5..79d72c55 100644 --- a/src/oscillator.js +++ b/src/oscillator.js @@ -446,6 +446,7 @@ class Oscillator { this.stop(now); this.disconnect(); this.panner.dispose(); + this.panner = null; this.oscillator = null; } // if it is a Pulse diff --git a/src/panner.js b/src/panner.js index 7a3ec20d..e234d23d 100644 --- a/src/panner.js +++ b/src/panner.js @@ -43,7 +43,7 @@ if (typeof ac.createStereoPanner !== 'undefined') { let time = tFromNow || 0; this.stereoPanner.pan.linearRampToValueAtTime( val, - this.ac.currentTime + 0.02 + time + this.ac.currentTime + time ); } else if (typeof val !== 'undefined') { val.connect(this.stereoPanner.pan); @@ -157,6 +157,29 @@ if (typeof ac.createStereoPanner !== 'undefined') { this.output.disconnect(); } } + + dispose() { + if (this.input) { + this.input.disconnect(); + delete this.input; + } + if (this.output) { + this.output.disconnect(); + delete this.output; + } + if (this.left) { + this.left.disconnect(); + delete this.left; + } + if (this.right) { + this.right.disconnect(); + delete this.right; + } + if (this.splitter) { + this.splitter.disconnect(); + delete this.splitter; + } + } } panner = Panner; }