Skip to content

Commit 2e97d14

Browse files
committed
updated examples/polyphonic_synth to use new synth API and AudioVoice base class
1 parent b9aff1c commit 2e97d14

File tree

3 files changed

+61
-155
lines changed

3 files changed

+61
-155
lines changed

examples/polyphonic_synth/sketch.js

Lines changed: 40 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
2-
3-
41
var psynth;
52

63
var ptable_real,ptable_imag;
74
var real_wave = [];
85
var imag_wave = []
96

107
function preload(){
11-
ptable_real = loadStrings('Wurlitzer_2_real.txt');
12-
ptable_imag = loadStrings('Wurlitzer_2_imag.txt' );
8+
ptable_real = loadStrings('../polyphonic_synth/TwelveStringGuitar_real.txt');
9+
ptable_imag = loadStrings('../polyphonic_synth/TwelveStringGuitar_imag.txt' );
1310
}
1411

1512

@@ -22,16 +19,16 @@ function setup() {
2219
frameRate(25);
2320

2421

25-
psynth = new PolySynth(15,PeriodicWave);
22+
// psynth = new PolySynth(15,PeriodicWave);
23+
psynth = new p5.PolySynth(PeriodicWave, 8);
2624

2725
for (var i = 0 ; i < 2048 ; i++) {
2826
real_wave[i] = float(ptable_real[i]);
29-
3027
}
3128
for (var i = 0 ; i < 2048 ; i++) {
3229
imag_wave[i] = float(ptable_imag[i]);
33-
3430
}
31+
3532

3633
}
3734

@@ -44,81 +41,77 @@ function draw() {
4441

4542
function mousePressed(){
4643

47-
var note = int(map(mouseX,0,width,60,84));
44+
var note = int(map(mouseX,0,width,200,440));
4845
var length = map(mouseY,0,300,0,5);
49-
50-
psynth.setAdsr(0.021,0.025,length,0.025);
46+
47+
48+
49+
psynth.play(note,1,0,length);
50+
psynth.noteADSR(note, 0.021,0.025,length,0.025);
51+
52+
var index = psynth.notes[note].getValueAtTime();
53+
psynth.audiovoices[index].setParams({real: real_wave , imag: imag_wave});
5154

5255
// uncomment for SquareVoice detune parameters
5356
//var d = int(random(1,12));
5457
//psynth.setParams({detune: d });
5558

5659
// uncomment for PeriodicWave
57-
psynth.setParams({real: real_wave , imag: imag_wave});
58-
59-
psynth.setNote(note);
60-
psynth.play();
60+
//psynth.setParams({real: real_wave , imag: imag_wave});
61+
6162

6263
}
6364

6465

6566
//////////////////////////////////////////////////////////////////////////////
6667
function PeriodicWave(params){
67-
AudioVoice.call(this);
68+
p5.MonoSynth.call(this);
6869

6970
this.real = new Float32Array([0,0]) ;
7071
this.imag = new Float32Array([0,1]);
71-
72-
this.context = getAudioContext();
7372

74-
this.wt = this.context.createPeriodicWave(this.real,this.imag);
73+
this.wt = this.ac.createPeriodicWave(this.real,this.imag);
7574

76-
this.oscillator = this.context.createOscillator();
77-
this.oscillator.setPeriodicWave(this.wt);
75+
// this.oscillator = this.context.createOscillator();
76+
this.oscillator.oscillator.setPeriodicWave(this.wt);
77+
this.filter.setType('lowpass');
78+
this.filter.set(22050,5);
7879

79-
this.oscillator.disconnect();
80-
this.oscillator.start();
81-
82-
this.oscillator.connect(this.filter);
83-
84-
this.setNote = function(note){
85-
this.oscillator.frequency.value = midiToFreq(note);
86-
}
80+
this.env.connect(this.filter);
8781

8882
this.setParams = function(params){
89-
// console.log(params.real);
9083
this.real = new Float32Array(params.real);
9184
this.imag = new Float32Array(params.imag);
92-
this.wt = this.context.createPeriodicWave(this.real, this.imag);
93-
this.oscillator.setPeriodicWave(this. wt);
85+
this.wt = this.ac.createPeriodicWave(this.real, this.imag);
86+
this.oscillator.oscillator.setPeriodicWave(this. wt);
9487
}
88+
this.setADSR = function(a,d,s,r) {
89+
this.attack = a;
90+
this.decay=d;
91+
this.sustain=s;
92+
this.release=r;
93+
this.volume = 1
94+
this.env.set(this.attack, this.volume, this.decay, this.volume, this.release, this.volume);
95+
// this.env.set(this.attack, this.decay, this.sustain, this.release);
96+
this.env.play(this.filter);
9597

98+
}
9699

97100
}
98101

99-
PeriodicWave.prototype = Object.create(AudioVoice.prototype);
102+
PeriodicWave.prototype = Object.create(p5.MonoSynth.prototype);
100103
PeriodicWave.prototype.constructor = PeriodicWave;
101104

102105

103106
//////////////////////////////////////////////////////////////////////////////////////////////
104107
// A typical synth class which inherits from AudioVoice class
105108
function SquareVoice(){
106109

107-
AudioVoice.call(this);
108-
109-
this.osctype = 'square';
110-
this.oscillator = new p5.Oscillator(this.note,this.osctype);
111-
this.oscillator.disconnect();
112-
this.oscillator.start();
110+
p5.MonoSynth.call(this);
113111

114-
this.oscillator.connect(this.filter);
115-
116-
this.setNote = function(note){
117-
this.note = note;
118-
this.oscillator.freq(midiToFreq(note));
119-
}
112+
this.oscillator.setType('square');
120113
}
121-
SquareVoice.prototype = Object.create(AudioVoice.prototype); // browsers support ECMAScript 5 ! warning for compatibility with older browsers
114+
SquareVoice.prototype = Object.create(p5.MonoSynth.prototype); // browsers support ECMAScript 5 ! warning for compatibility with older browsers
122115
SquareVoice.prototype.constructor = SquareVoice;
123116

124117
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -150,101 +143,5 @@ function DetunedOsc(){
150143
}
151144
}
152145

