Tone.js/Tone/instrument/PolySynth.js

198 lines
5.6 KiB
JavaScript
Raw Normal View History

2014-09-04 02:35:27 +00:00
define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/source/Source"],
2014-08-25 17:26:26 +00:00
function(Tone){
"use strict";
2014-08-25 17:26:26 +00:00
/**
* @class Creates a polyphonic synthesizer out of
* the monophonic voice which is passed in.
*
* @constructor
2014-09-20 23:24:04 +00:00
* @extends {Tone.Instrument}
* @param {number|Object} [polyphony=4] the number of voices to create
* @param {function} [voice=Tone.MonoSynth] the constructor of the voices
2014-08-25 17:26:26 +00:00
* uses Tone.MonoSynth by default
2015-02-28 04:24:51 +00:00
* @example
* //a polysynth composed of 6 Voices of MonoSynth
* var synth = new Tone.PolySynth(6, Tone.MonoSynth);
* //set a MonoSynth preset
* synth.setPreset("Pianoetta");
2014-08-25 17:26:26 +00:00
*/
Tone.PolySynth = function(){
2014-09-20 23:24:04 +00:00
Tone.Instrument.call(this);
2014-08-25 17:26:26 +00:00
2015-02-20 06:00:32 +00:00
var options = this.optionsObject(arguments, ["polyphony", "voice"], Tone.PolySynth.defaults);
2014-08-25 17:26:26 +00:00
/**
* the array of voices
* @type {Array}
*/
2014-12-08 16:03:20 +00:00
this.voices = new Array(options.polyphony);
2014-08-25 17:26:26 +00:00
/**
* the queue of free voices
* @private
* @type {Array}
*/
this._freeVoices = [];
/**
* keeps track of which notes are down
* @private
* @type {Object}
*/
this._activeVoices = {};
//create the voices
for (var i = 0; i < options.polyphony; i++){
2015-02-20 06:00:32 +00:00
var v = new options.voice(arguments[2], arguments[3]);
2014-12-08 16:03:20 +00:00
this.voices[i] = v;
2014-08-25 17:26:26 +00:00
v.connect(this.output);
}
//make a copy of the voices
2014-12-08 16:03:20 +00:00
this._freeVoices = this.voices.slice(0);
2015-02-20 06:00:32 +00:00
//get the prototypes and properties
2014-08-25 17:26:26 +00:00
};
2014-09-20 23:24:04 +00:00
Tone.extend(Tone.PolySynth, Tone.Instrument);
2014-08-25 17:26:26 +00:00
/**
* the defaults
* @const
* @static
* @type {Object}
*/
Tone.PolySynth.defaults = {
"polyphony" : 4,
2015-02-20 06:00:32 +00:00
"voice" : Tone.MonoSynth
2014-08-25 17:26:26 +00:00
};
2015-02-20 06:00:32 +00:00
/**
* Pull properties from the
*/
2014-08-25 17:26:26 +00:00
/**
* trigger the attack
* @param {string|number|Object|Array} value the value of the note(s) to start.
* if the value is an array, it will iterate
* over the array to play each of the notes
2015-05-23 23:01:05 +00:00
* @param {Tone.Type.Time} [time=now] the start time of the note
2014-12-02 06:42:08 +00:00
* @param {number} [velocity=1] the velocity of the note
2015-02-02 18:30:36 +00:00
* @returns {Tone.PolySynth} `this`
2014-08-25 17:26:26 +00:00
*/
2014-09-04 02:35:27 +00:00
Tone.PolySynth.prototype.triggerAttack = function(value, time, velocity){
if (!Array.isArray(value)){
value = [value];
}
for (var i = 0; i < value.length; i++){
var val = value[i];
var stringified = JSON.stringify(val);
if (this._activeVoices[stringified]){
this._activeVoices[stringified].triggerAttack(val, time, velocity);
} else if (this._freeVoices.length > 0){
var voice = this._freeVoices.shift();
voice.triggerAttack(val, time, velocity);
this._activeVoices[stringified] = voice;
}
2014-08-25 17:26:26 +00:00
}
2015-02-02 18:30:36 +00:00
return this;
2014-09-04 02:35:27 +00:00
};
/**
* trigger the attack and release after the specified duration
*
* @param {string|number|Object|Array} value the note(s).
* if the value is an array, it will iterate
* over the array to play each of the notes
2015-05-23 23:01:05 +00:00
* @param {Tone.Type.Time} duration the duration of the note
* @param {Tone.Type.Time} [time=now] if no time is given, defaults to now
2014-12-02 06:42:08 +00:00
* @param {number} [velocity=1] the velocity of the attack (0-1)
2015-02-02 18:30:36 +00:00
* @returns {Tone.PolySynth} `this`
2014-09-04 02:35:27 +00:00
*/
Tone.PolySynth.prototype.triggerAttackRelease = function(value, duration, time, velocity){
time = this.toSeconds(time);
this.triggerAttack(value, time, velocity);
2014-09-09 04:40:25 +00:00
this.triggerRelease(value, time + this.toSeconds(duration));
2015-02-02 18:30:36 +00:00
return this;
2014-08-25 17:26:26 +00:00
};
/**
* trigger the release of a note
* @param {string|number|Object|Array} value the value of the note(s) to release.
* if the value is an array, it will iterate
* over the array to play each of the notes
2015-05-23 23:01:05 +00:00
* @param {Tone.Type.Time} [time=now] the release time of the note
2015-02-02 18:30:36 +00:00
* @returns {Tone.PolySynth} `this`
2014-08-25 17:26:26 +00:00
*/
Tone.PolySynth.prototype.triggerRelease = function(value, time){
if (!Array.isArray(value)){
value = [value];
}
for (var i = 0; i < value.length; i++){
//get the voice
var stringified = JSON.stringify(value[i]);
var voice = this._activeVoices[stringified];
if (voice){
voice.triggerRelease(time);
this._freeVoices.push(voice);
2015-04-18 14:54:08 +00:00
delete this._activeVoices[stringified];
voice = null;
}
2014-08-25 17:26:26 +00:00
}
2015-02-02 18:30:36 +00:00
return this;
2014-08-25 17:26:26 +00:00
};
/**
* set the options on all of the voices
2015-04-24 23:34:26 +00:00
* @param {Object|string} params
* @param {number=} value
2015-05-23 23:01:05 +00:00
* @param {Tone.Type.Time=} rampTime
2015-02-02 18:30:36 +00:00
* @returns {Tone.PolySynth} `this`
2014-08-25 17:26:26 +00:00
*/
2015-04-24 23:34:26 +00:00
Tone.PolySynth.prototype.set = function(params, value, rampTime){
2014-12-08 16:03:20 +00:00
for (var i = 0; i < this.voices.length; i++){
2015-04-24 23:34:26 +00:00
this.voices[i].set(params, value, rampTime);
2014-08-25 17:26:26 +00:00
}
2015-02-02 18:30:36 +00:00
return this;
2014-08-25 17:26:26 +00:00
};
2015-02-20 06:00:32 +00:00
/**
* get a group of parameters
* @param {Array=} params the parameters to get, otherwise will return
* all available.
*/
Tone.PolySynth.prototype.get = function(params){
return this.voices[0].get(params);
};
2014-09-09 04:40:25 +00:00
/**
* @param {string} presetName the preset name
2015-02-02 18:30:36 +00:00
* @returns {Tone.PolySynth} `this`
2014-09-09 04:40:25 +00:00
*/
Tone.PolySynth.prototype.setPreset = function(presetName){
2014-12-08 16:03:20 +00:00
for (var i = 0; i < this.voices.length; i++){
this.voices[i].setPreset(presetName);
2014-09-09 04:40:25 +00:00
}
2015-02-02 18:30:36 +00:00
return this;
2014-09-09 04:40:25 +00:00
};
2014-08-25 17:26:26 +00:00
/**
* clean up
2015-02-02 18:30:36 +00:00
* @returns {Tone.PolySynth} `this`
2014-08-25 17:26:26 +00:00
*/
Tone.PolySynth.prototype.dispose = function(){
2014-09-20 23:24:04 +00:00
Tone.Instrument.prototype.dispose.call(this);
2014-12-08 16:03:20 +00:00
for (var i = 0; i < this.voices.length; i++){
this.voices[i].dispose();
this.voices[i] = null;
2014-08-25 17:26:26 +00:00
}
2014-12-08 16:03:20 +00:00
this.voices = null;
2014-08-25 17:26:26 +00:00
this._activeVoices = null;
this._freeVoices = null;
2015-02-02 18:30:36 +00:00
return this;
2014-08-25 17:26:26 +00:00
};
return Tone.PolySynth;
});