From 446c328de696dbc31e0a2f0a08415ad971427641 Mon Sep 17 00:00:00 2001 From: endurance21 Date: Thu, 20 Aug 2020 01:01:24 +0530 Subject: [PATCH] replacement of es5 functions to es6 classes feat p5.SoundLoop --- src/app.js | 16 +- src/soundLoop.js | 490 ++++++++++++++++++++++++----------------------- 2 files changed, 249 insertions(+), 257 deletions(-) diff --git a/src/app.js b/src/app.js index 35d9b26e..ab0e22e3 100644 --- a/src/app.js +++ b/src/app.js @@ -42,40 +42,33 @@ 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'; p5.Metro = Metro; import './looper'; -import './soundLoop'; + +import SoundLoop from './soundLoop'; +p5.SoundLoop = SoundLoop; import Compressor from './compressor'; p5.Compressor = Compressor; import './soundRecorder'; - import peakDetect from './peakDetect'; p5.peakDetect = peakDetect; - import Distortion from './distortion'; p5.Distortion = Distortion; @@ -88,11 +81,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/soundLoop.js b/src/soundLoop.js index f5953a30..3ca60a74 100644 --- a/src/soundLoop.js +++ b/src/soundLoop.js @@ -51,273 +51,275 @@ import Clock from 'Tone/core/Clock'; * } * */ -p5.SoundLoop = function (callback, interval) { - this.callback = callback; - /** - * musicalTimeMode uses Tone.Time convention - * true if string, false if number - * @property {Boolean} musicalTimeMode - */ - this.musicalTimeMode = typeof this._interval === 'number' ? false : true; +class SoundLoop { + constructor(callback, interval) { + /** + * Getters and Setters, setting any paramter will result in a change in the clock's + * frequency, that will be reflected after the next callback + * beats per minute (defaults to 60) + * @property {Number} bpm + * @for p5.SoundLoop + */ + Object.defineProperty(this, 'bpm', { + get: function () { + return this._bpm; + }, + set: function (bpm) { + if (!this.musicalTimeMode) { + console.warn( + 'Changing the BPM in "seconds" mode has no effect. ' + + 'BPM is only relevant in musicalTimeMode ' + + 'when the interval is specified as a string ' + + '("2n", "4n", "1m"...etc)' + ); + } + this._bpm = bpm; + this._update(); + }, + }); - this._interval = interval || 1; + /** + * number of quarter notes in a measure (defaults to 4) + * @property {Number} timeSignature + * @for p5.SoundLoop + */ + Object.defineProperty(this, 'timeSignature', { + get: function () { + return this._timeSignature; + }, + set: function (timeSig) { + if (!this.musicalTimeMode) { + console.warn( + 'Changing the timeSignature in "seconds" mode has no effect. ' + + 'BPM is only relevant in musicalTimeMode ' + + 'when the interval is specified as a string ' + + '("2n", "4n", "1m"...etc)' + ); + } + this._timeSignature = timeSig; + this._update(); + }, + }); - /** - * musicalTimeMode variables - * modify these only when the interval is specified in musicalTime format as a string - */ - this._timeSignature = 4; - this._bpm = 60; + /** + * length of the loops interval + * @property {Number|String} interval + * @for p5.SoundLoop + */ + Object.defineProperty(this, 'interval', { + get: function () { + return this._interval; + }, + set: function (interval) { + this.musicalTimeMode = typeof interval === 'number' ? false : true; + this._interval = interval; + this._update(); + }, + }); - this.isPlaying = false; + /** + * how many times the callback has been called so far + * @property {Number} iterations + * @for p5.SoundLoop + * @readonly + */ + Object.defineProperty(this, 'iterations', { + get: function () { + return this.clock.ticks; + }, + }); - /** - * Set a limit to the number of loops to play. defaults to Infinity - * @property {Number} maxIterations - */ - this.maxIterations = Infinity; - var self = this; + this.callback = callback; + /** + * musicalTimeMode uses Tone.Time convention + * true if string, false if number + * @property {Boolean} musicalTimeMode + */ + this.musicalTimeMode = typeof this._interval === 'number' ? false : true; - this.clock = new Clock({ - callback: function (time) { - var timeFromNow = time - p5sound.audiocontext.currentTime; - /** - * Do not initiate the callback if timeFromNow is < 0 - * This ususually occurs for a few milliseconds when the page - * is not fully loaded - * - * The callback should only be called until maxIterations is reached - */ - if (timeFromNow > 0 && self.iterations <= self.maxIterations) { - self.callback(timeFromNow); - } - }, - frequency: this._calcFreq(), - }); -}; + this._interval = interval || 1; -/** - * Start the loop - * @method start - * @for p5.SoundLoop - * @param {Number} [timeFromNow] schedule a starting time - */ -p5.SoundLoop.prototype.start = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (!this.isPlaying) { - this.clock.start(now + t); - this.isPlaying = true; - } -}; + /** + * musicalTimeMode variables + * modify these only when the interval is specified in musicalTime format as a string + */ + this._timeSignature = 4; + this._bpm = 60; -/** - * Stop the loop - * @method stop - * @for p5.SoundLoop - * @param {Number} [timeFromNow] schedule a stopping time - */ -p5.SoundLoop.prototype.stop = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (this.isPlaying) { - this.clock.stop(now + t); this.isPlaying = false; - } -}; -/** - * Pause the loop - * @method pause - * @for p5.SoundLoop - * @param {Number} [timeFromNow] schedule a pausing time - */ -p5.SoundLoop.prototype.pause = function (timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; - if (this.isPlaying) { - this.clock.pause(now + t); - this.isPlaying = false; - } -}; -/** - * Synchronize loops. Use this method to start two or more loops in synchronization - * or to start a loop in synchronization with a loop that is already playing - * This method will schedule the implicit loop in sync with the explicit master loop - * i.e. loopToStart.syncedStart(loopToSyncWith) - * - * @method syncedStart - * @for p5.SoundLoop - * @param {Object} otherLoop a p5.SoundLoop to sync with - * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds - */ -p5.SoundLoop.prototype.syncedStart = function (otherLoop, timeFromNow) { - var t = timeFromNow || 0; - var now = p5sound.audiocontext.currentTime; + /** + * Set a limit to the number of loops to play. defaults to Infinity + * @property {Number} maxIterations + */ + this.maxIterations = Infinity; + var self = this; - if (!otherLoop.isPlaying) { - otherLoop.clock.start(now + t); - otherLoop.isPlaying = true; - this.clock.start(now + t); - this.isPlaying = true; - } else if (otherLoop.isPlaying) { - var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime; - this.clock.start(now + time); - this.isPlaying = true; + this.clock = new Clock({ + callback: function (time) { + var timeFromNow = time - p5sound.audiocontext.currentTime; + /** + * Do not initiate the callback if timeFromNow is < 0 + * This ususually occurs for a few milliseconds when the page + * is not fully loaded + * + * The callback should only be called until maxIterations is reached + */ + if (timeFromNow > 0 && self.iterations <= self.maxIterations) { + self.callback(timeFromNow); + } + }, + frequency: this._calcFreq(), + }); } -}; -/** - * Updates frequency value, reflected in next callback - * @private - * @for p5.SoundLoop - * @method _update - */ -p5.SoundLoop.prototype._update = function () { - this.clock.frequency.value = this._calcFreq(); -}; - -/** - * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature - * @private - * @for p5.SoundLoop - * @method _calcFreq - * @return {Number} new clock frequency value - */ -p5.SoundLoop.prototype._calcFreq = function () { - //Seconds mode, bpm / timesignature has no effect - if (typeof this._interval === 'number') { - this.musicalTimeMode = false; - return 1 / this._interval; + /** + * Start the loop + * @method start + * @for p5.SoundLoop + * @param {Number} [timeFromNow] schedule a starting time + */ + start(timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (!this.isPlaying) { + this.clock.start(now + t); + this.isPlaying = true; + } } - //Musical timing mode, calculate interval based bpm, interval,and time signature - else if (typeof this._interval === 'string') { - this.musicalTimeMode = true; - return ( - (this._bpm / 60 / this._convertNotation(this._interval)) * - (this._timeSignature / 4) - ); + + /** + * Stop the loop + * @method stop + * @for p5.SoundLoop + * @param {Number} [timeFromNow] schedule a stopping time + */ + stop(timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (this.isPlaying) { + this.clock.stop(now + t); + this.isPlaying = false; + } } -}; -/** - * Convert notation from musical time format to seconds - * Uses Tone.Time convention - * @private - * @for p5.SoundLoop - * @method _convertNotation - * @param {String} value value to be converted - * @return {Number} converted value in seconds - */ -p5.SoundLoop.prototype._convertNotation = function (value) { - var type = value.slice(-1); - value = Number(value.slice(0, -1)); - switch (type) { - case 'm': - return this._measure(value); - case 'n': - return this._note(value); - default: - console.warn( - 'Specified interval is not formatted correctly. See Tone.js ' + - 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time' - ); + /** + * Pause the loop + * @method pause + * @for p5.SoundLoop + * @param {Number} [timeFromNow] schedule a pausing time + */ + pause(timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; + if (this.isPlaying) { + this.clock.pause(now + t); + this.isPlaying = false; + } } -}; -/** - * Helper conversion methods of measure and note - * @private - * @for p5.SoundLoop - * @method _measure - */ -p5.SoundLoop.prototype._measure = function (value) { - return value * this._timeSignature; -}; + /** + * Synchronize loops. Use this method to start two or more loops in synchronization + * or to start a loop in synchronization with a loop that is already playing + * This method will schedule the implicit loop in sync with the explicit master loop + * i.e. loopToStart.syncedStart(loopToSyncWith) + * + * @method syncedStart + * @for p5.SoundLoop + * @param {Object} otherLoop a p5.SoundLoop to sync with + * @param {Number} [timeFromNow] Start the loops in sync after timeFromNow seconds + */ + syncedStart(otherLoop, timeFromNow) { + var t = timeFromNow || 0; + var now = p5sound.audiocontext.currentTime; -/** - * @private - * @method _note - * @for p5.SoundLoop - */ -p5.SoundLoop.prototype._note = function (value) { - return this._timeSignature / value; -}; + if (!otherLoop.isPlaying) { + otherLoop.clock.start(now + t); + otherLoop.isPlaying = true; + this.clock.start(now + t); + this.isPlaying = true; + } else if (otherLoop.isPlaying) { + var time = otherLoop.clock._nextTick - p5sound.audiocontext.currentTime; + this.clock.start(now + time); + this.isPlaying = true; + } + } + /** + * Updates frequency value, reflected in next callback + * @private + * @for p5.SoundLoop + * @method _update + */ + _update() { + this.clock.frequency.value = this._calcFreq(); + } -/** - * Getters and Setters, setting any paramter will result in a change in the clock's - * frequency, that will be reflected after the next callback - * beats per minute (defaults to 60) - * @property {Number} bpm - * @for p5.SoundLoop - */ -Object.defineProperty(p5.SoundLoop.prototype, 'bpm', { - get: function () { - return this._bpm; - }, - set: function (bpm) { - if (!this.musicalTimeMode) { - console.warn( - 'Changing the BPM in "seconds" mode has no effect. ' + - 'BPM is only relevant in musicalTimeMode ' + - 'when the interval is specified as a string ' + - '("2n", "4n", "1m"...etc)' + /** + * Calculate the frequency of the clock's callback based on bpm, interval, and timesignature + * @private + * @for p5.SoundLoop + * @method _calcFreq + * @return {Number} new clock frequency value + */ + _calcFreq() { + //Seconds mode, bpm / timesignature has no effect + if (typeof this._interval === 'number') { + this.musicalTimeMode = false; + return 1 / this._interval; + } + //Musical timing mode, calculate interval based bpm, interval,and time signature + else if (typeof this._interval === 'string') { + this.musicalTimeMode = true; + return ( + (this._bpm / 60 / this._convertNotation(this._interval)) * + (this._timeSignature / 4) ); } - this._bpm = bpm; - this._update(); - }, -}); + } -/** - * number of quarter notes in a measure (defaults to 4) - * @property {Number} timeSignature - * @for p5.SoundLoop - */ -Object.defineProperty(p5.SoundLoop.prototype, 'timeSignature', { - get: function () { - return this._timeSignature; - }, - set: function (timeSig) { - if (!this.musicalTimeMode) { - console.warn( - 'Changing the timeSignature in "seconds" mode has no effect. ' + - 'BPM is only relevant in musicalTimeMode ' + - 'when the interval is specified as a string ' + - '("2n", "4n", "1m"...etc)' - ); + /** + * Convert notation from musical time format to seconds + * Uses Tone.Time convention + * @private + * @for p5.SoundLoop + * @method _convertNotation + * @param {String} value value to be converted + * @return {Number} converted value in seconds + */ + _convertNotation(value) { + var type = value.slice(-1); + value = Number(value.slice(0, -1)); + switch (type) { + case 'm': + return this._measure(value); + case 'n': + return this._note(value); + default: + console.warn( + 'Specified interval is not formatted correctly. See Tone.js ' + + 'timing reference for more info: https://github.com/Tonejs/Tone.js/wiki/Time' + ); } - this._timeSignature = timeSig; - this._update(); - }, -}); + } -/** - * length of the loops interval - * @property {Number|String} interval - * @for p5.SoundLoop - */ -Object.defineProperty(p5.SoundLoop.prototype, 'interval', { - get: function () { - return this._interval; - }, - set: function (interval) { - this.musicalTimeMode = typeof interval === 'number' ? false : true; - this._interval = interval; - this._update(); - }, -}); + /** + * Helper conversion methods of measure and note + * @private + * @for p5.SoundLoop + * @method _measure + */ + _measure(value) { + return value * this._timeSignature; + } -/** - * how many times the callback has been called so far - * @property {Number} iterations - * @for p5.SoundLoop - * @readonly - */ -Object.defineProperty(p5.SoundLoop.prototype, 'iterations', { - get: function () { - return this.clock.ticks; - }, -}); + /** + * @private + * @method _note + * @for p5.SoundLoop + */ + _note(value) { + return this._timeSignature / value; + } +} -export default p5.SoundLoop; +export default SoundLoop;