153-
DetunedOsc.prototype = Object.create(AudioVoice.prototype);
146+
DetunedOsc.prototype = Object.create(p5.AudioVoice.prototype);
154147
DetunedOsc.prototype.constructor = DetunedOsc;
155-
156-
157-
158-
159-
160-
161-
////////////////////////////////////////////////////////////////////////////////////////////
162-
// A super AudioVoice class to talk to the PolySynth class
163-
function AudioVoice () {
164-
165-
this.osctype = 'sine';
166-
this.volume= 0.33;
167-
this.note = 60;
168-
169-
this.attack = 0.25;
170-
this.decay=0.25;
171-
this.sustain=0.95;
172-
this.release=0.25;
173-
this.env = new p5.Env(this.attack,this.volume, this.decay,this.volume, this.sustain, this.volume,this.release);
174-
175-
this.filter = new p5.LowPass();
176-
this.filter.set(22050, 5);
177-
178-
this.env.connect(this.filter);
179-
180-
}
181-
182-
AudioVoice.prototype.voicePlay = function (){
183-
this.env.play(this.filter);
184-
}
185-
186-
AudioVoice.prototype.attackPlay = function (){
187-
this.env.triggerAttack(this.oscillator);
188-
}
189-
190-
AudioVoice.prototype.releasePlay = function (){
191-
this.env.triggerRelease(this.oscillator);
192-
}
193-
194-
AudioVoice.prototype.setNote = function(){
195-
196-
}
197-
198-
AudioVoice.prototype.setParams = function(params){
199-
200-
}
201-
202-
203-
AudioVoice.prototype.setAdsr = function (a,d,s,r){
204-
this.attack = a;
205-
this.decay=d;
206-
this.sustain=s;
207-
this.release=r;
208-
this.env = new p5.Env(this.attack, this.decay, this.sustain, this.release);
209-
this.env.play(this.filter);
210-
}
211-
212-
213-
214-
/////////////////////////////////////////////////////////////////////////////
215-
// a class to deal with voices allocations, of notes, parameters etc.
216-
// should be abastracted from the user
217-
function PolySynth(num,synthVoice){
218-
this.voices = [];
219-
this.num_voices = num;
220-
this.poly_counter=0;
221-
222-
this.allocateVoices(synthVoice);
223-
}
224-
225-
PolySynth.prototype.allocateVoices = function(synthVoice){
226-
for (var i = 0 ; i < this.num_voices ; i++){
227-
this.voices.push(new synthVoice());
228-
}
229-
}
230-
231-
PolySynth.prototype.play = function (){
232-
this.voices[this.poly_counter].voicePlay();
233-
this.poly_counter += 1;
234-
this.poly_counter = this.poly_counter % this.num_voices;
235-
}
236-
237-
PolySynth.prototype.setAdsr = function (a,d,s,r){
238-
this.voices[this.poly_counter].setAdsr(a,d,s,r);
239-
}
240-
241-
PolySynth.prototype.setNote = function (note){
242-
this.voices[this.poly_counter].setNote(note);
243-
}
244-
245-
PolySynth.prototype.setParams = function (params){
246-
this.voices[this.poly_counter].setParams(params);
247-
}
248-
249-
250-

