2017-02-01 18:02:04 -05:00
|
|
|
var Tone = require('tone');
|
2016-11-29 18:33:09 -05:00
|
|
|
|
2017-02-01 18:02:04 -05:00
|
|
|
/**
|
2017-02-02 14:53:17 -05:00
|
|
|
* A pitch change effect, which changes the playback rate of the sound in order
|
2017-02-01 18:02:04 -05:00
|
|
|
* to change its pitch: reducing the playback rate lowers the pitch, increasing the rate
|
|
|
|
* raises the pitch. The duration of the sound is also changed.
|
|
|
|
*
|
|
|
|
* Changing the value of the pitch effect by 10 causes a change in pitch by 1 semitone
|
|
|
|
* (i.e. a musical half-step, such as the difference between C and C#)
|
|
|
|
* Changing the pitch effect by 120 changes the pitch by one octave (12 semitones)
|
|
|
|
*
|
|
|
|
* The value of this effect is not clamped (i.e. it is typically between -120 and 120,
|
|
|
|
* but can be set much higher or much lower, with weird and fun results).
|
|
|
|
* We should consider what extreme values to use for clamping it.
|
|
|
|
*
|
|
|
|
* Note that this effect functions differently from the other audio effects. It is
|
|
|
|
* not part of a chain of audio nodes. Instead, it provides a way to set the playback
|
|
|
|
* on one SoundPlayer or a group of them.
|
|
|
|
* @constructor
|
|
|
|
*/
|
2016-11-29 18:33:09 -05:00
|
|
|
function PitchEffect () {
|
2017-02-01 18:02:04 -05:00
|
|
|
this.value = 0; // effect value
|
|
|
|
this.ratio = 1; // the playback rate ratio
|
2016-11-29 18:33:09 -05:00
|
|
|
|
2016-11-30 11:29:00 -05:00
|
|
|
this.tone = new Tone();
|
2016-11-29 18:33:09 -05:00
|
|
|
}
|
|
|
|
|
2017-02-01 18:02:04 -05:00
|
|
|
/**
|
|
|
|
* Set the effect value
|
|
|
|
* @param {number} val - the new value to set the effect to
|
|
|
|
* @param {object} players - a dictionary of SoundPlayer objects to apply the effect to, indexed by md5
|
|
|
|
*/
|
2016-11-29 18:33:09 -05:00
|
|
|
PitchEffect.prototype.set = function (val, players) {
|
|
|
|
this.value = val;
|
2017-01-30 11:09:45 -05:00
|
|
|
this.ratio = this.getRatio(this.value);
|
2016-11-29 18:33:09 -05:00
|
|
|
this.updatePlayers(players);
|
|
|
|
};
|
|
|
|
|
2017-02-01 18:02:04 -05:00
|
|
|
/**
|
|
|
|
* Change the effect value
|
|
|
|
* @param {number} val - the value to change the effect by
|
|
|
|
* @param {Object} players - a dictionary of SoundPlayer objects indexed by md5
|
|
|
|
*/
|
2016-11-29 18:33:09 -05:00
|
|
|
PitchEffect.prototype.changeBy = function (val, players) {
|
|
|
|
this.set(this.value + val, players);
|
|
|
|
};
|
|
|
|
|
2017-02-01 18:02:04 -05:00
|
|
|
/**
|
|
|
|
* Compute the playback ratio for an effect value.
|
|
|
|
* The playback ratio is scaled so that a change of 10 in the effect value
|
|
|
|
* gives a change of 1 semitone in the ratio.
|
|
|
|
* @param {number} val - an effect value
|
|
|
|
* @returns {number} a playback ratio
|
|
|
|
*/
|
2017-01-30 11:09:45 -05:00
|
|
|
PitchEffect.prototype.getRatio = function (val) {
|
|
|
|
return this.tone.intervalToFrequencyRatio(val / 10);
|
|
|
|
};
|
|
|
|
|
2017-02-01 18:02:04 -05:00
|
|
|
/**
|
|
|
|
* Update a sound player's playback rate using the current ratio for the effect
|
|
|
|
* @param {Object} player - a SoundPlayer object
|
|
|
|
*/
|
2017-01-30 11:09:45 -05:00
|
|
|
PitchEffect.prototype.updatePlayer = function (player) {
|
|
|
|
player.setPlaybackRate(this.ratio);
|
2016-11-29 18:33:09 -05:00
|
|
|
};
|
|
|
|
|
2017-02-01 18:02:04 -05:00
|
|
|
/**
|
|
|
|
* Update a sound player's playback rate using the current ratio for the effect
|
|
|
|
* @param {object} players - a dictionary of SoundPlayer objects to update, indexed by md5
|
|
|
|
*/
|
2016-11-29 18:33:09 -05:00
|
|
|
PitchEffect.prototype.updatePlayers = function (players) {
|
|
|
|
if (!players) return;
|
|
|
|
|
2017-01-30 11:09:45 -05:00
|
|
|
for (var md5 in players) {
|
|
|
|
this.updatePlayer(players[md5]);
|
2016-11-29 18:33:09 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = PitchEffect;
|
|
|
|
|