-'use strict';
-
-const internals = {
-
- config: {
- convolverNode: {
- requestMethod: 'GET',
- requestLocation: '/reverb.ogg',
- responseType: 'arraybuffer'
- },
- distortionNode: {
- amount: 400
- }
- },
-
- kTemplate: `<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">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>`,
- kPauseLabel : 'Pause.',
- kRecordLabel : 'Record.',
-};
-
-const Pepperoni = class Pepperoni {
- constructor() {
-
- const context = new AudioContext();
-
- const nodes = this._createNodes(context);
-
- this._activatedNodes = [];
- },
-
- _createNodes(context) {
-
- const delayNode = context.createDelay(1.0);
-
- const convolverNode = context.createConvolver();
- this._initializeConvolverNode(convolverNode);
-
- const loPassFilterNode = context.createBiquadFilter();
- loPassFilterNode.type = 'lowpass';
- loPassFilterNode.frequency.value = 1000;
- loPassFilterNode.gain.value = 25;
-
- const hiPassFilterNode = context.createBiquadFilter();
- hiPassFilterNode.type = 'highpass';
- hiPassFilterNode.frequency.value = 3000;
- hiPassFilterNode.gain.value = 25;
-
- const bandPassFilterNode = context.createBiquadFilter();
- bandPassFilterNode.type = 'bandpass';
- bandPassFilterNode.frequency.value = 2000;
- bandPassFilterNode.gain.value = 25;
-
- const distortionNode = context.createWaveShaper();
- distortionNode.curve = this._generateDistortion(400);
- distortionNode.oversample = '4x';
- }
-
- // Generates a wave to be used with the distortion wave shaper node
-
- _generateDistortion(amount = 50) {
-
- const sampleRate = 44100;
- const curve = new Float32Array(sampleRate);
- const angle = Math.PI / 180;
-
- for (let i = 0; i < sampleRate; ++i) {
- const x = i * 2 / sampleRate - 1;
- curve[i] = ( 3 + amount ) * x * 20 * angle / ( Math.PI + amount * Math.abs(x) );
- }
-
- return curve;
- },
-
- // Initializes a convolver node by requesting the reverb sound,
- // decoding it, and attaching it
-
- _initializeConvolverNode(node) {
-
- const request = new XMLHttpRequest();
- request.open(config.convolverNode.requestMethod, config.convolverNode.requestLocation);
- request.responseType = config.convolverNode.responseType;
- request.addEventListener('load', (event) => {
-
- node.context.decodeAudioData(event.target.response, (buffer) => {
-
- node.buffer = buffer;
- });
- });
- request.send();
- }
-
- // Handles the XHR response to the reverb file
-
-
-
- if (!this.source) {
- this._getUserMedia({
- audio : true
- }, this._onUserMedia.bind(this), this._onUserMediaError.bind(this))
- }
-
- this.element.html(this.constructor.INNER_HTML);
-
- this.controlButton = this.element.find('.record-button');
- this.clearButton = this.element.find('.record-clear');
- 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();
-};
-
-const Pepperoni.prototype = {
-
- _createNodes() {
-
- }
-
- 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) {
- },
-
- record : function record() {
- if (this.recorder && !this.recording) {
- this._canRecord(function handleCanRecord(canRecord) {
- if (canRecord) {
- this.recording = true;
- this.controlButton.addClass('recording')
- this.controlButton.html(this.constructor.PAUSE);
- this._interval = setInterval(this._onRecordCheck.bind(this), 100);
- this.recorder.record();
- }
- }.bind(this));
- }
- },
-
- stop : function stop() {
- if (this.recorder && this.recording) {
- this.recording = false;
- this.controlButton.removeClass('recording')
- this.controlButton.html(this.constructor.RECORD);
- clearInterval(this._interval);
- this.recorder.stop();
- this.recorder.exportWAV();
- }
- },
-
- clear : function clear() {
- if (this.recorder) {
- this.progressBar.width(0);
- this.audioElement.attr('src', '');
- this.audioElement[0].load();
- this.recorder.clear()
- }
- },
-
- finalize : function finalize(callback) {
- if (this.recorder) {
- this.recorder.exportWAV(callback);
- }
- },
-
- getBuffer : function getBuffer(callback) {
- if (this.recorder) {
- this.recorder.getBuffer(callback);
- }
- },
-
- _bindEvents : function bindEvents() {
- var pepperoni = this;
-
- this.controlButton.on('click', function () {
- if (this.recording) {
- this.stop();
- } else {
- this.record();
- }
- }.bind(this))
-
- this.clearButton.on('click', function () {
- if (!this.recording) {
- 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) {
- this._buffer = buffer;
-
- this.audioElement.attr('src', URL.createObjectURL(buffer));
- this.audioElement[0].load();
- },
-
- _onUserMedia : function _onUserMedia(localMediaStream) {
- this.source = this.context.createMediaStreamSource(localMediaStream);
- this.recorder = new Recorder(this.source, {
- workerPath : this.workerPath,
- callback : this._onRecording.bind(this)
- });
- },
-
- _onUserMediaError : function _onUserMediaError(error) {
- console.log("Something went wrong", error);
- this.disable();
- },
-
- _onRecordCheck : function _onRecordCheck() {
- this._canRecord(function (canRecord, bufferSize) {
- var width = bufferSize * this.progressBarContainer.width() / this.maxSize;
- this.progressBar.width(width);
- if (!canRecord) {
- this.stop();
- }
- }.bind(this));
- },
-
- _canRecord : function _canRecord(callback) {
- this.recorder.getBuffer(function getBuffer(buffer) {
- var bufferSize = buffer[0].length + buffer[1].length;
- callback && callback(bufferSize <= this.maxSize, bufferSize);
- }.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);
- },
-
- // Normalize get user media
- _getUserMedia : (navigator.getUserMedia ||
- navigator.webkitGetUserMedia ||
- navigator.mozGetUserMedia ||
- navigator.msGetUserMedia).bind(navigator)
-}
-});