src/monosynth.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ define(function (require) {
4747
this.filter.set(5, 1);
4848

4949
// oscillator --> env --> filter --> this.output (gain) --> p5.soundOut
50-
51-
// this.oscillator.connect(this.filter);
50+
this.oscillator.disconnect();
51+
this.oscillator.connect(this.filter);
5252
this.env.setInput(this.oscillator);
5353
this.filter.connect(this.output);
5454

src/polysynth.js

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ define(function (require) {
103103
* @param {Number} [sustainTime] time to sustain before releasing the envelope
104104
*/
105105
p5.PolySynth.prototype.play = function (note,velocity, secondsFromNow, susTime) {
106+
var susTime = susTime || 1;
106107
this.noteAttack(note, velocity, secondsFromNow);
107108
this.noteRelease(note, secondsFromNow + susTime);
108109
};
@@ -131,8 +132,11 @@ define(function (require) {
131132
* @param {Number} [releaseTime] Time in seconds from now (defaults to 0)
132133
**/
133134

134-
p5.PolySynth.prototype.noteADSR = function (note,a,d,s,r) {
135-
this.audiovoices[ this.notes[note] ].setADSR(a,d,s,r);
135+
p5.PolySynth.prototype.noteADSR = function (note,a,d,s,r,timeFromNow) {
136+
var now = p5sound.audiocontext.currentTime;
137+
var timeFromNow = timeFromNow || 0;
138+
var t = now + timeFromNow
139+
this.audiovoices[ this.notes[note].getValueAtTime(t) ].setADSR(a,d,s,r);
136140
};
137141

138142

@@ -191,7 +195,7 @@ define(function (require) {
191195
var currentVoice;
192196

193197
//Release the note if it is already playing
194-
if (this.notes[note] !== undefined) {
198+
if ( this.notes[note] !== undefined && this.notes[note].getValueAtTime(t) !== null) {
195199
this.noteRelease(note,0);
196200
}
197201

@@ -211,7 +215,9 @@ define(function (require) {
211215

212216
//Overrite the entry in the notes object. A note (frequency value)
213217
//corresponds to the index of the audiovoice that is playing it
214-
this.notes[note] = currentVoice;
218+
219+
this.notes[note] = new TimelineSignal();
220+
this.notes[note].setValueAtTime(currentVoice,t);
215221

216222
//Find the scheduled change in this._voicesInUse that will be previous to this new note
217223
//Add 1 and schedule this value at time 't', when this note will start playing
@@ -265,23 +271,26 @@ define(function (require) {
265271
var note = typeof _note === 'string' ? this.AudioVoice.prototype._setNote(_note)
266272
: typeof _note === 'number' ? _note : this.audiovoices[this._newest].oscillator.freq().value;
267273

268-
if (this.notes[note] === undefined) {
269-
console.warn('Cannot release a note that is not already playing');
270-
} else {
271274
var now = p5sound.audiocontext.currentTime;
272275
var tFromNow = secondsFromNow || 0;
273276
var t = now + tFromNow;
274277

278+
279+
if (this.notes[note].getValueAtTime(t) === null) {
280+
console.warn('Cannot release a note that is not already playing');
281+
} else {
282+
283+
275284
//Find the scheduled change in this._voicesInUse that will be previous to this new note
276285
//subtract 1 and schedule this value at time 't', when this note will stop playing
277286
var previousVal = this._voicesInUse._searchBefore(t) === null ? 0 : this._voicesInUse._searchBefore(t).value;
278287
this._voicesInUse.setValueAtTime(previousVal - 1, t);
279288
//Then update all scheduled values that follow to decrease by 1
280289
this._updateAfter(t, -1);
281290

282-
// console.log('RELEASE ' + note);
283-
this.audiovoices[ this.notes[note] ].triggerRelease(tFromNow);
284-
this.notes[note] = undefined;
291+
this.audiovoices[ this.notes[note].getValueAtTime(t) ].triggerRelease(tFromNow);
292+
293+
this.notes[note].setValueAtTime( null, t);
285294

286295
this._newest = this._newest === 0 ? 0 : (this._newest - 1) % (this.polyValue - 1);
287296
}

0 commit comments

Comments
 (0)