diff --git a/src/app.js b/src/app.js index 35d9b26e..41635dd7 100644 --- a/src/app.js +++ b/src/app.js @@ -42,22 +42,15 @@ p5.BandPass = BandPass; import EQ from './eq'; p5.EQ = EQ; - - import listener3D from './listener3d'; p5.listener3D = listener3D; - - import Panner3D from './panner3d'; p5.Panner3D = Panner3D; - - import Delay from './delay'; p5.Delay = Delay; - import './reverb'; import Metro from './metro'; @@ -69,12 +62,11 @@ import './soundLoop'; import Compressor from './compressor'; p5.Compressor = Compressor; -import './soundRecorder'; - - import peakDetect from './peakDetect'; p5.peakDetect = peakDetect; +import SoundRecorder from './soundRecorder'; +p5.SoundRecorder = SoundRecorder; import Distortion from './distortion'; p5.Distortion = Distortion; @@ -88,11 +80,8 @@ p5.AudioVoice = AudioVoice; import MonoSynth from './monosynth'; p5.MonoSynth = MonoSynth; - - import OnsetDetect from './onsetDetect'; p5.OnsetDetect = OnsetDetect; import PolySynth from './polysynth'; p5.PolySynth = PolySynth; - diff --git a/src/soundRecorder.js b/src/soundRecorder.js index 2fae9c92..cb802456 100644 --- a/src/soundRecorder.js +++ b/src/soundRecorder.js @@ -80,145 +80,149 @@ const ac = p5sound.audiocontext; * } * */ -p5.SoundRecorder = function () { - this.input = ac.createGain(); - this.output = ac.createGain(); - - this._inputChannels = 2; - this._outputChannels = 2; // stereo output, even if input is mono - - const workletBufferSize = safeBufferSize(1024); - - this._workletNode = new AudioWorkletNode( - ac, - processorNames.recorderProcessor, - { - outputChannelCount: [this._outputChannels], - processorOptions: { - numInputChannels: this._inputChannels, - bufferSize: workletBufferSize, - }, - } - ); - - this._workletNode.port.onmessage = function (event) { - if (event.data.name === 'buffers') { - const buffers = [ - new Float32Array(event.data.leftBuffer), - new Float32Array(event.data.rightBuffer), - ]; - this._callback(buffers); - } - }.bind(this); +class SoundRecorder { + constructor() { + this.input = ac.createGain(); + this.output = ac.createGain(); + + this._inputChannels = 2; + this._outputChannels = 2; // stereo output, even if input is mono + + const workletBufferSize = safeBufferSize(1024); + + this._workletNode = new AudioWorkletNode( + ac, + processorNames.recorderProcessor, + { + outputChannelCount: [this._outputChannels], + processorOptions: { + numInputChannels: this._inputChannels, + bufferSize: workletBufferSize, + }, + } + ); + + this._workletNode.port.onmessage = function (event) { + if (event.data.name === 'buffers') { + const buffers = [ + new Float32Array(event.data.leftBuffer), + new Float32Array(event.data.rightBuffer), + ]; + this._callback(buffers); + } + }.bind(this); + + /** + * callback invoked when the recording is over + * @private + * @type Function(Float32Array) + */ + this._callback = function () {}; + + // connections + this._workletNode.connect(p5.soundOut._silentNode); + this.setInput(); + + // add this p5.SoundFile to the soundArray + p5sound.soundArray.push(this); + } /** - * callback invoked when the recording is over - * @private - * @type Function(Float32Array) + * Connect a specific device to the p5.SoundRecorder. + * If no parameter is given, p5.SoundRecorer will record + * all audible p5.sound from your sketch. + * + * @method setInput + * @for p5.SoundRecorder + * @param {Object} [unit] p5.sound object or a web audio unit + * that outputs sound */ - this._callback = function () {}; - - // connections - this._workletNode.connect(p5.soundOut._silentNode); - this.setInput(); - - // add this p5.SoundFile to the soundArray - p5sound.soundArray.push(this); -}; + setInput(unit) { + this.input.disconnect(); + this.input = null; + this.input = ac.createGain(); + this.input.connect(this._workletNode); + this.input.connect(this.output); + if (unit) { + unit.connect(this.input); + } else { + p5.soundOut.output.connect(this.input); + } + } -/** - * Connect a specific device to the p5.SoundRecorder. - * If no parameter is given, p5.SoundRecorer will record - * all audible p5.sound from your sketch. - * - * @method setInput - * @for p5.SoundRecorder - * @param {Object} [unit] p5.sound object or a web audio unit - * that outputs sound - */ -p5.SoundRecorder.prototype.setInput = function (unit) { - this.input.disconnect(); - this.input = null; - this.input = ac.createGain(); - this.input.connect(this._workletNode); - this.input.connect(this.output); - if (unit) { - unit.connect(this.input); - } else { - p5.soundOut.output.connect(this.input); + /** + * Start recording. To access the recording, provide + * a p5.SoundFile as the first parameter. The p5.SoundRecorder + * will send its recording to that p5.SoundFile for playback once + * recording is complete. Optional parameters include duration + * (in seconds) of the recording, and a callback function that + * will be called once the complete recording has been + * transfered to the p5.SoundFile. + * + * @method record + * @for p5.SoundRecorder + * @param {p5.SoundFile} soundFile p5.SoundFile + * @param {Number} [duration] Time (in seconds) + * @param {Function} [callback] The name of a function that will be + * called once the recording completes + */ + record(sFile, duration, callback) { + this._workletNode.port.postMessage({ name: 'start', duration: duration }); + + if (sFile && callback) { + this._callback = function (buffer) { + sFile.setBuffer(buffer); + callback(); + }; + } else if (sFile) { + this._callback = function (buffer) { + sFile.setBuffer(buffer); + }; + } } -}; -/** - * Start recording. To access the recording, provide - * a p5.SoundFile as the first parameter. The p5.SoundRecorder - * will send its recording to that p5.SoundFile for playback once - * recording is complete. Optional parameters include duration - * (in seconds) of the recording, and a callback function that - * will be called once the complete recording has been - * transfered to the p5.SoundFile. - * - * @method record - * @for p5.SoundRecorder - * @param {p5.SoundFile} soundFile p5.SoundFile - * @param {Number} [duration] Time (in seconds) - * @param {Function} [callback] The name of a function that will be - * called once the recording completes - */ -p5.SoundRecorder.prototype.record = function (sFile, duration, callback) { - this._workletNode.port.postMessage({ name: 'start', duration: duration }); - - if (sFile && callback) { - this._callback = function (buffer) { - sFile.setBuffer(buffer); - callback(); - }; - } else if (sFile) { - this._callback = function (buffer) { - sFile.setBuffer(buffer); - }; + /** + * Stop the recording. Once the recording is stopped, + * the results will be sent to the p5.SoundFile that + * was given on .record(), and if a callback function + * was provided on record, that function will be called. + * + * @method stop + * @for p5.SoundRecorder + */ + stop() { + this._workletNode.port.postMessage({ name: 'stop' }); } -}; -/** - * Stop the recording. Once the recording is stopped, - * the results will be sent to the p5.SoundFile that - * was given on .record(), and if a callback function - * was provided on record, that function will be called. - * - * @method stop - * @for p5.SoundRecorder - */ -p5.SoundRecorder.prototype.stop = function () { - this._workletNode.port.postMessage({ name: 'stop' }); -}; + dispose() { + // remove reference from soundArray + var index = p5sound.soundArray.indexOf(this); + p5sound.soundArray.splice(index, 1); -p5.SoundRecorder.prototype.dispose = function () { - // remove reference from soundArray - var index = p5sound.soundArray.indexOf(this); - p5sound.soundArray.splice(index, 1); + this._callback = function () {}; + if (this.input) { + this.input.disconnect(); + } + this.input = null; + this._workletNode = null; + } - this._callback = function () {}; - if (this.input) { - this.input.disconnect(); + /** + * Save a p5.SoundFile as a .wav file. The browser will prompt the user + * to download the file to their device. + * For uploading audio to a server, use + * `p5.SoundFile.saveBlob`. + * + * @for p5 + * @method saveSound + * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save + * @param {String} fileName name of the resulting .wav file. + */ + // add to p5.prototype as this is used by the p5 `save()` method. + saveSound(soundFile, fileName) { + const dataView = convertToWav(soundFile.buffer); + p5.prototype.writeFile([dataView], fileName, 'wav'); } - this.input = null; - this._workletNode = null; -}; +} -/** - * Save a p5.SoundFile as a .wav file. The browser will prompt the user - * to download the file to their device. - * For uploading audio to a server, use - * `p5.SoundFile.saveBlob`. - * - * @for p5 - * @method saveSound - * @param {p5.SoundFile} soundFile p5.SoundFile that you wish to save - * @param {String} fileName name of the resulting .wav file. - */ -// add to p5.prototype as this is used by the p5 `save()` method. -p5.prototype.saveSound = function (soundFile, fileName) { - const dataView = convertToWav(soundFile.buffer); - p5.prototype.writeFile([dataView], fileName, 'wav'); -}; +export default SoundRecorder;