Tone.js/Tone/effect/BitCrusher.js

141 lines
3 KiB
JavaScript
Raw Normal View History

2014-08-23 18:23:54 +00:00
define(["Tone/core/Tone", "Tone/effect/Effect"], function(Tone){
2014-04-06 00:47:59 +00:00
2014-06-17 16:30:45 +00:00
/**
2014-08-21 00:46:40 +00:00
* @class downsample incoming signal
2014-06-17 16:30:45 +00:00
* inspiration from https://github.com/jaz303/bitcrusher/blob/master/index.js
*
* @constructor
2014-08-23 18:23:54 +00:00
* @extends {Tone.Effect}
* @param {number|Object=} bits
2014-06-17 16:30:45 +00:00
* @param {number=} frequency
*/
Tone.BitCrusher = function(){
2014-06-17 16:30:45 +00:00
var options = this.optionsObject(arguments, ["bits", "frequency"], Tone.BitCrusher.defaults);
Tone.Effect.call(this, options);
2014-04-06 00:47:59 +00:00
/**
* @private
* @type {number}
*/
this._bits = this.defaultArg(options.bits, 8);
/**
* @private
* @type {number}
*/
this._frequency = this.defaultArg(options.frequency, 0.5);
/**
* @private
* @type {number}
*/
2014-06-17 16:30:45 +00:00
this._step = 2 * Math.pow(0.5, this._bits);
/**
* @private
* @type {number}
*/
2014-06-17 16:30:45 +00:00
this._invStep = 1/this._step;
/**
* @private
* @type {number}
*/
2014-06-17 16:30:45 +00:00
this._phasor = 0;
/**
* @private
* @type {number}
*/
2014-06-17 16:30:45 +00:00
this._last = 0;
2014-04-06 00:47:59 +00:00
/**
* @private
* @type {ScriptProcessorNode}
*/
2014-06-17 16:30:45 +00:00
this._crusher = this.context.createScriptProcessor(this.bufferSize, 1, 1);
this._crusher.onaudioprocess = this._audioprocess.bind(this);
2014-04-06 00:47:59 +00:00
//connect it up
2014-08-23 18:23:54 +00:00
this.connectEffect(this._crusher);
2014-06-17 16:30:45 +00:00
};
2014-04-06 00:47:59 +00:00
2014-08-23 18:23:54 +00:00
Tone.extend(Tone.BitCrusher, Tone.Effect);
2014-04-06 00:47:59 +00:00
/**
* the default values
* @static
* @type {Object}
*/
Tone.BitCrusher.defaults = {
"bits" : 8,
"frequency" : 0.5
};
2014-06-17 16:30:45 +00:00
/**
* @private
* @param {AudioProcessingEvent} event
*/
Tone.BitCrusher.prototype._audioprocess = function(event){
//cache the values used in the loop
var phasor = this._phasor;
var freq = this._frequency;
var invStep = this._invStep;
var last = this._last;
var step = this._step;
var input = event.inputBuffer.getChannelData(0);
var output = event.outputBuffer.getChannelData(0);
2014-04-06 00:47:59 +00:00
for (var i = 0, len = output.length; i < len; i++) {
phasor += freq;
if (phasor >= 1) {
phasor -= 1;
last = step * ((input[i] * invStep) | 0 + 0.5);
2014-04-06 00:47:59 +00:00
}
output[i] = last;
}
2014-06-17 16:30:45 +00:00
//set the values for the next loop
this._phasor = phasor;
this._last = last;
};
2014-04-06 00:47:59 +00:00
2014-06-17 16:30:45 +00:00
/**
* set the bit rate
*
* @param {number} bits
*/
2014-04-06 00:47:59 +00:00
Tone.BitCrusher.prototype.setBits = function(bits){
2014-06-17 16:30:45 +00:00
this._bits = bits;
this._step = 2 * Math.pow(0.5, this._bits);
this._invStep = 1/this._step;
};
2014-04-06 00:47:59 +00:00
2014-06-17 16:30:45 +00:00
/**
* set the frequency
* @param {number} freq
*/
2014-04-06 00:47:59 +00:00
Tone.BitCrusher.prototype.setFrequency = function(freq){
2014-06-17 16:30:45 +00:00
this._frequency = freq;
};
2014-04-06 00:47:59 +00:00
2014-08-25 13:57:36 +00:00
/**
* set all of the parameters with an object
* @param {Object} params
*/
Tone.BitCrusher.prototype.set = function(params){
if (!this.isUndef(params.frequency)) this.setFrequency(params.frequency);
if (!this.isUndef(params.bits)) this.setBits(params.bits);
Tone.Effect.prototype.set.call(this, params);
};
2014-06-20 04:38:14 +00:00
/**
* clean up
*/
Tone.BitCrusher.prototype.dispose = function(){
Tone.Effect.prototype.dispose.call(this);
2014-06-20 04:38:14 +00:00
this._crusher.disconnect();
this._crusher = null;
};
2014-04-06 00:47:59 +00:00
return Tone.BitCrusher;
});