monophonic instruments extend a base class

This commit is contained in:
Yotam Mann 2014-09-03 19:05:09 -04:00
parent dc525e90ce
commit 71b475de60
5 changed files with 181 additions and 164 deletions

View file

@ -1,4 +1,4 @@
define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "Tone/signal/Signal", "Tone/signal/Multiply"],
define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "Tone/signal/Signal", "Tone/signal/Multiply", "Tone/instrument/Monophonic"],
function(Tone){
/**
@ -7,19 +7,14 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "To
* frequency ratio between the two voices and vibrato effect.
*
* @constructor
* @extends {Tone}
* @extends {Tone.Monophonic}
* @param {Object} options the options available for the synth
* see defaults below
*/
Tone.DuoSynth = function(options){
options = this.defaultArg(options, Tone.DuoSynth.defaults);
/**
* the output
* @type {GainNode}
*/
this.output = this.context.createGain();
Tone.Monophonic.call(this, options);
/**
* the first voice
@ -62,12 +57,6 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "To
*/
this._vibratoAmount = options.vibratoAmount;
/**
* the glide time between notes
* @type {number}
*/
this.portamento = this.toSeconds(options.portamento);
/**
* the frequency control
* @type {Tone.Signal}
@ -90,7 +79,7 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "To
this.voice1.connect(this.output);
};
Tone.extend(Tone.DuoSynth);
Tone.extend(Tone.DuoSynth, Tone.Monophonic);
/**
* @static
@ -100,7 +89,6 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "To
"vibratoAmount" : 0.5,
"vibratoRate" : 5,
"vibratoDelay" : 1,
"portamento" : 0.05,
"harmonicity" : 1.5,
"voice0" : {
"volume" : -10,
@ -139,47 +127,25 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "To
};
/**
* trigger the attack portion of the note
* start the attack portion of the envelopes
*
* @param {string|number} note the note frequency or note name
* @param {Tone.Time=} [time=now] the time the note will occur
* @param {Tone.Time=} duration if provided, a release will trigger
* after the duration.
* @param {Tone.Time=} [time=now] the time the attack should start
* @param {number=} velocity the velocity of the note (0-1)
*/
Tone.DuoSynth.prototype.triggerAttack = function(note, time, duration){
//the envelopes
this.voice0.envelope.triggerAttack(time);
this.voice1.envelope.triggerAttack(time);
Tone.DuoSynth.prototype.triggerEnvelopeAttack = function(time, velocity){
time = this.toSeconds(time);
this.voice0.envelope.triggerAttack(time, velocity);
this.voice1.envelope.triggerAttack(time, velocity);
this.voice0.filterEnvelope.triggerAttack(time);
this.voice1.filterEnvelope.triggerAttack(time);
//the port glide
time = this.toSeconds(time);
if (this.portamento > 0){
var currentNote = this.frequency.getValue();
this.frequency.setValueAtTime(currentNote, time);
this.frequency.exponentialRampToValueAtTime(note, time + this.portamento);
} else {
this.frequency.setValueAtTime(note, time);
}
//the vibrato
if (this._vibratoDelay > 0 && this._vibratoAmount > 0){
this._vibratoGain.gain.setValueAtTime(0, time);
//50 ms ramp to full vibrato
this._vibratoGain.gain.setValueAtTime(0, time + this._vibratoDelay - 0.05);
this._vibratoGain.gain.linearRampToValueAtTime(this._vibratoAmount, time + this._vibratoDelay);
}
if (!this.isUndef(duration)){
this.triggerRelease(this.toSeconds(time) + this.toSeconds(duration));
}
};
/**
* trigger the release portion of the note
* start the release portion of the envelopes
*
* @param {string|number} note the note frequency or note name
* @param {Tone.Time=} [time=now] the time the note will release
* @param {Tone.Time=} [time=now] the time the release should start
*/
Tone.DuoSynth.prototype.triggerRelease = function(time){
Tone.DuoSynth.prototype.triggerEnvelopeRelease = function(time){
this.voice0.triggerRelease(time);
this.voice1.triggerRelease(time);
};
@ -241,15 +207,16 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/component/LFO", "To
if (!this.isUndef(params.vibratoRate)) this.setVibratoRate(params.vibratoRate);
if (!this.isUndef(params.vibratoAmount)) this.setVibratoAmount(params.vibratoAmount);
if (!this.isUndef(params.vibratoDelay)) this.setVibratoDelay(params.vibratoDelay);
if (!this.isUndef(params.portamento)) this.setPortamento(params.portamento);
if (!this.isUndef(params.voice0)) this.voice0.set(params.voice0);
if (!this.isUndef(params.voice1)) this.voice1.set(params.voice1);
Tone.Monophonic.prototype.set.call(this, params);
};
/**
* clean up
*/
Tone.DuoSynth.dispose = function(){
Tone.Monophonic.prototype.dispose.call(this);
this.voice0.dispose();
this.voice1.dispose();
this.frequency.dispose();

View file

@ -1,4 +1,4 @@
define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "Tone/signal/Multiply"],
define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "Tone/signal/Multiply", "Tone/instrument/Monophonic"],
function(Tone){
/**
@ -6,19 +6,14 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "To
* carrier and the second is the modulator.
*
* @constructor
* @extends {Tone}
* @extends {Tone.Monophonic}
* @param {Object} options the options available for the synth
* see defaults below
*/
Tone.FMSynth = function(options){
options = this.defaultArg(options, Tone.FMSynth.defaults);
/**
* the output
* @type {GainNode}
*/
this.output = this.context.createGain();
Tone.Monophonic.call(this, options);
/**
* the first voice
@ -34,16 +29,6 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "To
this.modulator = new Tone.MonoSynth(options.modulator);
this.modulator.setVolume(-10);
/**
* scale the modulated frequency
*/
/**
* the glide time between notes
* @type {number}
*/
this.portamento = this.toSeconds(options.portamento);
/**
* the frequency control
* @type {Tone.Signal}
@ -84,14 +69,13 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "To
this.carrier.connect(this.output);
};
Tone.extend(Tone.FMSynth);
Tone.extend(Tone.FMSynth, Tone.Monophonic);
/**
* @static
* @type {Object}
*/
Tone.FMSynth.defaults = {
"portamento" : 0.0,
"harmonicity" : 3,
"modulationIndex" : 10,
"carrier" : {
@ -137,38 +121,25 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "To
/**
* trigger the attack portion of the note
*
* @param {string|number} note the note frequency or note name
* @param {Tone.Time=} [time=now] the time the note will occur
* @param {Tone.Time=} duration if provided, a release will trigger
* after the duration.
* @param {number=} velocity the velocity of the note
*/
Tone.FMSynth.prototype.triggerAttack = function(note, time, duration){
Tone.FMSynth.prototype.triggerEnvelopeAttack = function(time, velocity){
//the port glide
time = this.toSeconds(time);
//the envelopes
this.carrier.envelope.triggerAttack(time);
this.carrier.envelope.triggerAttack(time, velocity);
this.modulator.envelope.triggerAttack(time);
this.carrier.filterEnvelope.triggerAttack(time);
this.modulator.filterEnvelope.triggerAttack(time);
if (this.portamento > 0){
var currentNote = this.frequency.getValue();
this.frequency.setValueAtTime(currentNote, time);
this.frequency.exponentialRampToValueAtTime(note, time + this.portamento);
} else {
this.frequency.setValueAtTime(note, time);
}
if (!this.isUndef(duration)){
this.triggerRelease(time + this.toSeconds(duration));
}
};
/**
* trigger the release portion of the note
*
* @param {string|number} note the note frequency or note name
* @param {Tone.Time=} [time=now] the time the note will release
*/
Tone.FMSynth.prototype.triggerRelease = function(time){
Tone.FMSynth.prototype.triggerEnvelopeRelease = function(time){
this.carrier.triggerRelease(time);
this.modulator.triggerRelease(time);
};
@ -189,21 +160,6 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "To
this._modulationIndex.setValue(index);
};
/**
* the glide time between frequencies
* @param {Tone.Time} port
*/
Tone.FMSynth.prototype.setPortamento = function(port){
this.portamento = this.toSeconds(port);
};
/**
* set the volume of the instrument.
* borrowed from {@link Tone.Source}
* @function
*/
Tone.FMSynth.prototype.setVolume = Tone.Source.prototype.setVolume;
/**
* bulk setter
* @param {Object} param
@ -211,15 +167,16 @@ define(["Tone/core/Tone", "Tone/instrument/MonoSynth", "Tone/signal/Signal", "To
Tone.FMSynth.prototype.set = function(params){
if (!this.isUndef(params.harmonicity)) this.setHarmonicity(params.harmonicity);
if (!this.isUndef(params.modulationIndex)) this.setModulationIndex(params.modulationIndex);
if (!this.isUndef(params.portamento)) this.setPortamento(params.portamento);
if (!this.isUndef(params.carrier)) this.carrier.set(params.carrier);
if (!this.isUndef(params.modulator)) this.modulator.set(params.modulator);
Tone.Monophonic.prototype.set.call(this, params);
};
/**
* clean up
*/
Tone.FMSynth.dispose = function(){
Tone.Monophonic.prototype.dispose.call(this);
this.carrier.dispose();
this.modulator.dispose();
this.frequency.dispose();

View file

@ -1,15 +1,15 @@
define(["Tone/core/Tone", "Tone/component/Envelope", "Tone/source/Oscillator",
"Tone/signal/Signal", "Tone/component/Filter", "Tone/signal/Add", "Tone/source/Source"],
"Tone/signal/Signal", "Tone/component/Filter", "Tone/signal/Add", "Tone/instrument/Monophonic"],
function(Tone){
"use strict";
/**
* @class the MonoSynth is a single oscillator, monophonic synthesizer
* with vibrato, portamento, and a detuned unison
* with a filter, and two envelopes (on the filter and the amplitude)
*
* @constructor
* @extends {Tone}
* @extends {Tone.Monophonic}
* @param {Object} options the options available for the synth
* see defaults below
*/
@ -17,18 +17,7 @@ function(Tone){
//get the defaults
options = this.defaultArg(options, Tone.MonoSynth.defaults);
/**
* the output
* @type {GainNode}
*/
this.output = this.context.createGain();
/**
* the portamento (glide) time between notes in seconds
* @type {number}
*/
this.portamento = this.toSeconds(options.portamento);
Tone.Monophonic.call(this, options);
/**
* the first oscillator
@ -85,14 +74,12 @@ function(Tone){
this._amplitude.connect(this.output);
};
Tone.extend(Tone.MonoSynth);
Tone.extend(Tone.MonoSynth, Tone.Monophonic);
/**
* @static
*/
Tone.MonoSynth.defaults = {
/** @type {Tone.Time} the glide time between notes */
"portamento" : 0.05,
/** @type {string} the type of the first oscillator */
"oscType" : "square",
/** @type {Object} the filter properties */
@ -122,35 +109,20 @@ function(Tone){
/**
* start the attack portion of the envelope
* @param {string|number} note if a string, either a note name
* (i.e. C4, A#3) or a number in hertz
* @param {Tone.Time=} [time=now] the time the attack should start
* @param {Tone.Time=} duration if provided, a release will trigger
* after the duration.
* @param {number=} velocity the velocity of the note (0-1)
*/
Tone.MonoSynth.prototype.triggerAttack = function(note, time, duration){
Tone.MonoSynth.prototype.triggerEnvelopeAttack = function(time, velocity){
//the envelopes
this.envelope.triggerAttack(time);
this.envelope.triggerAttack(time, velocity);
this.filterEnvelope.triggerAttack(time);
//the port glide
if (this.portamento > 0){
var currentNote = this.frequency.getValue();
time = this.toSeconds(time);
this.frequency.setValueAtTime(currentNote, time);
this.frequency.exponentialRampToValueAtTime(note, time + this.portamento);
} else {
this.frequency.setValueAtTime(note, time);
}
if (!this.isUndef(duration)){
this.triggerRelease(this.toSeconds(time) + this.toSeconds(duration));
}
};
/**
* start the release portion of the envelope
* @param {Tone.Time=} [time=now] the time the release should start
*/
Tone.MonoSynth.prototype.triggerRelease = function(time){
Tone.MonoSynth.prototype.triggerEnvelopeRelease = function(time){
this.envelope.triggerRelease(time);
this.filterEnvelope.triggerRelease(time);
};
@ -163,21 +135,6 @@ function(Tone){
this.oscillator.setType(type);
};
/**
* set the glide time between notes
* @param {Tone.Time} port glide time
*/
Tone.MonoSynth.prototype.setPortamento = function(port){
this.portamento = this.toSeconds(port);
};
/**
* set the volume of the instrument.
* borrowed from {@link Tone.Source}
* @function
*/
Tone.MonoSynth.prototype.setVolume = Tone.Source.prototype.setVolume;
/**
* set the members at once
* @param {Object} params all of the parameters as an object.
@ -186,28 +143,25 @@ function(Tone){
*/
Tone.MonoSynth.prototype.set = function(params){
if (!this.isUndef(params.detune)) this.detune.setValue(params.detune);
if (!this.isUndef(params.volume)) this.setVolume(params.volume);
if (!this.isUndef(params.portamento)) this.setPortamento(params.portamento);
if (!this.isUndef(params.oscType)) this.setOscType(params.oscType);
if (!this.isUndef(params.filterEnvelope)) this.filterEnvelope.set(params.filterEnvelope);
if (!this.isUndef(params.envelope)) this.envelope.set(params.envelope);
if (!this.isUndef(params.filter)) this.filter.set(params.filter);
Tone.Monophonic.prototype.set.call(this, params);
};
/**
* clean up
*/
Tone.MonoSynth.prototype.dispose = function(){
Tone.prototype.dispose.call(this);
Tone.Monophonic.prototype.dispose.call(this);
this.oscillator.dispose();
this.envelope.dispose();
this.filterEnvelope.dispose();
this.frequency.dispose();
this.filter.dispose();
this.detune.dispose();
this._unison.dispose();
this.oscillator = null;
this.frequency = null;
this.filterEnvelope = null;
this.envelope = null;
this.filter = null;

View file

@ -0,0 +1,139 @@
define(["Tone/core/Tone", "Tone/source/Source", "Tone/signal/Signal"], function(Tone){
"use strict";
/**
* @class this is a base class for monophonic instruments.
* it defines their interfaces
*
* @constructor
* @abstract
* @extends {Tone}
*/
Tone.Monophonic = function(options){
//get the defaults
options = this.defaultArg(options, Tone.Monophonic.defaults);
/**
* the instrument's output
* @type {GainNode}
*/
this.output = this.context.createGain();
/**
* the portamento time
* @type {number}
*/
this.portamento = options.portamento;
};
Tone.extend(Tone.Monophonic);
/**
* @static
* @const
* @type {Object}
*/
Tone.Monophonic.defaults = {
"portamento" : 0
};
/**
* trigger the attack. start the note, at the time with the velocity
*
* @param {string|string} note the note
* @param {Tone.Time=} [time=now] the time, if not given is now
* @param {number=} [velocity=1] velocity defaults to 1
*/
Tone.Monophonic.prototype.triggerAttack = function(note, time, velocity) {
time = this.toSeconds(time);
this.triggerEnvelopeAttack(time, velocity);
this.setNote(note, time);
};
/**
* trigger the attack and release after the specified duration
*
* @param {number|string} note the note as a number or a string note name
* @param {Tone.Time} duration the duration of the note
* @param {Tone.Time=} time if no time is given, defaults to now
* @param {number=} velocity the velocity of the attack (0-1)
*/
Tone.Monophonic.prototype.triggerAttackRelease = function(note, duration, time, velocity) {
time = this.toSeconds(time);
this.triggerAttack(note, time, velocity);
this.triggerRelease(time + this.toSeconds(duration));
};
/**
* trigger the release portion of the envelope
* @param {Tone.Time=} [time=now] if no time is given, the release happens immediatly
*/
Tone.Monophonic.prototype.triggerRelease = function(time){
this.triggerEnvelopeRelease(time);
};
/**
* override this method with the actual method
* @abstract
* @param {Tone.Time=} [time=now] the time the attack should happen
* @param {number=} [velocity=1] the velocity of the envelope
*/
Tone.Monophonic.prototype.triggerEnvelopeAttack = function() {};
/**
* override this method with the actual method
* @abstract
* @param {Tone.Time=} [time=now] the time the attack should happen
* @param {number=} [velocity=1] the velocity of the envelope
*/
Tone.Monophonic.prototype.triggerEnvelopeRelease = function() {};
/**
* set the note to happen at a specific time
* @param {[type]} note [description]
*/
Tone.Monophonic.prototype.setNote = function(note, time){
time = this.toSeconds(time);
if (this.portamento > 0){
var currentNote = this.frequency.getValue();
this.frequency.setValueAtTime(currentNote, time);
this.frequency.exponentialRampToValueAtTime(note, time + this.portamento);
} else {
this.frequency.setValueAtTime(note, time);
}
};
/**
* set the glide time between notes
* @param {Tone.Time} port glide time
*/
Tone.Monophonic.prototype.setPortamento = function(port){
this.portamento = this.toSeconds(port);
};
/**
* set volume method borrowed form {@link Tone.Source}
* @function
*/
Tone.Monophonic.prototype.setVolume = Tone.Source.prototype.setVolume;
/**
* bulk setter
* @param {Object} params the params
*/
Tone.Monophonic.prototype.set = function(params) {
if (!this.isUndef(params.volume)) this.setVolume(params.volume);
if (!this.isUndef(params.portamento)) this.setPortamento(params.portamento);
};
/**
* clean up
*/
Tone.Monophonic.prototype.dispose = function(){
Tone.prototype.dispose.call(this);
};
return Tone.Monophonic;
});

View file

@ -115,8 +115,8 @@ define(["Tone/core/Tone", "Tone/instrument/FMSynth"], function(Tone){
},
"ScratchAttack" : {
"portamento" : 0,
"harmonicity" : 0.5,
"modulationIndex" : 31,
"harmonicity" : 10,
"modulationIndex" : 50,
"carrier" : {
"volume" : 0,
"portamento" : 0,
@ -129,7 +129,7 @@ define(["Tone/core/Tone", "Tone/instrument/FMSynth"], function(Tone){
"envelope" : {
"attack" : 0.08,
"decay" : 0.3,
"sustain" : 0.35,
"sustain" : 0,
"release" : 1.2
},
"filterEnvelope" : {
@ -151,7 +151,7 @@ define(["Tone/core/Tone", "Tone/instrument/FMSynth"], function(Tone){
"rolloff" : -48
},
"envelope" : {
"attack" : 0.2,
"attack" : 0.1,
"decay" : 0.2,
"sustain" : 0.3,
"release" : 0.01