Skip to content

Commit bdd9127

Browse files
author
piersh
committed
protect against errors during duplicate dispose/disconnect calls
1 parent 5b4a06a commit bdd9127

20 files changed

+270
-200
lines changed

src/amplitude.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,9 @@ define(function (require) {
166166
};
167167

168168
p5.Amplitude.prototype.disconnect = function() {
169-
this.output.disconnect();
169+
if (this.output) {
170+
this.output.disconnect();
171+
}
170172
};
171173

172174
// TO DO make this stereo / dependent on # of audio channels
@@ -305,11 +307,16 @@ define(function (require) {
305307
var index = p5sound.soundArray.indexOf(this);
306308
p5sound.soundArray.splice(index, 1);
307309

308-
this.input.disconnect();
309-
this.output.disconnect();
310+
if (this.input) {
311+
this.input.disconnect();
312+
delete this.input;
313+
}
314+
if (this.output) {
315+
this.output.disconnect();
316+
delete this.output;
317+
}
310318

311-
this.input = this.processor = undefined;
312-
this.output = undefined;
319+
delete this.processor;
313320
};
314321

315322
});

src/audioVoice.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ define(function() {
6565
};
6666

6767
p5.AudioVoice.prototype.dispose = function() {
68-
this.output.disconnect();
69-
delete this.output;
68+
if (this.output) {
69+
this.output.disconnect();
70+
delete this.output;
71+
}
7072
};
7173

7274
return p5.AudioVoice;

src/audioin.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,11 @@ define(function (require) {
179179
* @method disconnect
180180
*/
181181
p5.AudioIn.prototype.disconnect = function() {
182-
this.output.disconnect();
183-
// stay connected to amplitude even if not outputting to p5
184-
this.output.connect(this.amplitude.input);
182+
if (this.output) {
183+
this.output.disconnect();
184+
// stay connected to amplitude even if not outputting to p5
185+
this.output.connect(this.amplitude.input);
186+
}
185187
};
186188

187189
/**

src/compressor.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,11 @@ define(function (require) {
215215

216216

217217
p5.Compressor.prototype.dispose = function() {
218-
Effect.prototype.dispose.apply(this);
219-
this.compressor.disconnect();
220-
this.compressor = undefined;
218+
Effect.prototype.dispose.apply(this);
219+
if (this.compressor) {
220+
this.compressor.disconnect();
221+
delete this.compressor;
222+
}
221223
};
222224

223225
return p5.Compressor;

src/distortion.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,9 @@ define(function (require) {
132132

133133
p5.Distortion.prototype.dispose = function() {
134134
Effect.prototype.dispose.apply(this);
135-
this.waveShaperNode.disconnect();
136-
this.waveShaperNode = null;
135+
if (this.waveShaperNode) {
136+
this.waveShaperNode.disconnect();
137+
this.waveShaperNode = null;
138+
}
137139
};
138140
});

src/effect.js

Lines changed: 157 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,163 @@
11
'use strict';
22
define(function (require) {
33

4-
var p5sound = require('master');
5-
var CrossFade = require('Tone/component/CrossFade');
6-
7-
/**
8-
* Effect is a base class for audio effects in p5. <br>
9-
* This module handles the nodes and methods that are
10-
* common and useful for current and future effects.
11-
*
12-
*
13-
* This class is extended by <a href="/reference/#/p5.Distortion">p5.Distortion</a>,
14-
* <a href="/reference/#/p5.Compressor">p5.Compressor</a>,
15-
* <a href="/reference/#/p5.Delay">p5.Delay</a>,
16-
* <a href="/reference/#/p5.Filter">p5.Filter</a>,
17-
* <a href="/reference/#/p5.Reverb">p5.Reverb</a>.
18-
*
19-
* @class p5.Effect
20-
* @constructor
21-
*
22-
* @param {Object} [ac] Reference to the audio context of the p5 object
23-
* @param {AudioNode} [input] Gain Node effect wrapper
24-
* @param {AudioNode} [output] Gain Node effect wrapper
25-
* @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)
26-
* @param {AudioNode} [wet] Effects that extend this class should connect
27-
* to the wet signal to this gain node, so that dry and wet
28-
* signals are mixed properly.
29-
*/
30-
p5.Effect = function() {
31-
this.ac = p5sound.audiocontext;
32-
33-
this.input = this.ac.createGain();
34-
this.output = this.ac.createGain();
35-
36-
/**
37-
* The p5.Effect class is built
38-
* using Tone.js CrossFade
39-
* @private
40-
*/
41-
42-
this._drywet = new CrossFade(1);
43-
44-
/**
45-
* In classes that extend
46-
* p5.Effect, connect effect nodes
47-
* to the wet parameter
48-
*/
49-
this.wet = this.ac.createGain();
50-
51-
this.input.connect(this._drywet.a);
52-
this.wet.connect(this._drywet.b);
53-
this._drywet.connect(this.output);
54-
55-
this.connect();
56-
57-
//Add to the soundArray
58-
p5sound.soundArray.push(this);
59-
};
60-
61-
/**
62-
* Set the output volume of the filter.
63-
*
64-
* @method amp
65-
* @param {Number} [vol] amplitude between 0 and 1.0
66-
* @param {Number} [rampTime] create a fade that lasts until rampTime
67-
* @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds
68-
*/
69-
p5.Effect.prototype.amp = function(vol, rampTime, tFromNow){
70-
var rampTime = rampTime || 0;
71-
var tFromNow = tFromNow || 0;
72-
var now = p5sound.audiocontext.currentTime;
73-
var currentVol = this.output.gain.value;
74-
this.output.gain.cancelScheduledValues(now);
75-
this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + .001);
76-
this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + .001);
77-
};
78-
79-
/**
80-
* Link effects together in a chain
81-
* Example usage: filter.chain(reverb, delay, panner);
82-
* May be used with an open-ended number of arguments
83-
*
84-
* @method chain
4+
var p5sound = require('master');
5+
var CrossFade = require('Tone/component/CrossFade');
6+
7+
/**
8+
* Effect is a base class for audio effects in p5. <br>
9+
* This module handles the nodes and methods that are
10+
* common and useful for current and future effects.
11+
*
12+
*
13+
* This class is extended by <a href="/reference/#/p5.Distortion">p5.Distortion</a>,
14+
* <a href="/reference/#/p5.Compressor">p5.Compressor</a>,
15+
* <a href="/reference/#/p5.Delay">p5.Delay</a>,
16+
* <a href="/reference/#/p5.Filter">p5.Filter</a>,
17+
* <a href="/reference/#/p5.Reverb">p5.Reverb</a>.
18+
*
19+
* @class p5.Effect
20+
* @constructor
21+
*
22+
* @param {Object} [ac] Reference to the audio context of the p5 object
23+
* @param {AudioNode} [input] Gain Node effect wrapper
24+
* @param {AudioNode} [output] Gain Node effect wrapper
25+
* @param {Object} [_drywet] Tone.JS CrossFade node (defaults to value: 1)
26+
* @param {AudioNode} [wet] Effects that extend this class should connect
27+
* to the wet signal to this gain node, so that dry and wet
28+
* signals are mixed properly.
29+
*/
30+
p5.Effect = function() {
31+
this.ac = p5sound.audiocontext;
32+
33+
this.input = this.ac.createGain();
34+
this.output = this.ac.createGain();
35+
36+
/**
37+
* The p5.Effect class is built
38+
* using Tone.js CrossFade
39+
* @private
40+
*/
41+
42+
this._drywet = new CrossFade(1);
43+
44+
/**
45+
* In classes that extend
46+
* p5.Effect, connect effect nodes
47+
* to the wet parameter
48+
*/
49+
this.wet = this.ac.createGain();
50+
51+
this.input.connect(this._drywet.a);
52+
this.wet.connect(this._drywet.b);
53+
this._drywet.connect(this.output);
54+
55+
this.connect();
56+
57+
//Add to the soundArray
58+
p5sound.soundArray.push(this);
59+
};
60+
61+
/**
62+
* Set the output volume of the filter.
63+
*
64+
* @method amp
65+
* @param {Number} [vol] amplitude between 0 and 1.0
66+
* @param {Number} [rampTime] create a fade that lasts until rampTime
67+
* @param {Number} [tFromNow] schedule this event to happen in tFromNow seconds
68+
*/
69+
p5.Effect.prototype.amp = function(vol, rampTime, tFromNow){
70+
var rampTime = rampTime || 0;
71+
var tFromNow = tFromNow || 0;
72+
var now = p5sound.audiocontext.currentTime;
73+
var currentVol = this.output.gain.value;
74+
this.output.gain.cancelScheduledValues(now);
75+
this.output.gain.linearRampToValueAtTime(currentVol, now + tFromNow + .001);
76+
this.output.gain.linearRampToValueAtTime(vol, now + tFromNow + rampTime + .001);
77+
};
78+
79+
/**
80+
* Link effects together in a chain
81+
* Example usage: filter.chain(reverb, delay, panner);
82+
* May be used with an open-ended number of arguments
83+
*
84+
* @method chain
8585
* @param {Object} [arguments] Chain together multiple sound objects
86-
*/
87-
p5.Effect.prototype.chain = function(){
88-
if (arguments.length>0){
89-
this.connect(arguments[0]);
90-
for(var i=1;i<arguments.length; i+=1){
91-
arguments[i-1].connect(arguments[i]);
92-
}
93-
}
94-
return this;
95-
};
96-
97-
/**
98-
* Adjust the dry/wet value.
99-
*
100-
* @method drywet
101-
* @param {Number} [fade] The desired drywet value (0 - 1.0)
102-
*/
103-
p5.Effect.prototype.drywet = function(fade){
104-
if (typeof fade !=="undefined"){
105-
this._drywet.fade.value = fade
106-
}
107-
return this._drywet.fade.value;
108-
};
109-
110-
/**
111-
* Send output to a p5.js-sound, Web Audio Node, or use signal to
112-
* control an AudioParam
113-
*
114-
* @method connect
115-
* @param {Object} unit
116-
*/
117-
p5.Effect.prototype.connect = function (unit) {
118-
var u = unit || p5.soundOut.input;
119-
this.output.connect(u.input ? u.input : u);
120-
};
121-
122-
/**
123-
* Disconnect all output.
124-
*
125-
* @method disconnect
126-
*/
127-
p5.Effect.prototype.disconnect = function() {
128-
this.output.disconnect();
129-
};
130-
131-
p5.Effect.prototype.dispose = function() {
132-
// remove refernce form soundArray
133-
var index = p5sound.soundArray.indexOf(this);
134-
p5sound.soundArray.splice(index, 1);
135-
136-
this.input.disconnect();
137-
this.input = undefined;
138-
139-
this.output.disconnect();
140-
this.output = undefined;
141-
142-
this._drywet.disconnect();
143-
delete this._drywet;
144-
145-
this.wet.disconnect();
146-
delete this.wet;
147-
148-
this.ac = undefined;
149-
};
150-
151-
return p5.Effect;
86+
*/
87+
p5.Effect.prototype.chain = function(){
88+
if (arguments.length>0){
89+
this.connect(arguments[0]);
90+
for(var i=1;i<arguments.length; i+=1){
91+
arguments[i-1].connect(arguments[i]);
92+
}
93+
}
94+
return this;
95+
};
96+
97+
/**
98+
* Adjust the dry/wet value.
99+
*
100+
* @method drywet
101+
* @param {Number} [fade] The desired drywet value (0 - 1.0)
102+
*/
103+
p5.Effect.prototype.drywet = function(fade){
104+
if (typeof fade !=="undefined"){
105+
this._drywet.fade.value = fade
106+
}
107+
return this._drywet.fade.value;
108+
};
109+
110+
/**
111+
* Send output to a p5.js-sound, Web Audio Node, or use signal to
112+
* control an AudioParam
113+
*
114+
* @method connect
115+
* @param {Object} unit
116+
*/
117+
p5.Effect.prototype.connect = function (unit) {
118+
var u = unit || p5.soundOut.input;
119+
this.output.connect(u.input ? u.input : u);
120+
};
121+
122+
/**
123+
* Disconnect all output.
124+
*
125+
* @method disconnect
126+
*/
127+
p5.Effect.prototype.disconnect = function() {
128+
if (this.output) {
129+
this.output.disconnect();
130+
}
131+
};
132+
133+
p5.Effect.prototype.dispose = function() {
134+
// remove refernce form soundArray
135+
var index = p5sound.soundArray.indexOf(this);
136+
p5sound.soundArray.splice(index, 1);
137+
138+
if (this.input) {
139+
this.input.disconnect();
140+
delete this.input;
141+
}
142+
143+
if (this.output) {
144+
this.output.disconnect();
145+
delete this.output;
146+
}
147+
148+
if (this._drywet) {
149+
this._drywet.disconnect();
150+
delete this._drywet;
151+
}
152+
153+
if (this.wet) {
154+
this.wet.disconnect();
155+
delete this.wet;
156+
}
157+
158+
this.ac = undefined;
159+
};
160+
161+
return p5.Effect;
152162

153163
});

0 commit comments

Comments
 (0)