Skip to content

Commit 40d4a3c

Browse files
committed
update panner fallback to extend effect
1 parent 517a7b7 commit 40d4a3c

File tree

5 files changed

+28
-95
lines changed

5 files changed

+28
-95
lines changed

src/oscillator.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,8 @@ class Oscillator {
135135
// stereo panning
136136
this.connection = p5sound.input; // connect to p5sound by default
137137

138-
if (typeof p5sound.audiocontext.createStereoPanner !== 'undefined') {
139-
this.panner = new Panner();
140-
this.output.connect(this.panner);
141-
} else {
142-
this.panner = new Panner(this.output, this.connection, 1);
143-
}
138+
this.panner = new Panner();
139+
this.output.connect(this.panner);
144140
//array of math operation signal chaining
145141
this.mathOps = [this.output];
146142

src/panner.js

Lines changed: 21 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -74,46 +74,38 @@ if (typeof ac.createStereoPanner !== 'undefined') {
7474
delete this.stereoPanner;
7575
}
7676
}
77-
78-
//not implemented because stereopanner
79-
//node does not require this and will automatically
80-
//convert single channel or multichannel to stereo.
81-
//tested with single and stereo, not with (>2) multichannel
82-
inputChannels() {}
8377
}
8478

8579
panner = Panner;
8680
} else {
8781
// if there is no createStereoPanner object
8882
// such as in safari 7.1.7 at the time of writing this
8983
// use this method to create the effect
90-
class Panner {
91-
constructor(input, output, numInputChannels) {
92-
this.input = ac.createGain();
93-
input.connect(this.input);
84+
class Panner extends Effect {
85+
constructor() {
86+
super();
87+
88+
// 'explicit' channelCountMode will convert any number of channels to stereo
89+
this.input.channelCountMode = 'explicit';
9490

9591
this.panValue = 0;
9692
this.left = ac.createGain();
9793
this.right = ac.createGain();
9894
this.left.channelInterpretation = 'discrete';
9995
this.right.channelInterpretation = 'discrete';
10096

101-
// if input is stereo
102-
if (numInputChannels > 1) {
103-
this.splitter = ac.createChannelSplitter(2);
104-
this.input.connect(this.splitter);
97+
this.splitter = ac.createChannelSplitter(2);
98+
this.merger = ac.createChannelMerger(2);
10599

106-
this.splitter.connect(this.left, 1);
107-
this.splitter.connect(this.right, 0);
108-
} else {
109-
this.input.connect(this.left);
110-
this.input.connect(this.right);
111-
}
100+
this.input.connect(this.splitter);
112101

113-
this.output = ac.createChannelMerger(2);
114-
this.left.connect(this.output, 0, 1);
115-
this.right.connect(this.output, 0, 0);
116-
this.output.connect(output);
102+
this.splitter.connect(this.left, 1);
103+
this.splitter.connect(this.right, 0);
104+
105+
this.left.connect(this.merger, 0, 1);
106+
this.right.connect(this.merger, 0, 0);
107+
108+
this.merger.connect(this.wet);
117109
}
118110

119111
// -1 is left, +1 is right
@@ -132,44 +124,8 @@ if (typeof ac.createStereoPanner !== 'undefined') {
132124
return this.panValue;
133125
}
134126

135-
inputChannels(numChannels) {
136-
if (numChannels === 1) {
137-
this.input.disconnect();
138-
this.input.connect(this.left);
139-
this.input.connect(this.right);
140-
} else if (numChannels === 2) {
141-
if (typeof this.splitter === 'undefined') {
142-
this.splitter = ac.createChannelSplitter(2);
143-
}
144-
this.input.disconnect();
145-
this.input.connect(this.splitter);
146-
this.splitter.connect(this.left, 1);
147-
this.splitter.connect(this.right, 0);
148-
}
149-
}
150-
151-
connect(obj) {
152-
this.output.connect(obj);
153-
if (obj && obj._onNewInput) {
154-
obj._onNewInput(this);
155-
}
156-
}
157-
158-
disconnect() {
159-
if (this.output) {
160-
this.output.disconnect();
161-
}
162-
}
163-
164127
dispose() {
165-
if (this.input) {
166-
this.input.disconnect();
167-
delete this.input;
168-
}
169-
if (this.output) {
170-
this.output.disconnect();
171-
delete this.output;
172-
}
128+
super.dispose();
173129
if (this.left) {
174130
this.left.disconnect();
175131
delete this.left;
@@ -182,6 +138,10 @@ if (typeof ac.createStereoPanner !== 'undefined') {
182138
this.splitter.disconnect();
183139
delete this.splitter;
184140
}
141+
if (this.merger) {
142+
this.merger.disconnect();
143+
delete this.merger;
144+
}
185145
}
186146
}
187147
panner = Panner;

src/soundfile.js

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,8 @@ class SoundFile {
182182
this.startMillis = null;
183183

184184
// stereo panning
185-
if (typeof p5sound.audiocontext.createStereoPanner !== 'undefined') {
186-
this.panner = new Panner();
187-
this.output.connect(this.panner);
188-
} else {
189-
this.panner = new Panner(this.output, p5sound.input, 2);
190-
}
185+
this.panner = new Panner();
186+
this.output.connect(this.panner);
191187

192188
// it is possible to instantiate a soundfile with no path
193189
if (this.url || this.file) {
@@ -248,7 +244,6 @@ class SoundFile {
248244
function (buff) {
249245
if (!self.panner) return;
250246
self.buffer = buff;
251-
self.panner.inputChannels(buff.numberOfChannels);
252247
if (callback) {
253248
callback(self);
254249
}
@@ -323,7 +318,6 @@ class SoundFile {
323318
ac.decodeAudioData(reader.result, function (buff) {
324319
if (!self.panner) return;
325320
self.buffer = buff;
326-
self.panner.inputChannels(buff.numberOfChannels);
327321
if (callback) {
328322
callback(self);
329323
}
@@ -1357,9 +1351,6 @@ class SoundFile {
13571351
}
13581352

13591353
this.buffer = newBuffer;
1360-
1361-
// set numbers of channels on input to the panner
1362-
this.panner.inputChannels(numChannels);
13631354
}
13641355

13651356
// initialize counterNode, set its initial buffer and playbackRate

test/tests/p5.Panner.js

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
const expect = chai.expect;
22

33
describe('p5.Panner', function () {
4-
let ac, output, input;
4+
let ac, input;
55
beforeEach(function () {
66
ac = p5.prototype.getAudioContext();
7-
output = ac.createGain();
87
input = ac.createGain();
98
});
109
it('can be created', function () {
@@ -24,24 +23,11 @@ describe('p5.Panner', function () {
2423
}, 25);
2524
});
2625
it('can be panned with a delay', function (done) {
27-
let panner = new p5.Panner(input, output);
26+
let panner = new p5.Panner();
2827
panner.pan(-0.7, 0.1);
2928
setTimeout(() => {
3029
expect(panner.getPan()).to.be.approximately(-0.7, 0.01);
3130
done();
3231
}, 125);
3332
});
34-
it('can take inputChannels as 1 or 2', function () {
35-
let panner = new p5.Panner(input, output);
36-
panner.inputChannels(1);
37-
panner.inputChannels(2);
38-
});
39-
it('can execute _onNewInput() hook on connected unit', function (done) {
40-
let panner = new p5.Panner(input, output);
41-
const gain = new p5.Gain();
42-
gain._onNewInput = function () {
43-
done();
44-
};
45-
panner.connect(gain);
46-
});
4733
});

test/tests/p5.SoundFile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe('p5.SoundFile', function () {
3131
expect(sf.mode).to.equal('sustain');
3232
expect(sf.startMillis).to.be.null;
3333
expect(sf.getPan()).to.equal(0);
34-
expect(sf.panner).to.have.property('stereoPanner');
34+
expect(sf).to.have.property('panner');
3535
expect(p5.soundOut.soundArray).to.include(sf);
3636

3737
expect(sf._whileLoading).to.not.throw();

0 commit comments

Comments
 (0)