mirror of
https://github.com/Tonejs/Tone.js
synced 2025-01-16 05:43:56 +00:00
170 lines
3.8 KiB
JavaScript
170 lines
3.8 KiB
JavaScript
|
import Tone from "../core/Tone";
|
||
|
import "../component/PhaseShiftAllpass";
|
||
|
import "../source/Oscillator";
|
||
|
import "../signal/Signal";
|
||
|
import "../signal/Multiply";
|
||
|
import "../signal/Negate";
|
||
|
import "../signal/Add";
|
||
|
import "../effect/Effect";
|
||
|
|
||
|
/**
|
||
|
* @class Tone.FrequencyShifter shifts frequencys.
|
||
|
*
|
||
|
* @extends {Tone.Effect}
|
||
|
* @param {Interval=} pitch The interval to transpose the incoming signal by.
|
||
|
*/
|
||
|
Tone.FrequencyShifter = function(){
|
||
|
|
||
|
var options = Tone.defaults(arguments, ["pitch"], Tone.FrequencyShifter);
|
||
|
Tone.Effect.call(this, options);
|
||
|
|
||
|
//this.createInsOuts(1, 1);
|
||
|
|
||
|
/**
|
||
|
* The ring modulators carrier frequency
|
||
|
* @type {Tone.Signal}
|
||
|
*/
|
||
|
this.carrierFrequency = new Tone.Signal(options.pitch);
|
||
|
|
||
|
/**
|
||
|
* The ring modulators sine carrier
|
||
|
* @type {Tone.Oscillator}
|
||
|
* @private
|
||
|
*/
|
||
|
const sineConfig = {
|
||
|
"type" : "sine",
|
||
|
"frequency" : this.carrierFrequency.value,
|
||
|
"phase" : 0
|
||
|
};
|
||
|
this._sine = new Tone.Oscillator(sineConfig);
|
||
|
|
||
|
/**
|
||
|
* The ring modulators cosine carrier
|
||
|
* @type {Tone.Oscillator}
|
||
|
* @private
|
||
|
*/
|
||
|
const cosineConfig = {
|
||
|
"type" : "sine",
|
||
|
"frequency" : this.carrierFrequency.value,
|
||
|
"phase" : -90
|
||
|
};
|
||
|
this._cosine = new Tone.Oscillator(cosineConfig);
|
||
|
|
||
|
/**
|
||
|
* The sine multiply operator
|
||
|
* @type {Tone.Multiply}
|
||
|
* @private
|
||
|
*/
|
||
|
this._sineMultipy = new Tone.Multiply();
|
||
|
|
||
|
/**
|
||
|
* The cosine multiply operator
|
||
|
* @type {Tone.Multiply}
|
||
|
* @private
|
||
|
*/
|
||
|
this._cosineMultiply = new Tone.Multiply();
|
||
|
|
||
|
/**
|
||
|
* The negate operator
|
||
|
* @type {Tone.Negate}
|
||
|
* @private
|
||
|
*/
|
||
|
this._negate = new Tone.Negate();
|
||
|
|
||
|
/**
|
||
|
* The final add operator
|
||
|
* @type {Tone.Add}
|
||
|
* @private
|
||
|
*/
|
||
|
this._add = new Tone.Add();
|
||
|
|
||
|
/**
|
||
|
* The phase shifter to create the initial 90° phase offset
|
||
|
* @type {Tone.PhaseShiftAllpass}
|
||
|
* @private
|
||
|
*/
|
||
|
this._phaseShifter = new Tone.PhaseShiftAllpass();
|
||
|
|
||
|
// connect the carrier frequency signal to the two oscillators
|
||
|
this.carrierFrequency.connect(this._sine.frequency);
|
||
|
this.carrierFrequency.connect(this._cosine.frequency);
|
||
|
|
||
|
// connect the audio graph
|
||
|
Tone.connect(this.input, this._phaseShifter);
|
||
|
|
||
|
this._phaseShifter.connect(this._cosineMultiply, 1, 0);
|
||
|
this._cosine.connect(this._cosineMultiply, 0, 1);
|
||
|
|
||
|
this._phaseShifter.connect(this._sineMultipy, 0, 0);
|
||
|
this._sine.connect(this._sineMultipy, 0, 1);
|
||
|
this._sineMultipy.connect(this._negate);
|
||
|
|
||
|
this._cosineMultiply.connect(this._add, 0, 0);
|
||
|
this._negate.connect(this._add, 0, 1);
|
||
|
|
||
|
this._add.connect(this.output);
|
||
|
|
||
|
// start the oscillators at the same time
|
||
|
var now = this.now();
|
||
|
this._sine.start(now);
|
||
|
this._cosine.start(now);
|
||
|
};
|
||
|
|
||
|
Tone.extend(Tone.FrequencyShifter, Tone.Effect);
|
||
|
|
||
|
/**
|
||
|
* default values
|
||
|
* @static
|
||
|
* @type {Object}
|
||
|
* @const
|
||
|
*/
|
||
|
Tone.FrequencyShifter.defaults = {
|
||
|
"pitch" : 0
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Repitch the incoming signal by some interval (measured
|
||
|
* in semi-tones).
|
||
|
* @memberOf Tone.FrequencyShifter#
|
||
|
* @type {Interval}
|
||
|
* @name pitch
|
||
|
* @example
|
||
|
* frequencyShifter.pitch = -12; //down one octave
|
||
|
* frequencyShifter.pitch = 7; //up a fifth
|
||
|
*/
|
||
|
Object.defineProperty(Tone.FrequencyShifter.prototype, "pitch", {
|
||
|
get : function(){
|
||
|
return this.carrierFrequency.value;
|
||
|
},
|
||
|
set : function(interval){
|
||
|
this.carrierFrequency.value = Tone.intervalToFrequencyRatio(interval);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Clean up.
|
||
|
* @return {Tone.FrequencyShifter} this
|
||
|
*/
|
||
|
Tone.FrequencyShifter.prototype.dispose = function(){
|
||
|
Tone.Effect.prototype.dispose.call(this);
|
||
|
this.carrierFrequency.dispose();
|
||
|
this.carrierFrequency = null;
|
||
|
this._sine.dispose();
|
||
|
this._sine = null;
|
||
|
this._cosine.dispose();
|
||
|
this._cosine = null;
|
||
|
this._sineMultipy.dispose();
|
||
|
this._sineMultipy = null;
|
||
|
this._cosineMultiply.dispose();
|
||
|
this._cosineMultiply = null;
|
||
|
this._negate.dispose();
|
||
|
this._negate = null;
|
||
|
this._add.dispose();
|
||
|
this._add = null;
|
||
|
this._phaseShifter.dispose();
|
||
|
this._phaseShifter = null;
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
export default Tone.FrequencyShifter;
|