+'use strict';
+
Class(UnlimitedPizza, "Pepperoni").inherits(Widget)({
INNER_HTML : ' \
-<a class="record-button">⬤</a> \
+<a class="record-button">Record.</a> \
<div class="record-info"> \
<div class="record-progress"> \
<div class="record-progress-bar-container"> \
<div class="record-progress-bar"></div> \
</div> \
- <a class="record-clear">X</a> \
+ <a class="record-clear">Clear recording.</a> \
</div> \
<audio class="record-preview" controls></audio> \
+ <div class="filter-switches"> \
+ <input class="filter-switch" name="bandpass-filter" type="checkbox" /> <label for="bandpass-filter">Band Pass</label> \
+ <input class="filter-switch" name="hipass-filter" type="checkbox" /> <label for="hipass-filter">Hi Pass</label> \
+ <input class="filter-switch" name="lopass-filter" type="checkbox" /> <label for="lopass-filter">Lo Pass</label> \
+ <input class="filter-switch" name="reverb-filter" type="checkbox" /> <label for="reverb-filter">Reverb</label> \
+ <input class="filter-switch" name="distort-filter" type="checkbox" /> <label for="distort-filter">Distort</label> \
+ </div> \
</div> \
',
- PAUSE : '▐▐',
- RECORD : '⬤',
+ PAUSE : 'Pause.',
+ RECORD : 'Record.',
prototype : {
maxSize : 1048576,
recording : false,
source : null,
recorder : null,
context : null,
+ _delayNode : null,
+ _bandPassFilterNode : null,
+ _hiPassFilterNode : null,
+ _loPassFilterNode : null,
+ _convolverNode : null,
+ _distortionNode : null,
+ _activatedNodes : null,
workerPath : '/js/vendor/recorderjs/recorderWorker.js',
init : function init(config) {
+ var channels, frameCount, reverbBuffer, request, requestHandler;
+
Widget.prototype.init.call(this, config);
if (!this.context) {
this.context = new (window.AudioContext || window.webkitAudioContext)();
}
+ this._delayNode = this.context.createDelay(1.0);
+ this._bandPassFilterNode = this.context.createBiquadFilter();
+ this._hiPassFilterNode = this.context.createBiquadFilter();
+ this._loPassFilterNode = this.context.createBiquadFilter();
+ this._convolverNode = this.context.createConvolver();
+ this._distortionNode = this.context.createWaveShaper();
+
+ this._distortionNode.curve = this._generateDistortion(400);
+ this._distortionNode.oversample = '4x';
+
+ this._activatedNodes = [];
+
+ // config lo pass
+ this._loPassFilterNode.type = "lowpass";
+ this._loPassFilterNode.frequency.value = 1000;
+ this._loPassFilterNode.gain.value = 25;
+
+ // config hi pass
+ this._hiPassFilterNode.type = "highpass";
+ this._hiPassFilterNode.frequency.value = 3000;
+ this._hiPassFilterNode.gain.value = 25;
+
+ // config band pass
+ this._bandPassFilterNode.type = "bandpass";
+ this._bandPassFilterNode.frequency.value = 2000;
+ this._bandPassFilterNode.gain.value = 25;
+
+ requestHandler = function bufferFile(ev) {
+ var request = ev.target;
+ console.log("Reverb loading");
+ this.context.decodeAudioData(request.response, function(buffer){
+ console.log("Reverb loaded");
+ this._convolverNode.buffer = buffer;
+ }.bind(this));
+ }.bind(this);
+
+ request = new XMLHttpRequest();
+ request.open('GET', '/reverb.ogg', true);
+ request.responseType = 'arraybuffer';
+ request.addEventListener('load', requestHandler, false);
+ request.send();
+
if (!this.source) {
this._getUserMedia({
audio : true
this.audioElement = this.element.find('audio');
this.progressBarContainer = this.element.find('.record-progress-bar-container');
this.progressBar = this.element.find('.record-progress-bar');
+ this.switches = this.element.find('.filter-switch');
this._bindEvents();
},
},
_bindEvents : function bindEvents() {
+ var pepperoni = this;
+
this.controlButton.on('click', function () {
if (this.recording) {
this.stop();
this.clear();
}
}.bind(this))
+
+ this.switches.on('change', function (ev) {
+ if (!pepperoni.source) {
+ this.checked = false;
+ return false;
+ }
+ switch (this.name) {
+ case 'delay-filter':
+ if (this.checked) {
+ pepperoni._addNode(pepperoni._delayNode);
+ } else {
+ pepperoni._removeNode(pepperoni._delayNode);
+ }
+ break;
+
+ case 'hipass-filter':
+ if (this.checked) {
+ pepperoni._addNode(pepperoni._hiPassFilterNode);
+ } else {
+ pepperoni._removeNode(pepperoni._hiPassFilterNode);
+ }
+ break;
+
+ case 'bandpass-filter':
+ if (this.checked) {
+ pepperoni._addNode(pepperoni._bandPassFilterNode);
+ } else {
+ pepperoni._removeNode(pepperoni._bandPassFilterNode);
+ }
+ break;
+
+ case 'lopass-filter':
+ if (this.checked) {
+ pepperoni._addNode(pepperoni._loPassFilterNode);
+ } else {
+ pepperoni._removeNode(pepperoni._loPassFilterNode);
+ }
+ break;
+
+ case 'reverb-filter':
+ if (this.checked) {
+ pepperoni._addNode(pepperoni._convolverNode);
+ } else {
+ pepperoni._removeNode(pepperoni._convolverNode);
+ }
+ break;
+
+ case 'distort-filter':
+ if (this.checked) {
+ pepperoni._addNode(pepperoni._distortionNode);
+ } else {
+ pepperoni._removeNode(pepperoni._distortionNode);
+ }
+
+ break;
+ }
+ });
},
_onRecording : function _onRecording(buffer) {
}.bind(this));
},
+ _addNode : function _addNode(node) {
+ var i;
+
+ i = this._activatedNodes.length;
+
+ this._activatedNodes.push(node);
+
+ if (i === 0) {
+ this.source.disconnect();
+ this.source.connect(node);
+ } else {
+ this._activatedNodes[i - 1].disconnect();
+ this._activatedNodes[i - 1].connect(node);
+ }
+
+ node.connect(this.recorder.node);
+ this.recorder.context = node.context;
+ this.recorder.node.connect(this.recorder.context.destination)
+
+ console.log("Adding: ", node);
+ },
+
+ _removeNode : function _removeNode(node) {
+ var i;
+
+ i = this._activatedNodes.indexOf(node);
+
+ node.disconnect();
+
+ if (i === 0 && i + 1 === this._activatedNodes.length) {
+ // It was the only one, connect source to recorder.
+ this.source.disconnect();
+ this.source.connect(this.recorder.node);
+ } else if (i === 0) {
+ // Normal 0 case, connect source to node. Recorder stays the same
+ this.source.disconnect();
+ this.source.connect(this._activatedNodes[i+1]);
+ } else if (i + 1 === this._activatedNodes.length) {
+ // It's not the 0 case, but we need to reconnect to recorder.
+ this._activatedNodes[i - 1].disconnect();
+ this._activatedNodes[i - 1].connect(this.recorder.node);
+ } else {
+ // Normal case, connect previous node to node
+ this._activatedNodes[i - 1].disconnect();
+ this._activatedNodes[i - 1].connect(this._activatedNodes[i + 1]);
+ }
+
+ this._activatedNodes.splice(i, 1);
+
+ console.log("Removing: ", node);
+ },
+
+ _generateDistortion : function generateDistortion(amount) {
+ var k = typeof amount === 'number' ? amount : 50,
+ n_samples = 44100,
+ curve = new Float32Array(n_samples),
+ deg = Math.PI / 180,
+ i = 0,
+ x;
+ for ( ; i < n_samples; ++i ) {
+ x = i * 2 / n_samples - 1;
+ curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) );
+ }
+ return curve;
+ },
+
// Normalize get user media
_getUserMedia : (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||