Tone.js/Tone/source/OmniOscillator.js

237 lines
6.4 KiB
JavaScript
Raw Normal View History

2015-02-02 01:38:06 +00:00
define(["Tone/core/Tone", "Tone/source/Source", "Tone/source/Oscillator",
"Tone/source/PulseOscillator", "Tone/source/PWMOscillator"],
2014-09-30 03:44:59 +00:00
function(Tone){
"use strict";
/**
* @class Tone.OmniOscillator aggregates Tone.Oscillator, Tone.PulseOscillator,
* and Tone.PWMOscillator into one class, allowing it to have the
* types: sine, square, triangle, sawtooth, pulse or pwm. Additionally,
* OmniOscillator is capable of setting the first x number of partials
* of the oscillator. For example: "sine4" would set be the first 4
* partials of the sine wave and "triangle8" would set the first
* 8 partials of the triangle wave.
2014-09-30 03:44:59 +00:00
*
2014-10-03 20:07:30 +00:00
* @extends {Tone.Oscillator}
2014-09-30 03:44:59 +00:00
* @constructor
2015-06-20 19:50:57 +00:00
* @param {Frequency} frequency The initial frequency of the oscillator.
* @param {string} type The type of the oscillator.
2015-02-27 16:19:45 +00:00
* @example
* var omniOsc = new Tone.OmniOscillator("C#4", "pwm");
2014-09-30 03:44:59 +00:00
*/
Tone.OmniOscillator = function(){
var options = this.optionsObject(arguments, ["frequency", "type"], Tone.OmniOscillator.defaults);
2015-02-02 01:38:06 +00:00
Tone.Source.call(this, options);
2014-09-30 03:44:59 +00:00
/**
2015-06-20 19:50:57 +00:00
* The frequency control.
2015-06-13 23:50:39 +00:00
* @type {Frequency}
* @signal
2014-09-30 03:44:59 +00:00
*/
this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
2014-09-30 03:44:59 +00:00
/**
2015-06-20 19:50:57 +00:00
* The detune control
2015-06-13 23:50:39 +00:00
* @type {Cents}
* @signal
2014-09-30 03:44:59 +00:00
*/
this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
2014-09-30 03:44:59 +00:00
/**
* the type of the oscillator source
* @type {string}
* @private
*/
this._sourceType = undefined;
/**
* the oscillator
* @type {Tone.Oscillator|Tone.PWMOscillator|Tone.PulseOscillator}
* @private
*/
this._oscillator = null;
//set the oscillator
this.type = options.type;
2015-08-21 21:04:29 +00:00
this.phase = options.phase;
2015-04-05 18:53:27 +00:00
this._readOnly(["frequency", "detune"]);
2014-09-30 03:44:59 +00:00
};
2014-10-03 20:07:30 +00:00
Tone.extend(Tone.OmniOscillator, Tone.Oscillator);
2014-09-30 03:44:59 +00:00
/**
* default values
* @static
* @type {Object}
* @const
*/
Tone.OmniOscillator.defaults = {
"frequency" : 440,
"detune" : 0,
"type" : "sine",
2015-08-21 21:04:29 +00:00
"phase" : 0,
2014-09-30 03:44:59 +00:00
"width" : 0.4, //only applies if the oscillator is set to "pulse",
"modulationFrequency" : 0.4, //only applies if the oscillator is set to "pwm",
};
2015-02-27 16:19:45 +00:00
/**
* @enum {string}
* @private
*/
var OmniOscType = {
PulseOscillator : "PulseOscillator",
PWMOscillator : "PWMOscillator",
Oscillator : "Oscillator"
};
2014-09-30 03:44:59 +00:00
/**
* start the oscillator
2015-06-14 00:20:36 +00:00
* @param {Time} [time=now] the time to start the oscillator
2015-02-02 02:32:07 +00:00
* @private
2014-09-30 03:44:59 +00:00
*/
2015-02-02 02:32:07 +00:00
Tone.OmniOscillator.prototype._start = function(time){
this._oscillator.start(time);
2014-09-30 03:44:59 +00:00
};
/**
* start the oscillator
2015-06-14 00:20:36 +00:00
* @param {Time} [time=now] the time to start the oscillator
2015-02-02 02:32:07 +00:00
* @private
2014-09-30 03:44:59 +00:00
*/
2015-02-02 02:32:07 +00:00
Tone.OmniOscillator.prototype._stop = function(time){
this._oscillator.stop(time);
2014-09-30 03:44:59 +00:00
};
/**
* The type of the oscillator. sine, square, triangle, sawtooth, pwm, or pulse.
* @memberOf Tone.OmniOscillator#
* @type {string}
* @name type
2014-09-30 03:44:59 +00:00
*/
Object.defineProperty(Tone.OmniOscillator.prototype, "type", {
get : function(){
return this._oscillator.type;
},
set : function(type){
2015-05-21 17:51:40 +00:00
if (type.indexOf("sine") === 0 || type.indexOf("square") === 0 ||
type.indexOf("triangle") === 0 || type.indexOf("sawtooth") === 0){
if (this._sourceType !== OmniOscType.Oscillator){
this._sourceType = OmniOscType.Oscillator;
this._createNewOscillator(Tone.Oscillator);
}
this._oscillator.type = type;
} else if (type === "pwm"){
if (this._sourceType !== OmniOscType.PWMOscillator){
this._sourceType = OmniOscType.PWMOscillator;
this._createNewOscillator(Tone.PWMOscillator);
}
} else if (type === "pulse"){
if (this._sourceType !== OmniOscType.PulseOscillator){
this._sourceType = OmniOscType.PulseOscillator;
this._createNewOscillator(Tone.PulseOscillator);
}
} else {
2015-08-16 19:16:26 +00:00
throw new Error("Tone.OmniOscillator does not support type "+type);
2014-09-30 03:44:59 +00:00
}
}
});
2014-10-01 02:48:21 +00:00
2014-09-30 03:44:59 +00:00
/**
* connect the oscillator to the frequency and detune signals
* @private
*/
2014-10-03 05:00:37 +00:00
Tone.OmniOscillator.prototype._createNewOscillator = function(OscillatorConstructor){
//short delay to avoid clicks on the change
2015-07-21 15:22:36 +00:00
var now = this.now() + this.blockTime;
2014-10-03 05:00:37 +00:00
if (this._oscillator !== null){
var oldOsc = this._oscillator;
oldOsc.stop(now);
2015-08-16 19:16:26 +00:00
//dispose the old one
setTimeout(function(){
2014-10-03 05:00:37 +00:00
oldOsc.dispose();
oldOsc = null;
2015-08-16 19:16:26 +00:00
}, this.blockTime * 1000);
2014-10-03 05:00:37 +00:00
}
this._oscillator = new OscillatorConstructor();
2014-09-30 03:44:59 +00:00
this.frequency.connect(this._oscillator.frequency);
this.detune.connect(this._oscillator.detune);
this._oscillator.connect(this.output);
if (this.state === Tone.State.Started){
this._oscillator.start(now);
2014-09-30 03:44:59 +00:00
}
};
/**
2015-06-14 02:03:06 +00:00
* The phase of the oscillator in degrees.
* @memberOf Tone.OmniOscillator#
2015-06-14 00:20:36 +00:00
* @type {Degrees}
* @name phase
*/
Object.defineProperty(Tone.OmniOscillator.prototype, "phase", {
get : function(){
return this._oscillator.phase;
},
set : function(phase){
this._oscillator.phase = phase;
2014-09-30 03:44:59 +00:00
}
});
2014-09-30 03:44:59 +00:00
/**
2015-02-27 16:19:45 +00:00
* The width of the oscillator (only if the oscillator is set to pulse)
* @memberOf Tone.OmniOscillator#
2015-06-13 23:50:39 +00:00
* @type {NormalRange}
* @signal
* @name width
2015-02-27 16:19:45 +00:00
* @example
* var omniOsc = new Tone.OmniOscillator(440, "pulse");
* //can access the width attribute only if type === "pulse"
* omniOsc.width.value = 0.2;
2014-09-30 03:44:59 +00:00
*/
Object.defineProperty(Tone.OmniOscillator.prototype, "width", {
get : function(){
if (this._sourceType === OmniOscType.PulseOscillator){
return this._oscillator.width;
}
2014-09-30 03:44:59 +00:00
}
});
2014-09-30 03:44:59 +00:00
/**
* The modulationFrequency Signal of the oscillator
2015-02-27 16:19:45 +00:00
* (only if the oscillator type is set to pwm).
* @memberOf Tone.OmniOscillator#
2015-06-13 23:50:39 +00:00
* @type {Frequency}
* @signal
2015-02-27 16:19:45 +00:00
* @name modulationFrequency
* @example
* var omniOsc = new Tone.OmniOscillator(440, "pwm");
* //can access the modulationFrequency attribute only if type === "pwm"
* omniOsc.modulationFrequency.value = 0.2;
2014-09-30 03:44:59 +00:00
*/
Object.defineProperty(Tone.OmniOscillator.prototype, "modulationFrequency", {
get : function(){
if (this._sourceType === OmniOscType.PWMOscillator){
return this._oscillator.modulationFrequency;
}
}
});
2014-09-30 03:44:59 +00:00
/**
2015-06-20 19:50:57 +00:00
* Clean up.
* @return {Tone.OmniOscillator} this
2014-09-30 03:44:59 +00:00
*/
2015-02-02 03:05:24 +00:00
Tone.OmniOscillator.prototype.dispose = function(){
Tone.Source.prototype.dispose.call(this);
2015-04-05 18:53:27 +00:00
this._writable(["frequency", "detune"]);
2014-09-30 03:44:59 +00:00
this.detune.dispose();
this.detune = null;
2014-12-04 02:38:24 +00:00
this.frequency.dispose();
this.frequency = null;
2014-12-04 02:38:24 +00:00
this._oscillator.dispose();
this._oscillator = null;
2014-09-30 03:44:59 +00:00
this._sourceType = null;
return this;
2014-09-30 03:44:59 +00:00
};
return Tone.OmniOscillator;
});