2019-01-27 18:05:20 +00:00
|
|
|
import Tone from "../core/Tone";
|
|
|
|
import "../signal/Signal";
|
|
|
|
import "../source/Source";
|
|
|
|
import "../core/Transport";
|
|
|
|
import "../source/OscillatorNode";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class Tone.Oscillator supports a number of features including
|
|
|
|
* phase rotation, multiple oscillator types (see Tone.Oscillator.type),
|
|
|
|
* and Transport syncing (see Tone.Oscillator.syncFrequency).
|
|
|
|
*
|
|
|
|
* @constructor
|
|
|
|
* @extends {Tone.Source}
|
|
|
|
* @param {Frequency} [frequency] Starting frequency
|
|
|
|
* @param {string} [type] The oscillator type. Read more about type below.
|
|
|
|
* @example
|
|
|
|
* //make and start a 440hz sine tone
|
|
|
|
* var osc = new Tone.Oscillator(440, "sine").toMaster().start();
|
|
|
|
*/
|
|
|
|
Tone.Oscillator = function(){
|
|
|
|
|
|
|
|
var options = Tone.defaults(arguments, ["frequency", "type"], Tone.Oscillator);
|
|
|
|
Tone.Source.call(this, options);
|
2014-08-29 21:14:41 +00:00
|
|
|
|
2014-06-15 21:36:52 +00:00
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* the main oscillator
|
|
|
|
* @type {OscillatorNode}
|
|
|
|
* @private
|
2014-06-15 21:36:52 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this._oscillator = null;
|
2014-04-05 22:05:42 +00:00
|
|
|
|
2014-08-29 21:14:41 +00:00
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* The frequency control.
|
|
|
|
* @type {Frequency}
|
|
|
|
* @signal
|
2014-08-29 21:14:41 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this.frequency = new Tone.Signal(options.frequency, Tone.Type.Frequency);
|
2014-08-29 21:14:41 +00:00
|
|
|
|
2015-08-31 20:42:27 +00:00
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* The detune control signal.
|
|
|
|
* @type {Cents}
|
|
|
|
* @signal
|
2015-08-31 20:42:27 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this.detune = new Tone.Signal(options.detune, Tone.Type.Cents);
|
2015-08-31 20:42:27 +00:00
|
|
|
|
2014-06-15 21:36:52 +00:00
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* the periodic wave
|
|
|
|
* @type {PeriodicWave}
|
2015-02-02 02:32:07 +00:00
|
|
|
* @private
|
2014-06-15 21:36:52 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this._wave = null;
|
2014-06-19 05:40:16 +00:00
|
|
|
|
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* The partials of the oscillator
|
|
|
|
* @type {Array}
|
2015-02-27 16:19:45 +00:00
|
|
|
* @private
|
2014-06-15 21:36:52 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this._partials = options.partials;
|
2014-04-05 22:05:42 +00:00
|
|
|
|
2015-02-02 01:02:13 +00:00
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* The number of partials to limit or extend the periodic wave by
|
|
|
|
* @type {Number}
|
|
|
|
* @private
|
2015-02-02 01:02:13 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this._partialCount = options.partialCount;
|
2015-02-02 01:02:13 +00:00
|
|
|
|
2014-06-15 21:36:52 +00:00
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* the phase of the oscillator
|
|
|
|
* between 0 - 360
|
|
|
|
* @type {number}
|
|
|
|
* @private
|
2014-06-15 21:36:52 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this._phase = options.phase;
|
2015-02-01 20:48:20 +00:00
|
|
|
|
2019-01-08 05:13:48 +00:00
|
|
|
/**
|
2019-01-27 18:05:20 +00:00
|
|
|
* the type of the oscillator
|
|
|
|
* @type {string}
|
|
|
|
* @private
|
2019-01-08 05:13:48 +00:00
|
|
|
*/
|
2019-01-27 18:05:20 +00:00
|
|
|
this._type = options.type;
|
|
|
|
|
|
|
|
//setup
|
|
|
|
if (options.partialCount && options.type !== Tone.Oscillator.Type.Custom){
|
|
|
|
this._type = this.baseType + options.partialCount.toString();
|
|
|
|
}
|
|
|
|
this.phase = this._phase;
|
|
|
|
this._readOnly(["frequency", "detune"]);
|
|
|
|
};
|
|
|
|
|
|
|
|
Tone.extend(Tone.Oscillator, Tone.Source);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* the default parameters
|
|
|
|
* @type {Object}
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.defaults = {
|
|
|
|
"type" : "sine",
|
|
|
|
"frequency" : 440,
|
|
|
|
"detune" : 0,
|
|
|
|
"phase" : 0,
|
|
|
|
"partials" : [],
|
|
|
|
"partialCount" : 0
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The Oscillator types
|
|
|
|
* @enum {String}
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.Type = {
|
|
|
|
Sine : "sine",
|
|
|
|
Triangle : "triangle",
|
|
|
|
Sawtooth : "sawtooth",
|
|
|
|
Square : "square",
|
|
|
|
Custom : "custom"
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* start the oscillator
|
|
|
|
* @param {Time} [time=now]
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype._start = function(time){
|
|
|
|
this.log("start", time);
|
|
|
|
//new oscillator with previous values
|
2019-03-08 17:17:20 +00:00
|
|
|
var oscillator = new Tone.OscillatorNode();
|
|
|
|
this._oscillator = oscillator;
|
|
|
|
if (this._wave){
|
|
|
|
this._oscillator.setPeriodicWave(this._wave);
|
|
|
|
} else {
|
|
|
|
this._oscillator.type = this._type;
|
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
//connect the control signal to the oscillator frequency & detune
|
|
|
|
this._oscillator.connect(this.output);
|
|
|
|
this.frequency.connect(this._oscillator.frequency);
|
|
|
|
this.detune.connect(this._oscillator.detune);
|
2019-03-08 17:17:20 +00:00
|
|
|
|
|
|
|
//disconnect onended
|
|
|
|
oscillator.onended = function(){
|
|
|
|
//defer the callback for the offline context rendering
|
|
|
|
setTimeout(function(){
|
2019-06-10 19:42:45 +00:00
|
|
|
if (this.frequency){
|
|
|
|
this.frequency.disconnect(oscillator.frequency);
|
|
|
|
}
|
|
|
|
if (this.detune){
|
|
|
|
this.detune.disconnect(oscillator.detune);
|
|
|
|
}
|
2019-03-08 17:17:20 +00:00
|
|
|
}.bind(this), 100);
|
|
|
|
}.bind(this);
|
|
|
|
|
2019-01-27 18:05:20 +00:00
|
|
|
//start the oscillator
|
|
|
|
time = this.toSeconds(time);
|
|
|
|
this._oscillator.start(time);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* stop the oscillator
|
|
|
|
* @private
|
|
|
|
* @param {Time} [time=now] (optional) timing parameter
|
|
|
|
* @returns {Tone.Oscillator} this
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype._stop = function(time){
|
|
|
|
this.log("stop", time);
|
|
|
|
if (this._oscillator){
|
|
|
|
time = this.toSeconds(time);
|
|
|
|
this._oscillator.stop(time);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Restart the oscillator. Does not stop the oscillator, but instead
|
|
|
|
* just cancels any scheduled 'stop' from being invoked.
|
|
|
|
* @param {Time=} time
|
|
|
|
* @return {Tone.Oscillator} this
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype.restart = function(time){
|
|
|
|
if (this._oscillator){
|
|
|
|
this._oscillator.cancelStop();
|
|
|
|
}
|
|
|
|
this._state.cancel(this.toSeconds(time));
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sync the signal to the Transport's bpm. Any changes to the transports bpm,
|
|
|
|
* will also affect the oscillators frequency.
|
|
|
|
* @returns {Tone.Oscillator} this
|
|
|
|
* @example
|
|
|
|
* Tone.Transport.bpm.value = 120;
|
|
|
|
* osc.frequency.value = 440;
|
|
|
|
* //the ration between the bpm and the frequency will be maintained
|
|
|
|
* osc.syncFrequency();
|
|
|
|
* Tone.Transport.bpm.value = 240;
|
|
|
|
* // the frequency of the oscillator is doubled to 880
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype.syncFrequency = function(){
|
|
|
|
Tone.Transport.syncSignal(this.frequency);
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unsync the oscillator's frequency from the Transport.
|
|
|
|
* See Tone.Oscillator.syncFrequency
|
|
|
|
* @returns {Tone.Oscillator} this
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype.unsyncFrequency = function(){
|
|
|
|
Tone.Transport.unsyncSignal(this.frequency);
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The type of the oscillator: either sine, square, triangle, or sawtooth. Also 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.
|
|
|
|
* <br><br>
|
|
|
|
* Uses PeriodicWave internally even for native types so that it can set the phase.
|
|
|
|
* PeriodicWave equations are from the
|
|
|
|
* [Webkit Web Audio implementation](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/modules/webaudio/PeriodicWave.cpp&sq=package:chromium).
|
|
|
|
*
|
|
|
|
* @memberOf Tone.Oscillator#
|
|
|
|
* @type {string}
|
|
|
|
* @name type
|
|
|
|
* @example
|
|
|
|
* //set it to a square wave
|
|
|
|
* osc.type = "square";
|
|
|
|
* @example
|
|
|
|
* //set the first 6 partials of a sawtooth wave
|
|
|
|
* osc.type = "sawtooth6";
|
|
|
|
*/
|
|
|
|
Object.defineProperty(Tone.Oscillator.prototype, "type", {
|
|
|
|
get : function(){
|
|
|
|
return this._type;
|
|
|
|
},
|
|
|
|
set : function(type){
|
2019-03-08 17:17:20 +00:00
|
|
|
var isBasicType = [Tone.Oscillator.Type.Sine, Tone.Oscillator.Type.Square, Tone.Oscillator.Type.Triangle, Tone.Oscillator.Type.Sawtooth].includes(type);
|
|
|
|
if (this._phase === 0 && isBasicType){
|
|
|
|
this._wave = null;
|
|
|
|
this._partialCount = 0;
|
|
|
|
//just go with the basic approach
|
|
|
|
if (this._oscillator !== null){
|
2019-03-14 14:29:51 +00:00
|
|
|
this._oscillator.type = type;
|
2019-03-08 17:17:20 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
var coefs = this._getRealImaginary(type, this._phase);
|
|
|
|
var periodicWave = this.context.createPeriodicWave(coefs[0], coefs[1]);
|
|
|
|
this._wave = periodicWave;
|
|
|
|
if (this._oscillator !== null){
|
|
|
|
this._oscillator.setPeriodicWave(this._wave);
|
|
|
|
}
|
2019-01-08 05:13:48 +00:00
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
this._type = type;
|
|
|
|
}
|
|
|
|
});
|
2019-01-08 05:13:48 +00:00
|
|
|
|
2019-01-27 18:05:20 +00:00
|
|
|
/**
|
|
|
|
* The oscillator type without the partialsCount appended to the end
|
|
|
|
* @memberOf Tone.Oscillator#
|
|
|
|
* @type {string}
|
|
|
|
* @name baseType
|
|
|
|
* @example
|
|
|
|
* osc.type = 'sine2'
|
|
|
|
* osc.baseType //'sine'
|
|
|
|
* osc.partialCount = 2
|
|
|
|
*/
|
|
|
|
Object.defineProperty(Tone.Oscillator.prototype, "baseType", {
|
|
|
|
get : function(){
|
|
|
|
return this._type.replace(this.partialCount, "");
|
|
|
|
},
|
|
|
|
set : function(baseType){
|
|
|
|
if (this.partialCount && this._type !== Tone.Oscillator.Type.Custom && baseType !== Tone.Oscillator.Type.Custom){
|
|
|
|
this.type = baseType + this.partialCount;
|
|
|
|
} else {
|
|
|
|
this.type = baseType;
|
2018-12-09 23:45:01 +00:00
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
}
|
|
|
|
});
|
2018-12-09 23:45:01 +00:00
|
|
|
|
2019-01-27 18:05:20 +00:00
|
|
|
/**
|
|
|
|
* 'partialCount' offers an alternative way to set the number of used partials.
|
|
|
|
* When partialCount is 0, the maximum number of partials are used when representing
|
|
|
|
* the waveform using the periodicWave. When 'partials' is set, this value is
|
|
|
|
* not settable, but equals the length of the partials array.
|
|
|
|
* @example
|
|
|
|
* osc.type = 'sine'
|
|
|
|
* osc.partialCount = 3
|
|
|
|
* //is equivalent to
|
|
|
|
* osc.type = 'sine3'
|
|
|
|
* @memberOf Tone.Oscillator#
|
|
|
|
* @type {Number}
|
|
|
|
* @name partialCount
|
|
|
|
*/
|
|
|
|
Object.defineProperty(Tone.Oscillator.prototype, "partialCount", {
|
|
|
|
get : function(){
|
|
|
|
return this._partialCount;
|
|
|
|
},
|
|
|
|
set : function(p){
|
|
|
|
var type = this._type;
|
|
|
|
var partial = /^(sine|triangle|square|sawtooth)(\d+)$/.exec(this._type);
|
|
|
|
if (partial){
|
|
|
|
type = partial[1];
|
2018-12-28 21:00:03 +00:00
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
if (this._type !== Tone.Oscillator.Type.Custom){
|
|
|
|
if (p === 0){
|
|
|
|
this.type = type;
|
2018-12-09 23:45:01 +00:00
|
|
|
} else {
|
2019-01-27 18:05:20 +00:00
|
|
|
this.type = type + p.toString();
|
2015-08-31 20:42:27 +00:00
|
|
|
}
|
2015-08-28 01:32:09 +00:00
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
}
|
|
|
|
});
|
2015-08-28 01:32:09 +00:00
|
|
|
|
2019-01-27 18:05:20 +00:00
|
|
|
/**
|
|
|
|
* Get the object's attributes. Given no arguments get
|
|
|
|
* will return all available object properties and their corresponding
|
|
|
|
* values.
|
|
|
|
* @memberOf Tone.Oscillator#
|
|
|
|
* @returns {Object}
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype.get = function(){
|
2019-05-13 13:29:41 +00:00
|
|
|
var values = Tone.prototype.get.apply(this, arguments);
|
2019-01-27 18:05:20 +00:00
|
|
|
if (values.type !== Tone.Oscillator.Type.Custom){
|
|
|
|
delete values.partials;
|
|
|
|
}
|
|
|
|
return values;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the real and imaginary components based
|
|
|
|
* on the oscillator type.
|
|
|
|
* @returns {Array} [real, imaginary]
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype._getRealImaginary = function(type, phase){
|
|
|
|
var fftSize = 4096;
|
|
|
|
var periodicWaveSize = fftSize / 2;
|
|
|
|
|
|
|
|
var real = new Float32Array(periodicWaveSize);
|
|
|
|
var imag = new Float32Array(periodicWaveSize);
|
|
|
|
|
|
|
|
var partialCount = 1;
|
|
|
|
if (type === Tone.Oscillator.Type.Custom){
|
|
|
|
partialCount = this._partials.length + 1;
|
|
|
|
this._partialCount = this._partials.length;
|
|
|
|
periodicWaveSize = partialCount;
|
|
|
|
} else {
|
|
|
|
var partial = /^(sine|triangle|square|sawtooth)(\d+)$/.exec(type);
|
|
|
|
if (partial){
|
|
|
|
partialCount = parseInt(partial[2]) + 1;
|
|
|
|
this._partialCount = parseInt(partial[2]);
|
|
|
|
type = partial[1];
|
|
|
|
partialCount = Math.max(partialCount, 2);
|
|
|
|
periodicWaveSize = partialCount;
|
|
|
|
} else {
|
|
|
|
this._partialCount = 0;
|
2015-08-28 01:32:09 +00:00
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
this._partials = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (var n = 1; n < periodicWaveSize; ++n){
|
|
|
|
var piFactor = 2 / (n * Math.PI);
|
|
|
|
var b;
|
|
|
|
switch (type){
|
|
|
|
case Tone.Oscillator.Type.Sine:
|
|
|
|
b = (n <= partialCount) ? 1 : 0;
|
|
|
|
this._partials[n-1] = b;
|
|
|
|
break;
|
|
|
|
case Tone.Oscillator.Type.Square:
|
|
|
|
b = (n & 1) ? 2 * piFactor : 0;
|
|
|
|
this._partials[n-1] = b;
|
|
|
|
break;
|
|
|
|
case Tone.Oscillator.Type.Sawtooth:
|
|
|
|
b = piFactor * ((n & 1) ? 1 : -1);
|
|
|
|
this._partials[n-1] = b;
|
|
|
|
break;
|
|
|
|
case Tone.Oscillator.Type.Triangle:
|
|
|
|
if (n & 1){
|
|
|
|
b = 2 * (piFactor * piFactor) * ((((n - 1) >> 1) & 1) ? -1 : 1);
|
|
|
|
} else {
|
|
|
|
b = 0;
|
|
|
|
}
|
|
|
|
this._partials[n-1] = b;
|
|
|
|
break;
|
|
|
|
case Tone.Oscillator.Type.Custom:
|
|
|
|
b = this._partials[n - 1];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new TypeError("Tone.Oscillator: invalid type: "+type);
|
2015-08-28 01:32:09 +00:00
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
if (b !== 0){
|
|
|
|
real[n] = -b * Math.sin(phase * n);
|
|
|
|
imag[n] = b * Math.cos(phase * n);
|
|
|
|
} else {
|
|
|
|
real[n] = 0;
|
|
|
|
imag[n] = 0;
|
2015-08-28 01:32:09 +00:00
|
|
|
}
|
2019-01-27 18:05:20 +00:00
|
|
|
}
|
|
|
|
return [real, imag];
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute the inverse FFT for a given phase.
|
|
|
|
* @param {Float32Array} real
|
|
|
|
* @param {Float32Array} imag
|
|
|
|
* @param {NormalRange} phase
|
|
|
|
* @return {AudioRange}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype._inverseFFT = function(real, imag, phase){
|
|
|
|
var sum = 0;
|
|
|
|
var len = real.length;
|
|
|
|
for (var i = 0; i < len; i++){
|
|
|
|
sum += real[i] * Math.cos(i * phase) + imag[i] * Math.sin(i * phase);
|
|
|
|
}
|
|
|
|
return sum;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the initial value of the oscillator.
|
|
|
|
* @return {AudioRange}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype._getInitialValue = function(){
|
|
|
|
var coefs = this._getRealImaginary(this._type, 0);
|
|
|
|
var real = coefs[0];
|
|
|
|
var imag = coefs[1];
|
|
|
|
var maxValue = 0;
|
|
|
|
var twoPi = Math.PI * 2;
|
|
|
|
//check for peaks in 8 places
|
|
|
|
for (var i = 0; i < 8; i++){
|
|
|
|
maxValue = Math.max(this._inverseFFT(real, imag, (i / 8) * twoPi), maxValue);
|
|
|
|
}
|
|
|
|
return -this._inverseFFT(real, imag, this._phase) / maxValue;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The partials of the waveform. A partial represents
|
|
|
|
* the amplitude at a harmonic. The first harmonic is the
|
|
|
|
* fundamental frequency, the second is the octave and so on
|
|
|
|
* following the harmonic series.
|
|
|
|
* Setting this value will automatically set the type to "custom".
|
|
|
|
* The value is an empty array when the type is not "custom".
|
|
|
|
* @memberOf Tone.Oscillator#
|
|
|
|
* @type {Array}
|
|
|
|
* @name partials
|
|
|
|
* @example
|
|
|
|
* osc.partials = [1, 0.2, 0.01];
|
|
|
|
*/
|
|
|
|
Object.defineProperty(Tone.Oscillator.prototype, "partials", {
|
|
|
|
get : function(){
|
|
|
|
return this._partials;
|
|
|
|
},
|
|
|
|
set : function(partials){
|
|
|
|
this._partials = partials;
|
|
|
|
this.type = Tone.Oscillator.Type.Custom;
|
|
|
|
}
|
|
|
|
});
|
2015-08-28 01:32:09 +00:00
|
|
|
|
2019-01-27 18:05:20 +00:00
|
|
|
/**
|
|
|
|
* The phase of the oscillator in degrees.
|
|
|
|
* @memberOf Tone.Oscillator#
|
|
|
|
* @type {Degrees}
|
|
|
|
* @name phase
|
|
|
|
* @example
|
|
|
|
* osc.phase = 180; //flips the phase of the oscillator
|
|
|
|
*/
|
|
|
|
Object.defineProperty(Tone.Oscillator.prototype, "phase", {
|
|
|
|
get : function(){
|
|
|
|
return this._phase * (180 / Math.PI);
|
|
|
|
},
|
|
|
|
set : function(phase){
|
|
|
|
this._phase = phase * Math.PI / 180;
|
|
|
|
//reset the type
|
|
|
|
this.type = this._type;
|
|
|
|
}
|
|
|
|
});
|
2015-08-31 20:42:27 +00:00
|
|
|
|
2019-01-27 18:05:20 +00:00
|
|
|
/**
|
|
|
|
* Dispose and disconnect.
|
|
|
|
* @return {Tone.Oscillator} this
|
|
|
|
*/
|
|
|
|
Tone.Oscillator.prototype.dispose = function(){
|
|
|
|
Tone.Source.prototype.dispose.call(this);
|
|
|
|
if (this._oscillator !== null){
|
|
|
|
this._oscillator.dispose();
|
|
|
|
this._oscillator = null;
|
|
|
|
}
|
|
|
|
this._wave = null;
|
|
|
|
this._writable(["frequency", "detune"]);
|
|
|
|
this.frequency.dispose();
|
|
|
|
this.frequency = null;
|
|
|
|
this.detune.dispose();
|
|
|
|
this.detune = null;
|
|
|
|
this._partials = null;
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Tone.Oscillator;
|
2014-12-19 21:39:50 +00:00
|
|
|
|