@@ -17,11 +17,9 @@ define(function (require) {
17
17
*
18
18
* @param {Number } [synthVoice] A monophonic synth voice inheriting
19
19
* the AudioVoice class. Defaults to p5.MonoSynth
20
- *
21
20
* @param {Number } [polyValue] Number of voices, defaults to 8;
22
21
*
23
22
*
24
- *
25
23
* @example
26
24
* <div><code>
27
25
* var polysynth;
@@ -85,6 +83,7 @@ define(function (require) {
85
83
/**
86
84
* Construct the appropriate number of audiovoices
87
85
* @private
86
+ * @method _allocateVoices
88
87
*/
89
88
p5 . PolySynth . prototype . _allocateVoices = function ( ) {
90
89
for ( var i = 0 ; i < this . polyValue ; i ++ ) {
@@ -183,43 +182,61 @@ define(function (require) {
183
182
//this value is used by this._voicesInUse
184
183
var t = now + tFromNow ;
185
184
186
- // var note = _note === undefined ? 60 : _note;
187
- //
188
- var note = typeof _note === 'string' ? this . AudioVoice . prototype . _setNote ( _note )
189
- : typeof _note === 'number' ? _note : 440 ;
185
+ //Convert note to frequency if necessary. This is because entries into this.notes
186
+ //should be based on frequency for the sake of consistency.
187
+ var note = typeof _note === 'string' ? this . AudioVoice . prototype . _setNote ( _note )
188
+ : typeof _note === 'number' ? _note : 440 ;
190
189
var velocity = _velocity === undefined ? 1 : _velocity ;
191
190
192
191
var currentVoice ;
193
192
193
+ //Release the note if it is already playing
194
194
if ( this . notes [ note ] !== undefined ) {
195
195
this . noteRelease ( note , 0 ) ;
196
196
}
197
197
198
-
198
+ //Check to see how many voices are in use at the time the note will start
199
199
if ( this . _voicesInUse . getValueAtTime ( t ) < this . polyValue ) {
200
200
currentVoice = this . _voicesInUse . getValueAtTime ( t ) ;
201
- } else {
201
+ }
202
+ //If we are exceeding the polyvalue, bump off the oldest notes and replace
203
+ //with a new note
204
+ else {
202
205
currentVoice = this . _oldest ;
203
206
204
207
var oldestNote = p5 . prototype . freqToMidi ( this . audiovoices [ this . _oldest ] . oscillator . freq ( ) . value ) ;
205
208
this . noteRelease ( oldestNote ) ;
206
209
this . _oldest = ( this . _oldest + 1 ) % ( this . polyValue - 1 ) ;
207
210
}
208
211
212
+ //Overrite the entry in the notes object. A note (frequency value)
213
+ //corresponds to the index of the audiovoice that is playing it
209
214
this . notes [ note ] = currentVoice ;
210
215
211
- //this._voicesInUse.setValueAtTime(this._voicesInUse.getValueAtTime(t) + 1, t);
212
-
216
+ //Find the scheduled change in this._voicesInUse that will be previous to this new note
217
+ //Add 1 and schedule this value at time 't', when this note will start playing
213
218
var previousVal = this . _voicesInUse . _searchBefore ( t ) === null ? 0 : this . _voicesInUse . _searchBefore ( t ) . value ;
214
219
this . _voicesInUse . setValueAtTime ( previousVal + 1 , t ) ;
220
+
221
+ //Then update all scheduled values that follow to increase by 1
215
222
this . _updateAfter ( t , 1 ) ;
216
223
217
224
this . _newest = currentVoice ;
218
225
226
+ //The audiovoice handles the actual scheduling of the note
219
227
this . audiovoices [ currentVoice ] . triggerAttack ( note , velocity , tFromNow ) ;
220
-
221
228
} ;
222
229
230
+ /**
231
+ * Private method to ensure accurate values of this._voicesInUse
232
+ * Any time a new value is scheduled, it is necessary to increment all subsequent
233
+ * scheduledValues after attack, and decrement all subsequent
234
+ * scheduledValues after release
235
+ *
236
+ * @param {[type] } time [description]
237
+ * @param {[type] } value [description]
238
+ * @return {[type] } [description]
239
+ */
223
240
p5 . PolySynth . prototype . _updateAfter = function ( time , value ) {
224
241
225
242
if ( this . _voicesInUse . _searchAfter ( time ) === null ) {
@@ -229,8 +246,7 @@ define(function (require) {
229
246
var nextTime = this . _voicesInUse . _searchAfter ( time ) . time ;
230
247
this . _updateAfter ( nextTime , value ) ;
231
248
}
232
- }
233
-
249
+ } ;
234
250
235
251
236
252
/**
@@ -245,12 +261,9 @@ define(function (require) {
245
261
*/
246
262
247
263
p5 . PolySynth . prototype . noteRelease = function ( _note , secondsFromNow ) {
248
- // var note = _note === undefined ?
249
- // p5.prototype.freqToMidi(this.audiovoices[this._newest].oscillator.freq().value)
250
- // : _note;
264
+ //Make sure note is in frequency inorder to query the this.notes object
251
265
var note = typeof _note === 'string' ? this . AudioVoice . prototype . _setNote ( _note )
252
- : typeof _note === 'number' ? _note : this . audiovoices [ this . _newest ] . oscillator . freq ( ) . value ;
253
-
266
+ : typeof _note === 'number' ? _note : this . audiovoices [ this . _newest ] . oscillator . freq ( ) . value ;
254
267
255
268
if ( this . notes [ note ] === undefined ) {
256
269
console . warn ( 'Cannot release a note that is not already playing' ) ;
@@ -259,10 +272,11 @@ define(function (require) {
259
272
var tFromNow = secondsFromNow || 0 ;
260
273
var t = now + tFromNow ;
261
274
262
- // this._voicesInUse.setValueAtTime( this._voicesInUse.getValueAtTime(t)-1, t);
263
- // console.log(' value at time: '+ t +' value '+ this._voicesInUse.getValueAtTime(t));
275
+ //Find the scheduled change in this._voicesInUse that will be previous to this new note
276
+ //subtract 1 and schedule this value at time 't', when this note will stop playing
264
277
var previousVal = this . _voicesInUse . _searchBefore ( t ) === null ? 0 : this . _voicesInUse . _searchBefore ( t ) . value ;
265
278
this . _voicesInUse . setValueAtTime ( previousVal - 1 , t ) ;
279
+ //Then update all scheduled values that follow to decrease by 1
266
280
this . _updateAfter ( t , - 1 ) ;
267
281
268
282
// console.log('RELEASE ' + note);
@@ -274,37 +288,33 @@ define(function (require) {
274
288
275
289
} ;
276
290
277
-
278
291
/**
279
- * Set cutoms parameters to a specific synth implementation
280
- * with the help of JavaScript Object Notation (JSON).
281
- *
282
- * @method setParams
283
- * @param JSON object
284
- *
285
- * For instance to set the detune parameter of a synth, call :
286
- * setParams({detune: 15 });
287
- *
288
- */
289
- p5 . PolySynth . prototype . noteParams = function ( note , params ) {
290
- if ( this . voices [ note ] == null ) {
291
- this . voices [ note ] = new this . AudioVoice ( ) ;
292
- }
293
- this . voices [ note ] . setParams ( params ) ;
294
-
295
- } ;
296
-
292
+ * Connect to a p5.sound / Web Audio object.
293
+ *
294
+ * @method connect
295
+ * @param {Object } unit A p5.sound or Web Audio object
296
+ */
297
297
p5 . PolySynth . prototype . connect = function ( unit ) {
298
298
var u = unit || p5sound . input ;
299
299
this . output . connect ( u . input ? u . input : u ) ;
300
300
} ;
301
301
302
+ /**
303
+ * Disconnect all outputs
304
+ *
305
+ * @method disconnect
306
+ */
302
307
p5 . PolySynth . prototype . disconnect = function ( ) {
303
308
this . output . disconnect ( ) ;
304
309
} ;
305
310
311
+ /**
312
+ * Get rid of the MonoSynth and free up its resources / memory.
313
+ *
314
+ * @method dispose
315
+ */
306
316
p5 . PolySynth . prototype . dispose = function ( ) {
307
- this . audiovoices . forEach ( function ( voice ) {
317
+ this . audiovoices . forEach ( function ( voice ) {
308
318
voice . dispose ( ) ;
309
319
} ) ;
310
320
0 commit comments