From 6f7595695a3c95bec585edc0daa865c18e36ba58 Mon Sep 17 00:00:00 2001
From: Divyanshu Raj
Date: Wed, 15 Jul 2020 06:35:40 +0530
Subject: [PATCH 1/3] replacement of es5 functions to es6 class def feat.P5.FFT
---
src/app.js | 3 +-
src/fft.js | 114 +++++++++++++++++++++++++++--------------------------
2 files changed, 60 insertions(+), 57 deletions(-)
diff --git a/src/app.js b/src/app.js
index 6bea179b..453309d6 100644
--- a/src/app.js
+++ b/src/app.js
@@ -8,7 +8,8 @@ import './audioWorklet';
import './panner';
import './soundfile';
import './amplitude';
-import './fft';
+import FFT from './fft';
+p5.FFT = FFT;
import './signal';
import './oscillator';
import './envelope';
diff --git a/src/fft.js b/src/fft.js
index 49bddc58..525d13ac 100644
--- a/src/fft.js
+++ b/src/fft.js
@@ -84,52 +84,54 @@ import p5sound from './master';
* }
*
*/
-p5.FFT = function (smoothing, bins) {
- this.input = this.analyser = p5sound.audiocontext.createAnalyser();
-
- Object.defineProperties(this, {
- bins: {
- get: function () {
- return this.analyser.fftSize / 2;
- },
- set: function (b) {
- this.analyser.fftSize = b * 2;
- },
- configurable: true,
- enumerable: true,
- },
- smoothing: {
- get: function () {
- return this.analyser.smoothingTimeConstant;
+class FFT {
+ constructor(smoothing, bins) {
+ this.input = this.analyser = p5sound.audiocontext.createAnalyser();
+
+ Object.defineProperties(this, {
+ bins: {
+ get: function () {
+ return this.analyser.fftSize / 2;
+ },
+ set: function (b) {
+ this.analyser.fftSize = b * 2;
+ },
+ configurable: true,
+ enumerable: true,
},
- set: function (s) {
- this.analyser.smoothingTimeConstant = s;
+ smoothing: {
+ get: function () {
+ return this.analyser.smoothingTimeConstant;
+ },
+ set: function (s) {
+ this.analyser.smoothingTimeConstant = s;
+ },
+ configurable: true,
+ enumerable: true,
},
- configurable: true,
- enumerable: true,
- },
- });
-
- // set default smoothing and bins
- this.smooth(smoothing);
- this.bins = bins || 1024;
-
- // default connections to p5sound fftMeter
- p5sound.fftMeter.connect(this.analyser);
-
- this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);
- this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);
-
- // predefined frequency ranges, these will be tweakable
- this.bass = [20, 140];
- this.lowMid = [140, 400];
- this.mid = [400, 2600];
- this.highMid = [2600, 5200];
- this.treble = [5200, 14000];
-
- // add this p5.SoundFile to the soundArray
- p5sound.soundArray.push(this);
-};
+ });
+
+ // set default smoothing and bins
+ this.smooth(smoothing);
+ this.bins = bins || 1024;
+
+ // default connections to p5sound fftMeter
+ p5sound.fftMeter.connect(this.analyser);
+
+ this.freqDomain = new Uint8Array(this.analyser.frequencyBinCount);
+ this.timeDomain = new Uint8Array(this.analyser.frequencyBinCount);
+
+ // predefined frequency ranges, these will be tweakable
+ this.bass = [20, 140];
+ this.lowMid = [140, 400];
+ this.mid = [400, 2600];
+ this.highMid = [2600, 5200];
+ this.treble = [5200, 14000];
+
+ // add this p5.SoundFile to the soundArray
+ p5sound.soundArray.push(this);
+ }
+}
/**
* Set the input source for the FFT analysis. If no source is
@@ -139,7 +141,7 @@ p5.FFT = function (smoothing, bins) {
* @for p5.FFT
* @param {Object} [source] p5.sound object (or web audio API source node)
*/
-p5.FFT.prototype.setInput = function (source) {
+FFT.prototype.setInput = function (source) {
if (!source) {
p5sound.fftMeter.connect(this.analyser);
} else {
@@ -169,7 +171,7 @@ p5.FFT.prototype.setInput = function (source) {
* over time. Array length = bins.
*
*/
-p5.FFT.prototype.waveform = function () {
+FFT.prototype.waveform = function () {
var bins, mode;
var normalArray = new Array();
@@ -268,7 +270,7 @@ p5.FFT.prototype.waveform = function () {
*
*
*/
-p5.FFT.prototype.analyze = function () {
+FFT.prototype.analyze = function () {
var mode;
for (var i = 0; i < arguments.length; i++) {
@@ -323,7 +325,7 @@ p5.FFT.prototype.analyze = function () {
* 0 and 255.
*
*/
-p5.FFT.prototype.getEnergy = function (frequency1, frequency2) {
+FFT.prototype.getEnergy = function (frequency1, frequency2) {
var nyquist = p5sound.audiocontext.sampleRate / 2;
if (frequency1 === 'bass') {
@@ -376,7 +378,7 @@ p5.FFT.prototype.getEnergy = function (frequency1, frequency2) {
};
// compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...
-p5.FFT.prototype.getFreq = function (freq1, freq2) {
+FFT.prototype.getFreq = function (freq1, freq2) {
console.log('getFreq() is deprecated. Please use getEnergy() instead.');
var x = this.getEnergy(freq1, freq2);
return x;
@@ -447,7 +449,7 @@ p5.FFT.prototype.getFreq = function (freq1, freq2) {
*}
*
*/
-p5.FFT.prototype.getCentroid = function () {
+FFT.prototype.getCentroid = function () {
var nyquist = p5sound.audiocontext.sampleRate / 2;
var cumulative_sum = 0;
var centroid_normalization = 0;
@@ -474,14 +476,14 @@ p5.FFT.prototype.getCentroid = function () {
* @param {Number} smoothing 0.0 < smoothing < 1.0.
* Defaults to 0.8.
*/
-p5.FFT.prototype.smooth = function (s) {
+FFT.prototype.smooth = function (s) {
if (typeof s !== 'undefined') {
this.smoothing = s;
}
return this.smoothing;
};
-p5.FFT.prototype.dispose = function () {
+FFT.prototype.dispose = function () {
// remove reference from soundArray
var index = p5sound.soundArray.indexOf(this);
p5sound.soundArray.splice(index, 1);
@@ -504,7 +506,7 @@ p5.FFT.prototype.dispose = function () {
* @param {Number} N Number of returned frequency groups
* @return {Array} linearAverages Array of average amplitude values for each group
*/
-p5.FFT.prototype.linAverages = function (_N) {
+FFT.prototype.linAverages = function (_N) {
var N = _N || 16; // This prevents undefined, null or 0 values of N
var spectrum = this.freqDomain;
@@ -544,7 +546,7 @@ p5.FFT.prototype.linAverages = function (_N) {
* @param {Array} octaveBands Array of Octave Bands objects for grouping
* @return {Array} logAverages Array of average amplitude values for each group
*/
-p5.FFT.prototype.logAverages = function (octaveBands) {
+FFT.prototype.logAverages = function (octaveBands) {
var nyquist = p5sound.audiocontext.sampleRate / 2;
var spectrum = this.freqDomain;
var spectrumLength = spectrum.length;
@@ -587,7 +589,7 @@ p5.FFT.prototype.logAverages = function (octaveBands) {
* @param {Number} fCtr0 Minimum central frequency for the lowest band
* @return {Array} octaveBands Array of octave band objects with their bounds
*/
-p5.FFT.prototype.getOctaveBands = function (_N, _fCtr0) {
+FFT.prototype.getOctaveBands = function (_N, _fCtr0) {
var N = _N || 3; // Default to 1/3 Octave Bands
var fCtr0 = _fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz
@@ -635,4 +637,4 @@ function timeToInt(fft) {
}
}
-export default p5.FFT;
+export default FFT;
From 923707e3a0ed73506785ec7d5b0727d24654ebf4 Mon Sep 17 00:00:00 2001
From: Divyanshu Raj
Date: Fri, 17 Jul 2020 06:23:21 +0530
Subject: [PATCH 2/3] added class methods inside of declaration, facilating
autoboxing
---
src/fft.js | 894 +++++++++++++++++++++++++++--------------------------
1 file changed, 450 insertions(+), 444 deletions(-)
diff --git a/src/fft.js b/src/fft.js
index 525d13ac..153d0548 100644
--- a/src/fft.js
+++ b/src/fft.js
@@ -131,489 +131,495 @@ class FFT {
// add this p5.SoundFile to the soundArray
p5sound.soundArray.push(this);
}
-}
-/**
- * Set the input source for the FFT analysis. If no source is
- * provided, FFT will analyze all sound in the sketch.
- *
- * @method setInput
- * @for p5.FFT
- * @param {Object} [source] p5.sound object (or web audio API source node)
- */
-FFT.prototype.setInput = function (source) {
- if (!source) {
- p5sound.fftMeter.connect(this.analyser);
- } else {
- if (source.output) {
- source.output.connect(this.analyser);
- } else if (source.connect) {
- source.connect(this.analyser);
+ /**
+ * Set the input source for the FFT analysis. If no source is
+ * provided, FFT will analyze all sound in the sketch.
+ *
+ * @method setInput
+ * @for p5.FFT
+ * @param {Object} [source] p5.sound object (or web audio API source node)
+ */
+ setInput(source) {
+ if (!source) {
+ p5sound.fftMeter.connect(this.analyser);
+ } else {
+ if (source.output) {
+ source.output.connect(this.analyser);
+ } else if (source.connect) {
+ source.connect(this.analyser);
+ }
+ p5sound.fftMeter.disconnect();
}
- p5sound.fftMeter.disconnect();
}
-};
-/**
- * Returns an array of amplitude values (between -1.0 and +1.0) that represent
- * a snapshot of amplitude readings in a single buffer. Length will be
- * equal to bins (defaults to 1024). Can be used to draw the waveform
- * of a sound.
- *
- * @method waveform
- * @for p5.FFT
- * @param {Number} [bins] Must be a power of two between
- * 16 and 1024. Defaults to 1024.
- * @param {String} [precision] If any value is provided, will return results
- * in a Float32 Array which is more precise
- * than a regular array.
- * @return {Array} Array Array of amplitude values (-1 to 1)
- * over time. Array length = bins.
- *
- */
-FFT.prototype.waveform = function () {
- var bins, mode;
- var normalArray = new Array();
-
- for (var i = 0; i < arguments.length; i++) {
- if (typeof arguments[i] === 'number') {
- bins = arguments[i];
- this.analyser.fftSize = bins * 2;
+ /**
+ * Returns an array of amplitude values (between -1.0 and +1.0) that represent
+ * a snapshot of amplitude readings in a single buffer. Length will be
+ * equal to bins (defaults to 1024). Can be used to draw the waveform
+ * of a sound.
+ *
+ * @method waveform
+ * @for p5.FFT
+ * @param {Number} [bins] Must be a power of two between
+ * 16 and 1024. Defaults to 1024.
+ * @param {String} [precision] If any value is provided, will return results
+ * in a Float32 Array which is more precise
+ * than a regular array.
+ * @return {Array} Array Array of amplitude values (-1 to 1)
+ * over time. Array length = bins.
+ *
+ */
+ waveform() {
+ var bins, mode;
+ var normalArray = new Array();
+
+ for (var i = 0; i < arguments.length; i++) {
+ if (typeof arguments[i] === 'number') {
+ bins = arguments[i];
+ this.analyser.fftSize = bins * 2;
+ }
+ if (typeof arguments[i] === 'string') {
+ mode = arguments[i];
+ }
}
- if (typeof arguments[i] === 'string') {
- mode = arguments[i];
+
+ // getFloatFrequencyData doesnt work in Safari as of 5/2015
+ if (mode && !p5.prototype._isSafari()) {
+ timeToFloat(this, this.timeDomain);
+ this.analyser.getFloatTimeDomainData(this.timeDomain);
+ return this.timeDomain;
+ } else {
+ timeToInt(this, this.timeDomain);
+ this.analyser.getByteTimeDomainData(this.timeDomain);
+ for (var j = 0; j < this.timeDomain.length; j++) {
+ var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);
+ normalArray.push(scaled);
+ }
+ return normalArray;
}
}
- // getFloatFrequencyData doesnt work in Safari as of 5/2015
- if (mode && !p5.prototype._isSafari()) {
- timeToFloat(this, this.timeDomain);
- this.analyser.getFloatTimeDomainData(this.timeDomain);
- return this.timeDomain;
- } else {
- timeToInt(this, this.timeDomain);
- this.analyser.getByteTimeDomainData(this.timeDomain);
- for (var j = 0; j < this.timeDomain.length; j++) {
- var scaled = p5.prototype.map(this.timeDomain[j], 0, 255, -1, 1);
- normalArray.push(scaled);
+ /**
+ * Returns an array of amplitude values (between 0 and 255)
+ * across the frequency spectrum. Length is equal to FFT bins
+ * (1024 by default). The array indices correspond to frequencies
+ * (i.e. pitches), from the lowest to the highest that humans can
+ * hear. Each value represents amplitude at that slice of the
+ * frequency spectrum. Must be called prior to using
+ * getEnergy()
.
+ *
+ * @method analyze
+ * @for p5.FFT
+ * @param {Number} [bins] Must be a power of two between
+ * 16 and 1024. Defaults to 1024.
+ * @param {Number} [scale] If "dB," returns decibel
+ * float measurements between
+ * -140 and 0 (max).
+ * Otherwise returns integers from 0-255.
+ * @return {Array} spectrum Array of energy (amplitude/volume)
+ * values across the frequency spectrum.
+ * Lowest energy (silence) = 0, highest
+ * possible is 255.
+ * @example
+ *
+ * let osc, fft;
+ *
+ * function setup(){
+ * let cnv = createCanvas(100,100);
+ * cnv.mousePressed(startSound);
+ * osc = new p5.Oscillator();
+ * osc.amp(0);
+ * fft = new p5.FFT();
+ * }
+ *
+ * function draw(){
+ * background(220);
+ *
+ * let freq = map(mouseX, 0, windowWidth, 20, 10000);
+ * freq = constrain(freq, 1, 20000);
+ * osc.freq(freq);
+ *
+ * let spectrum = fft.analyze();
+ * noStroke();
+ * fill(255, 0, 255);
+ * for (let i = 0; i< spectrum.length; i++){
+ * let x = map(i, 0, spectrum.length, 0, width);
+ * let h = -height + map(spectrum[i], 0, 255, height, 0);
+ * rect(x, height, width / spectrum.length, h );
+ * }
+ *
+ * stroke(255);
+ * if (!osc.started) {
+ * text('tap here and drag to change frequency', 10, 20, width - 20);
+ * } else {
+ * text(round(freq)+'Hz', 10, 20);
+ * }
+ * }
+ *
+ * function startSound() {
+ * osc.start();
+ * osc.amp(0.5, 0.2);
+ * }
+ *
+ * function mouseReleased() {
+ * osc.amp(0, 0.2);
+ * }
+ *
+ *
+ *
+ */
+ analyze() {
+ var mode;
+
+ for (var i = 0; i < arguments.length; i++) {
+ if (typeof arguments[i] === 'number') {
+ this.bins = arguments[i];
+ this.analyser.fftSize = this.bins * 2;
+ }
+ if (typeof arguments[i] === 'string') {
+ mode = arguments[i];
+ }
}
- return normalArray;
- }
-};
-/**
- * Returns an array of amplitude values (between 0 and 255)
- * across the frequency spectrum. Length is equal to FFT bins
- * (1024 by default). The array indices correspond to frequencies
- * (i.e. pitches), from the lowest to the highest that humans can
- * hear. Each value represents amplitude at that slice of the
- * frequency spectrum. Must be called prior to using
- * getEnergy()
.
- *
- * @method analyze
- * @for p5.FFT
- * @param {Number} [bins] Must be a power of two between
- * 16 and 1024. Defaults to 1024.
- * @param {Number} [scale] If "dB," returns decibel
- * float measurements between
- * -140 and 0 (max).
- * Otherwise returns integers from 0-255.
- * @return {Array} spectrum Array of energy (amplitude/volume)
- * values across the frequency spectrum.
- * Lowest energy (silence) = 0, highest
- * possible is 255.
- * @example
- *
- * let osc, fft;
- *
- * function setup(){
- * let cnv = createCanvas(100,100);
- * cnv.mousePressed(startSound);
- * osc = new p5.Oscillator();
- * osc.amp(0);
- * fft = new p5.FFT();
- * }
- *
- * function draw(){
- * background(220);
- *
- * let freq = map(mouseX, 0, windowWidth, 20, 10000);
- * freq = constrain(freq, 1, 20000);
- * osc.freq(freq);
- *
- * let spectrum = fft.analyze();
- * noStroke();
- * fill(255, 0, 255);
- * for (let i = 0; i< spectrum.length; i++){
- * let x = map(i, 0, spectrum.length, 0, width);
- * let h = -height + map(spectrum[i], 0, 255, height, 0);
- * rect(x, height, width / spectrum.length, h );
- * }
- *
- * stroke(255);
- * if (!osc.started) {
- * text('tap here and drag to change frequency', 10, 20, width - 20);
- * } else {
- * text(round(freq)+'Hz', 10, 20);
- * }
- * }
- *
- * function startSound() {
- * osc.start();
- * osc.amp(0.5, 0.2);
- * }
- *
- * function mouseReleased() {
- * osc.amp(0, 0.2);
- * }
- *
- *
- *
- */
-FFT.prototype.analyze = function () {
- var mode;
+ if (mode && mode.toLowerCase() === 'db') {
+ freqToFloat(this);
+ this.analyser.getFloatFrequencyData(this.freqDomain);
+ return this.freqDomain;
+ } else {
+ freqToInt(this, this.freqDomain);
+ this.analyser.getByteFrequencyData(this.freqDomain);
+ var normalArray = Array.apply([], this.freqDomain);
- for (var i = 0; i < arguments.length; i++) {
- if (typeof arguments[i] === 'number') {
- this.bins = arguments[i];
- this.analyser.fftSize = this.bins * 2;
- }
- if (typeof arguments[i] === 'string') {
- mode = arguments[i];
+ return normalArray;
}
}
- if (mode && mode.toLowerCase() === 'db') {
- freqToFloat(this);
- this.analyser.getFloatFrequencyData(this.freqDomain);
- return this.freqDomain;
- } else {
- freqToInt(this, this.freqDomain);
- this.analyser.getByteFrequencyData(this.freqDomain);
- var normalArray = Array.apply([], this.freqDomain);
+ /**
+ * Returns the amount of energy (volume) at a specific
+ *
+ * frequency, or the average amount of energy between two
+ * frequencies. Accepts Number(s) corresponding
+ * to frequency (in Hz), or a String corresponding to predefined
+ * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble").
+ * Returns a range between 0 (no energy/volume at that frequency) and
+ * 255 (maximum energy).
+ * NOTE: analyze() must be called prior to getEnergy(). Analyze()
+ * tells the FFT to analyze frequency data, and getEnergy() uses
+ * the results determine the value at a specific frequency or
+ * range of frequencies.
+ *
+ * @method getEnergy
+ * @for p5.FFT
+ * @param {Number|String} frequency1 Will return a value representing
+ * energy at this frequency. Alternately,
+ * the strings "bass", "lowMid" "mid",
+ * "highMid", and "treble" will return
+ * predefined frequency ranges.
+ * @param {Number} [frequency2] If a second frequency is given,
+ * will return average amount of
+ * energy that exists between the
+ * two frequencies.
+ * @return {Number} Energy Energy (volume/amplitude) from
+ * 0 and 255.
+ *
+ */
+ getEnergy(frequency1, frequency2) {
+ var nyquist = p5sound.audiocontext.sampleRate / 2;
+
+ if (frequency1 === 'bass') {
+ frequency1 = this.bass[0];
+ frequency2 = this.bass[1];
+ } else if (frequency1 === 'lowMid') {
+ frequency1 = this.lowMid[0];
+ frequency2 = this.lowMid[1];
+ } else if (frequency1 === 'mid') {
+ frequency1 = this.mid[0];
+ frequency2 = this.mid[1];
+ } else if (frequency1 === 'highMid') {
+ frequency1 = this.highMid[0];
+ frequency2 = this.highMid[1];
+ } else if (frequency1 === 'treble') {
+ frequency1 = this.treble[0];
+ frequency2 = this.treble[1];
+ }
- return normalArray;
+ if (typeof frequency1 !== 'number') {
+ throw 'invalid input for getEnergy()';
+ } else if (!frequency2) {
+ // if only one parameter:
+ var index = Math.round((frequency1 / nyquist) * this.freqDomain.length);
+ return this.freqDomain[index];
+ } else if (frequency1 && frequency2) {
+ // if two parameters:
+ // if second is higher than first
+ if (frequency1 > frequency2) {
+ var swap = frequency2;
+ frequency2 = frequency1;
+ frequency1 = swap;
+ }
+ var lowIndex = Math.round(
+ (frequency1 / nyquist) * this.freqDomain.length
+ );
+ var highIndex = Math.round(
+ (frequency2 / nyquist) * this.freqDomain.length
+ );
+
+ var total = 0;
+ var numFrequencies = 0;
+ // add up all of the values for the frequencies
+ for (var i = lowIndex; i <= highIndex; i++) {
+ total += this.freqDomain[i];
+ numFrequencies += 1;
+ }
+ // divide by total number of frequencies
+ var toReturn = total / numFrequencies;
+ return toReturn;
+ } else {
+ throw 'invalid input for getEnergy()';
+ }
}
-};
-/**
- * Returns the amount of energy (volume) at a specific
- *
- * frequency, or the average amount of energy between two
- * frequencies. Accepts Number(s) corresponding
- * to frequency (in Hz), or a String corresponding to predefined
- * frequency ranges ("bass", "lowMid", "mid", "highMid", "treble").
- * Returns a range between 0 (no energy/volume at that frequency) and
- * 255 (maximum energy).
- * NOTE: analyze() must be called prior to getEnergy(). Analyze()
- * tells the FFT to analyze frequency data, and getEnergy() uses
- * the results determine the value at a specific frequency or
- * range of frequencies.
- *
- * @method getEnergy
- * @for p5.FFT
- * @param {Number|String} frequency1 Will return a value representing
- * energy at this frequency. Alternately,
- * the strings "bass", "lowMid" "mid",
- * "highMid", and "treble" will return
- * predefined frequency ranges.
- * @param {Number} [frequency2] If a second frequency is given,
- * will return average amount of
- * energy that exists between the
- * two frequencies.
- * @return {Number} Energy Energy (volume/amplitude) from
- * 0 and 255.
- *
- */
-FFT.prototype.getEnergy = function (frequency1, frequency2) {
- var nyquist = p5sound.audiocontext.sampleRate / 2;
-
- if (frequency1 === 'bass') {
- frequency1 = this.bass[0];
- frequency2 = this.bass[1];
- } else if (frequency1 === 'lowMid') {
- frequency1 = this.lowMid[0];
- frequency2 = this.lowMid[1];
- } else if (frequency1 === 'mid') {
- frequency1 = this.mid[0];
- frequency2 = this.mid[1];
- } else if (frequency1 === 'highMid') {
- frequency1 = this.highMid[0];
- frequency2 = this.highMid[1];
- } else if (frequency1 === 'treble') {
- frequency1 = this.treble[0];
- frequency2 = this.treble[1];
+ // compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...
+ getFreq(freq1, freq2) {
+ console.log('getFreq() is deprecated. Please use getEnergy() instead.');
+ var x = this.getEnergy(freq1, freq2);
+ return x;
}
- if (typeof frequency1 !== 'number') {
- throw 'invalid input for getEnergy()';
- } else if (!frequency2) {
- // if only one parameter:
- var index = Math.round((frequency1 / nyquist) * this.freqDomain.length);
- return this.freqDomain[index];
- } else if (frequency1 && frequency2) {
- // if two parameters:
- // if second is higher than first
- if (frequency1 > frequency2) {
- var swap = frequency2;
- frequency2 = frequency1;
- frequency1 = swap;
- }
- var lowIndex = Math.round((frequency1 / nyquist) * this.freqDomain.length);
- var highIndex = Math.round((frequency2 / nyquist) * this.freqDomain.length);
-
- var total = 0;
- var numFrequencies = 0;
- // add up all of the values for the frequencies
- for (var i = lowIndex; i <= highIndex; i++) {
- total += this.freqDomain[i];
- numFrequencies += 1;
+ /**
+ * Returns the
+ *
+ * spectral centroid of the input signal.
+ * NOTE: analyze() must be called prior to getCentroid(). Analyze()
+ * tells the FFT to analyze frequency data, and getCentroid() uses
+ * the results determine the spectral centroid.
+ *
+ * @method getCentroid
+ * @for p5.FFT
+ * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz.
+ *
+ *
+ * @example
+ *
+ * function setup(){
+ * cnv = createCanvas(100,100);
+ * cnv.mousePressed(userStartAudio);
+ * sound = new p5.AudioIn();
+ * sound.start();
+ * fft = new p5.FFT();
+ * sound.connect(fft);
+ *}
+ *
+ *function draw() {
+ * if (getAudioContext().state !== 'running') {
+ * background(220);
+ * text('tap here and enable mic to begin', 10, 20, width - 20);
+ * return;
+ * }
+ * let centroidplot = 0.0;
+ * let spectralCentroid = 0;
+ *
+ * background(0);
+ * stroke(0,255,0);
+ * let spectrum = fft.analyze();
+ * fill(0,255,0); // spectrum is green
+ *
+ * //draw the spectrum
+ * for (let i = 0; i < spectrum.length; i++){
+ * let x = map(log(i), 0, log(spectrum.length), 0, width);
+ * let h = map(spectrum[i], 0, 255, 0, height);
+ * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));
+ * rect(x, height, rectangle_width, -h )
+ * }
+ * let nyquist = 22050;
+ *
+ * // get the centroid
+ * spectralCentroid = fft.getCentroid();
+ *
+ * // the mean_freq_index calculation is for the display.
+ * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length);
+ *
+ * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);
+ *
+ * stroke(255,0,0); // the line showing where the centroid is will be red
+ *
+ * rect(centroidplot, 0, width / spectrum.length, height)
+ * noStroke();
+ * fill(255,255,255); // text is white
+ * text('centroid: ', 10, 20);
+ * text(round(spectralCentroid)+' Hz', 10, 40);
+ *}
+ *
+ */
+ getCentroid() {
+ var nyquist = p5sound.audiocontext.sampleRate / 2;
+ var cumulative_sum = 0;
+ var centroid_normalization = 0;
+
+ for (var i = 0; i < this.freqDomain.length; i++) {
+ cumulative_sum += i * this.freqDomain[i];
+ centroid_normalization += this.freqDomain[i];
}
- // divide by total number of frequencies
- var toReturn = total / numFrequencies;
- return toReturn;
- } else {
- throw 'invalid input for getEnergy()';
- }
-};
-// compatability with v.012, changed to getEnergy in v.0121. Will be deprecated...
-FFT.prototype.getFreq = function (freq1, freq2) {
- console.log('getFreq() is deprecated. Please use getEnergy() instead.');
- var x = this.getEnergy(freq1, freq2);
- return x;
-};
+ var mean_freq_index = 0;
-/**
- * Returns the
- *
- * spectral centroid of the input signal.
- * NOTE: analyze() must be called prior to getCentroid(). Analyze()
- * tells the FFT to analyze frequency data, and getCentroid() uses
- * the results determine the spectral centroid.
- *
- * @method getCentroid
- * @for p5.FFT
- * @return {Number} Spectral Centroid Frequency of the spectral centroid in Hz.
- *
- *
- * @example
- *
- * function setup(){
- * cnv = createCanvas(100,100);
- * cnv.mousePressed(userStartAudio);
- * sound = new p5.AudioIn();
- * sound.start();
- * fft = new p5.FFT();
- * sound.connect(fft);
- *}
- *
- *function draw() {
- * if (getAudioContext().state !== 'running') {
- * background(220);
- * text('tap here and enable mic to begin', 10, 20, width - 20);
- * return;
- * }
- * let centroidplot = 0.0;
- * let spectralCentroid = 0;
- *
- * background(0);
- * stroke(0,255,0);
- * let spectrum = fft.analyze();
- * fill(0,255,0); // spectrum is green
- *
- * //draw the spectrum
- * for (let i = 0; i < spectrum.length; i++){
- * let x = map(log(i), 0, log(spectrum.length), 0, width);
- * let h = map(spectrum[i], 0, 255, 0, height);
- * let rectangle_width = (log(i+1)-log(i))*(width/log(spectrum.length));
- * rect(x, height, rectangle_width, -h )
- * }
- * let nyquist = 22050;
- *
- * // get the centroid
- * spectralCentroid = fft.getCentroid();
- *
- * // the mean_freq_index calculation is for the display.
- * let mean_freq_index = spectralCentroid/(nyquist/spectrum.length);
- *
- * centroidplot = map(log(mean_freq_index), 0, log(spectrum.length), 0, width);
- *
- * stroke(255,0,0); // the line showing where the centroid is will be red
- *
- * rect(centroidplot, 0, width / spectrum.length, height)
- * noStroke();
- * fill(255,255,255); // text is white
- * text('centroid: ', 10, 20);
- * text(round(spectralCentroid)+' Hz', 10, 40);
- *}
- *
- */
-FFT.prototype.getCentroid = function () {
- var nyquist = p5sound.audiocontext.sampleRate / 2;
- var cumulative_sum = 0;
- var centroid_normalization = 0;
-
- for (var i = 0; i < this.freqDomain.length; i++) {
- cumulative_sum += i * this.freqDomain[i];
- centroid_normalization += this.freqDomain[i];
- }
-
- var mean_freq_index = 0;
+ if (centroid_normalization !== 0) {
+ mean_freq_index = cumulative_sum / centroid_normalization;
+ }
- if (centroid_normalization !== 0) {
- mean_freq_index = cumulative_sum / centroid_normalization;
+ var spec_centroid_freq =
+ mean_freq_index * (nyquist / this.freqDomain.length);
+ return spec_centroid_freq;
}
- var spec_centroid_freq = mean_freq_index * (nyquist / this.freqDomain.length);
- return spec_centroid_freq;
-};
-
-/**
- * Smooth FFT analysis by averaging with the last analysis frame.
- *
- * @method smooth
- * @param {Number} smoothing 0.0 < smoothing < 1.0.
- * Defaults to 0.8.
- */
-FFT.prototype.smooth = function (s) {
- if (typeof s !== 'undefined') {
- this.smoothing = s;
+ /**
+ * Smooth FFT analysis by averaging with the last analysis frame.
+ *
+ * @method smooth
+ * @param {Number} smoothing 0.0 < smoothing < 1.0.
+ * Defaults to 0.8.
+ */
+ smooth(s) {
+ if (typeof s !== 'undefined') {
+ this.smoothing = s;
+ }
+ return this.smoothing;
}
- return this.smoothing;
-};
-FFT.prototype.dispose = function () {
- // remove reference from soundArray
- var index = p5sound.soundArray.indexOf(this);
- p5sound.soundArray.splice(index, 1);
+ dispose() {
+ // remove reference from soundArray
+ var index = p5sound.soundArray.indexOf(this);
+ p5sound.soundArray.splice(index, 1);
- if (this.analyser) {
- this.analyser.disconnect();
- delete this.analyser;
+ if (this.analyser) {
+ this.analyser.disconnect();
+ delete this.analyser;
+ }
}
-};
-/**
- * Returns an array of average amplitude values for a given number
- * of frequency bands split equally. N defaults to 16.
- * NOTE: analyze() must be called prior to linAverages(). Analyze()
- * tells the FFT to analyze frequency data, and linAverages() uses
- * the results to group them into a smaller set of averages.
- *
- * @method linAverages
- * @for p5.FFT
- * @param {Number} N Number of returned frequency groups
- * @return {Array} linearAverages Array of average amplitude values for each group
- */
-FFT.prototype.linAverages = function (_N) {
- var N = _N || 16; // This prevents undefined, null or 0 values of N
-
- var spectrum = this.freqDomain;
- var spectrumLength = spectrum.length;
- var spectrumStep = Math.floor(spectrumLength / N);
-
- var linearAverages = new Array(N);
- // Keep a second index for the current average group and place the values accordingly
- // with only one loop in the spectrum data
- var groupIndex = 0;
-
- for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {
- linearAverages[groupIndex] =
- linearAverages[groupIndex] !== undefined
- ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2
- : spectrum[specIndex];
-
- // Increase the group index when the last element of the group is processed
- if (specIndex % spectrumStep === spectrumStep - 1) {
- groupIndex++;
+ /**
+ * Returns an array of average amplitude values for a given number
+ * of frequency bands split equally. N defaults to 16.
+ * NOTE: analyze() must be called prior to linAverages(). Analyze()
+ * tells the FFT to analyze frequency data, and linAverages() uses
+ * the results to group them into a smaller set of averages.
+ *
+ * @method linAverages
+ * @for p5.FFT
+ * @param {Number} N Number of returned frequency groups
+ * @return {Array} linearAverages Array of average amplitude values for each group
+ */
+
+ linAverages(_N) {
+ var N = _N || 16; // This prevents undefined, null or 0 values of N
+
+ var spectrum = this.freqDomain;
+ var spectrumLength = spectrum.length;
+ var spectrumStep = Math.floor(spectrumLength / N);
+
+ var linearAverages = new Array(N);
+ // Keep a second index for the current average group and place the values accordingly
+ // with only one loop in the spectrum data
+ var groupIndex = 0;
+
+ for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {
+ linearAverages[groupIndex] =
+ linearAverages[groupIndex] !== undefined
+ ? (linearAverages[groupIndex] + spectrum[specIndex]) / 2
+ : spectrum[specIndex];
+
+ // Increase the group index when the last element of the group is processed
+ if (specIndex % spectrumStep === spectrumStep - 1) {
+ groupIndex++;
+ }
}
- }
- return linearAverages;
-};
+ return linearAverages;
+ }
-/**
- * Returns an array of average amplitude values of the spectrum, for a given
- * set of
- * Octave Bands
- * NOTE: analyze() must be called prior to logAverages(). Analyze()
- * tells the FFT to analyze frequency data, and logAverages() uses
- * the results to group them into a smaller set of averages.
- *
- * @method logAverages
- * @for p5.FFT
- * @param {Array} octaveBands Array of Octave Bands objects for grouping
- * @return {Array} logAverages Array of average amplitude values for each group
- */
-FFT.prototype.logAverages = function (octaveBands) {
- var nyquist = p5sound.audiocontext.sampleRate / 2;
- var spectrum = this.freqDomain;
- var spectrumLength = spectrum.length;
-
- var logAverages = new Array(octaveBands.length);
- // Keep a second index for the current average group and place the values accordingly
- // With only one loop in the spectrum data
- var octaveIndex = 0;
-
- for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {
- var specIndexFrequency = Math.round(
- (specIndex * nyquist) / this.freqDomain.length
- );
-
- // Increase the group index if the current frequency exceeds the limits of the band
- if (specIndexFrequency > octaveBands[octaveIndex].hi) {
- octaveIndex++;
+ /**
+ * Returns an array of average amplitude values of the spectrum, for a given
+ * set of
+ * Octave Bands
+ * NOTE: analyze() must be called prior to logAverages(). Analyze()
+ * tells the FFT to analyze frequency data, and logAverages() uses
+ * the results to group them into a smaller set of averages.
+ *
+ * @method logAverages
+ * @for p5.FFT
+ * @param {Array} octaveBands Array of Octave Bands objects for grouping
+ * @return {Array} logAverages Array of average amplitude values for each group
+ */
+ logAverages(octaveBands) {
+ var nyquist = p5sound.audiocontext.sampleRate / 2;
+ var spectrum = this.freqDomain;
+ var spectrumLength = spectrum.length;
+
+ var logAverages = new Array(octaveBands.length);
+ // Keep a second index for the current average group and place the values accordingly
+ // With only one loop in the spectrum data
+ var octaveIndex = 0;
+
+ for (var specIndex = 0; specIndex < spectrumLength; specIndex++) {
+ var specIndexFrequency = Math.round(
+ (specIndex * nyquist) / this.freqDomain.length
+ );
+
+ // Increase the group index if the current frequency exceeds the limits of the band
+ if (specIndexFrequency > octaveBands[octaveIndex].hi) {
+ octaveIndex++;
+ }
+
+ logAverages[octaveIndex] =
+ logAverages[octaveIndex] !== undefined
+ ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2
+ : spectrum[specIndex];
}
- logAverages[octaveIndex] =
- logAverages[octaveIndex] !== undefined
- ? (logAverages[octaveIndex] + spectrum[specIndex]) / 2
- : spectrum[specIndex];
+ return logAverages;
}
- return logAverages;
-};
+ /**
+ * Calculates and Returns the 1/N
+ * Octave Bands
+ * N defaults to 3 and minimum central frequency to 15.625Hz.
+ * (1/3 Octave Bands ~= 31 Frequency Bands)
+ * Setting fCtr0 to a central value of a higher octave will ignore the lower bands
+ * and produce less frequency groups.
+ *
+ * @method getOctaveBands
+ * @for p5.FFT
+ * @param {Number} N Specifies the 1/N type of generated octave bands
+ * @param {Number} fCtr0 Minimum central frequency for the lowest band
+ * @return {Array} octaveBands Array of octave band objects with their bounds
+ */
+ getOctaveBands(_N, _fCtr0) {
+ var N = _N || 3; // Default to 1/3 Octave Bands
+ var fCtr0 = _fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz
+
+ var octaveBands = [];
+ var lastFrequencyBand = {
+ lo: fCtr0 / Math.pow(2, 1 / (2 * N)),
+ ctr: fCtr0,
+ hi: fCtr0 * Math.pow(2, 1 / (2 * N)),
+ };
+ octaveBands.push(lastFrequencyBand);
+
+ var nyquist = p5sound.audiocontext.sampleRate / 2;
+ while (lastFrequencyBand.hi < nyquist) {
+ var newFrequencyBand = {};
+ newFrequencyBand.lo = lastFrequencyBand.hi;
+ newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);
+ newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));
+
+ octaveBands.push(newFrequencyBand);
+ lastFrequencyBand = newFrequencyBand;
+ }
-/**
- * Calculates and Returns the 1/N
- * Octave Bands
- * N defaults to 3 and minimum central frequency to 15.625Hz.
- * (1/3 Octave Bands ~= 31 Frequency Bands)
- * Setting fCtr0 to a central value of a higher octave will ignore the lower bands
- * and produce less frequency groups.
- *
- * @method getOctaveBands
- * @for p5.FFT
- * @param {Number} N Specifies the 1/N type of generated octave bands
- * @param {Number} fCtr0 Minimum central frequency for the lowest band
- * @return {Array} octaveBands Array of octave band objects with their bounds
- */
-FFT.prototype.getOctaveBands = function (_N, _fCtr0) {
- var N = _N || 3; // Default to 1/3 Octave Bands
- var fCtr0 = _fCtr0 || 15.625; // Minimum central frequency, defaults to 15.625Hz
-
- var octaveBands = [];
- var lastFrequencyBand = {
- lo: fCtr0 / Math.pow(2, 1 / (2 * N)),
- ctr: fCtr0,
- hi: fCtr0 * Math.pow(2, 1 / (2 * N)),
- };
- octaveBands.push(lastFrequencyBand);
-
- var nyquist = p5sound.audiocontext.sampleRate / 2;
- while (lastFrequencyBand.hi < nyquist) {
- var newFrequencyBand = {};
- newFrequencyBand.lo = lastFrequencyBand.hi;
- newFrequencyBand.ctr = lastFrequencyBand.ctr * Math.pow(2, 1 / N);
- newFrequencyBand.hi = newFrequencyBand.ctr * Math.pow(2, 1 / (2 * N));
-
- octaveBands.push(newFrequencyBand);
- lastFrequencyBand = newFrequencyBand;
+ return octaveBands;
}
-
- return octaveBands;
-};
+}
// helper methods to convert type from float (dB) to int (0-255)
function freqToFloat(fft) {
From bc4ad0845f3a02dfe2031baf560881eb7a24ddaf Mon Sep 17 00:00:00 2001
From: Divyanshu Raj
Date: Sat, 25 Jul 2020 09:35:03 +0530
Subject: [PATCH 3/3] replacement of es5 functions to es6 class def feat
P5.Amplitude
---
src/amplitude.js | 462 ++++++++++++++++++++++++-----------------------
src/app.js | 6 +-
src/audioin.js | 3 +-
3 files changed, 239 insertions(+), 232 deletions(-)
diff --git a/src/amplitude.js b/src/amplitude.js
index 681ef058..30baf8f8 100644
--- a/src/amplitude.js
+++ b/src/amplitude.js
@@ -44,267 +44,269 @@ import processorNames from './audioWorklet/processorNames';
*
*
*/
-p5.Amplitude = function (smoothing) {
- // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default
- this.bufferSize = safeBufferSize(2048);
+class Amplitude {
+ constructor(smoothing) {
+ // Set to 2048 for now. In future iterations, this should be inherited or parsed from p5sound's default
+ this.bufferSize = safeBufferSize(2048);
- // set audio context
- this.audiocontext = p5sound.audiocontext;
- this._workletNode = new AudioWorkletNode(
- this.audiocontext,
- processorNames.amplitudeProcessor,
- {
- outputChannelCount: [1],
+ // set audio context
+ this.audiocontext = p5sound.audiocontext;
+ this._workletNode = new AudioWorkletNode(
+ this.audiocontext,
+ processorNames.amplitudeProcessor,
+ {
+ outputChannelCount: [1],
- parameterData: { smoothing: smoothing || 0 },
- processorOptions: {
- normalize: false,
- smoothing: smoothing || 0,
- numInputChannels: 2,
- bufferSize: this.bufferSize,
- },
- }
- );
+ parameterData: { smoothing: smoothing || 0 },
+ processorOptions: {
+ normalize: false,
+ smoothing: smoothing || 0,
+ numInputChannels: 2,
+ bufferSize: this.bufferSize,
+ },
+ }
+ );
- this._workletNode.port.onmessage = function (event) {
- if (event.data.name === 'amplitude') {
- this.volume = event.data.volume;
- this.volNorm = event.data.volNorm;
- this.stereoVol = event.data.stereoVol;
- this.stereoVolNorm = event.data.stereoVolNorm;
- }
- }.bind(this);
+ this._workletNode.port.onmessage = function (event) {
+ if (event.data.name === 'amplitude') {
+ this.volume = event.data.volume;
+ this.volNorm = event.data.volNorm;
+ this.stereoVol = event.data.stereoVol;
+ this.stereoVolNorm = event.data.stereoVolNorm;
+ }
+ }.bind(this);
- // for connections
- this.input = this._workletNode;
+ // for connections
+ this.input = this._workletNode;
- this.output = this.audiocontext.createGain();
+ this.output = this.audiocontext.createGain();
- // the variables to return
- this.volume = 0;
- this.volNorm = 0;
- this.stereoVol = [0, 0];
- this.stereoVolNorm = [0, 0];
+ // the variables to return
+ this.volume = 0;
+ this.volNorm = 0;
+ this.stereoVol = [0, 0];
+ this.stereoVolNorm = [0, 0];
- this.normalize = false;
+ this.normalize = false;
- this._workletNode.connect(this.output);
- this.output.gain.value = 0;
+ this._workletNode.connect(this.output);
+ this.output.gain.value = 0;
- // this may only be necessary because of a Chrome bug
- this.output.connect(this.audiocontext.destination);
+ // this may only be necessary because of a Chrome bug
+ this.output.connect(this.audiocontext.destination);
- // connect to p5sound master output by default, unless set by input()
- p5sound.meter.connect(this._workletNode);
+ // connect to p5sound master output by default, unless set by input()
+ p5sound.meter.connect(this._workletNode);
- // add this p5.SoundFile to the soundArray
- p5sound.soundArray.push(this);
-};
+ // add this p5.SoundFile to the soundArray
+ p5sound.soundArray.push(this);
+ }
-/**
- * Connects to the p5sound instance (master output) by default.
- * Optionally, you can pass in a specific source (i.e. a soundfile).
- *
- * @method setInput
- * @for p5.Amplitude
- * @param {soundObject|undefined} [snd] set the sound source
- * (optional, defaults to
- * master output)
- * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0
- * to smooth amplitude readings
- * @example
- *
- * function preload(){
- * sound1 = loadSound('assets/beat.mp3');
- * sound2 = loadSound('assets/drum.mp3');
- * }
- * function setup(){
- * cnv = createCanvas(100, 100);
- * cnv.mouseClicked(toggleSound);
- *
- * amplitude = new p5.Amplitude();
- * amplitude.setInput(sound2);
- * }
- *
- * function draw() {
- * background(220);
- * text('tap to play', 20, 20);
- *
- * let level = amplitude.getLevel();
- * let size = map(level, 0, 1, 0, 200);
- * ellipse(width/2, height/2, size, size);
- * }
- *
- * function toggleSound(){
- * if (sound1.isPlaying() && sound2.isPlaying()) {
- * sound1.stop();
- * sound2.stop();
- * } else {
- * sound1.play();
- * sound2.play();
- * }
- * }
- *
- */
-p5.Amplitude.prototype.setInput = function (source, smoothing) {
- p5sound.meter.disconnect();
+ /**
+ * Connects to the p5sound instance (master output) by default.
+ * Optionally, you can pass in a specific source (i.e. a soundfile).
+ *
+ * @method setInput
+ * @for p5.Amplitude
+ * @param {soundObject|undefined} [snd] set the sound source
+ * (optional, defaults to
+ * master output)
+ * @param {Number|undefined} [smoothing] a range between 0.0 and 1.0
+ * to smooth amplitude readings
+ * @example
+ *
+ * function preload(){
+ * sound1 = loadSound('assets/beat.mp3');
+ * sound2 = loadSound('assets/drum.mp3');
+ * }
+ * function setup(){
+ * cnv = createCanvas(100, 100);
+ * cnv.mouseClicked(toggleSound);
+ *
+ * amplitude = new p5.Amplitude();
+ * amplitude.setInput(sound2);
+ * }
+ *
+ * function draw() {
+ * background(220);
+ * text('tap to play', 20, 20);
+ *
+ * let level = amplitude.getLevel();
+ * let size = map(level, 0, 1, 0, 200);
+ * ellipse(width/2, height/2, size, size);
+ * }
+ *
+ * function toggleSound(){
+ * if (sound1.isPlaying() && sound2.isPlaying()) {
+ * sound1.stop();
+ * sound2.stop();
+ * } else {
+ * sound1.play();
+ * sound2.play();
+ * }
+ * }
+ *
+ */
+ setInput(source, smoothing) {
+ p5sound.meter.disconnect();
- if (smoothing) {
- this._workletNode.parameters.get('smoothing').value = smoothing;
- }
+ if (smoothing) {
+ this._workletNode.parameters.get('smoothing').value = smoothing;
+ }
- // connect to the master out of p5s instance if no snd is provided
- if (source == null) {
- console.log(
- 'Amplitude input source is not ready! Connecting to master output instead'
- );
- p5sound.meter.connect(this._workletNode);
- }
+ // connect to the master out of p5s instance if no snd is provided
+ if (source == null) {
+ console.log(
+ 'Amplitude input source is not ready! Connecting to master output instead'
+ );
+ p5sound.meter.connect(this._workletNode);
+ }
- // if it is a p5.Signal
- else if (source instanceof p5.Signal) {
- source.output.connect(this._workletNode);
- }
- // connect to the sound if it is available
- else if (source) {
- source.connect(this._workletNode);
- this._workletNode.disconnect();
- this._workletNode.connect(this.output);
- }
+ // if it is a p5.Signal
+ else if (source instanceof p5.Signal) {
+ source.output.connect(this._workletNode);
+ }
+ // connect to the sound if it is available
+ else if (source) {
+ source.connect(this._workletNode);
+ this._workletNode.disconnect();
+ this._workletNode.connect(this.output);
+ }
- // otherwise, connect to the master out of p5s instance (default)
- else {
- p5sound.meter.connect(this._workletNode);
+ // otherwise, connect to the master out of p5s instance (default)
+ else {
+ p5sound.meter.connect(this._workletNode);
+ }
}
-};
-p5.Amplitude.prototype.connect = function (unit) {
- if (unit) {
- if (unit.hasOwnProperty('input')) {
- this.output.connect(unit.input);
+ connect(unit) {
+ if (unit) {
+ if (unit.hasOwnProperty('input')) {
+ this.output.connect(unit.input);
+ } else {
+ this.output.connect(unit);
+ }
} else {
- this.output.connect(unit);
+ this.output.connect(this.panner.connect(p5sound.input));
}
- } else {
- this.output.connect(this.panner.connect(p5sound.input));
}
-};
-p5.Amplitude.prototype.disconnect = function () {
- if (this.output) {
- this.output.disconnect();
+ disconnect() {
+ if (this.output) {
+ this.output.disconnect();
+ }
}
-};
-/**
- * Returns a single Amplitude reading at the moment it is called.
- * For continuous readings, run in the draw loop.
- *
- * @method getLevel
- * @for p5.Amplitude
- * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)
- * @return {Number} Amplitude as a number between 0.0 and 1.0
- * @example
- *
- * function preload(){
- * sound = loadSound('assets/beat.mp3');
- * }
- *
- * function setup() {
- * let cnv = createCanvas(100, 100);
- * cnv.mouseClicked(toggleSound);
- * amplitude = new p5.Amplitude();
- * }
- *
- * function draw() {
- * background(220, 150);
- * textAlign(CENTER);
- * text('tap to play', width/2, 20);
- *
- * let level = amplitude.getLevel();
- * let size = map(level, 0, 1, 0, 200);
- * ellipse(width/2, height/2, size, size);
- * }
- *
- * function toggleSound(){
- * if (sound.isPlaying()) {
- * sound.stop();
- * } else {
- * sound.play();
- * }
- * }
- *
- */
-p5.Amplitude.prototype.getLevel = function (channel) {
- if (typeof channel !== 'undefined') {
- if (this.normalize) {
- return this.stereoVolNorm[channel];
+ /**
+ * Returns a single Amplitude reading at the moment it is called.
+ * For continuous readings, run in the draw loop.
+ *
+ * @method getLevel
+ * @for p5.Amplitude
+ * @param {Number} [channel] Optionally return only channel 0 (left) or 1 (right)
+ * @return {Number} Amplitude as a number between 0.0 and 1.0
+ * @example
+ *
+ * function preload(){
+ * sound = loadSound('assets/beat.mp3');
+ * }
+ *
+ * function setup() {
+ * let cnv = createCanvas(100, 100);
+ * cnv.mouseClicked(toggleSound);
+ * amplitude = new p5.Amplitude();
+ * }
+ *
+ * function draw() {
+ * background(220, 150);
+ * textAlign(CENTER);
+ * text('tap to play', width/2, 20);
+ *
+ * let level = amplitude.getLevel();
+ * let size = map(level, 0, 1, 0, 200);
+ * ellipse(width/2, height/2, size, size);
+ * }
+ *
+ * function toggleSound(){
+ * if (sound.isPlaying()) {
+ * sound.stop();
+ * } else {
+ * sound.play();
+ * }
+ * }
+ *
+ */
+ getLevel(channel) {
+ if (typeof channel !== 'undefined') {
+ if (this.normalize) {
+ return this.stereoVolNorm[channel];
+ } else {
+ return this.stereoVol[channel];
+ }
+ } else if (this.normalize) {
+ return this.volNorm;
} else {
- return this.stereoVol[channel];
+ return this.volume;
}
- } else if (this.normalize) {
- return this.volNorm;
- } else {
- return this.volume;
}
-};
-/**
- * Determines whether the results of Amplitude.process() will be
- * Normalized. To normalize, Amplitude finds the difference the
- * loudest reading it has processed and the maximum amplitude of
- * 1.0. Amplitude adds this difference to all values to produce
- * results that will reliably map between 0.0 and 1.0. However,
- * if a louder moment occurs, the amount that Normalize adds to
- * all the values will change. Accepts an optional boolean parameter
- * (true or false). Normalizing is off by default.
- *
- * @method toggleNormalize
- * @for p5.Amplitude
- * @param {boolean} [boolean] set normalize to true (1) or false (0)
- */
-p5.Amplitude.prototype.toggleNormalize = function (bool) {
- if (typeof bool === 'boolean') {
- this.normalize = bool;
- } else {
- this.normalize = !this.normalize;
+ /**
+ * Determines whether the results of Amplitude.process() will be
+ * Normalized. To normalize, Amplitude finds the difference the
+ * loudest reading it has processed and the maximum amplitude of
+ * 1.0. Amplitude adds this difference to all values to produce
+ * results that will reliably map between 0.0 and 1.0. However,
+ * if a louder moment occurs, the amount that Normalize adds to
+ * all the values will change. Accepts an optional boolean parameter
+ * (true or false). Normalizing is off by default.
+ *
+ * @method toggleNormalize
+ * @for p5.Amplitude
+ * @param {boolean} [boolean] set normalize to true (1) or false (0)
+ */
+ toggleNormalize(bool) {
+ if (typeof bool === 'boolean') {
+ this.normalize = bool;
+ } else {
+ this.normalize = !this.normalize;
+ }
+ this._workletNode.port.postMessage({
+ name: 'toggleNormalize',
+ normalize: this.normalize,
+ });
}
- this._workletNode.port.postMessage({
- name: 'toggleNormalize',
- normalize: this.normalize,
- });
-};
-
-/**
- * Smooth Amplitude analysis by averaging with the last analysis
- * frame. Off by default.
- *
- * @method smooth
- * @for p5.Amplitude
- * @param {Number} set smoothing from 0.0 <= 1
- */
-p5.Amplitude.prototype.smooth = function (s) {
- if (s >= 0 && s < 1) {
- this._workletNode.port.postMessage({ name: 'smoothing', smoothing: s });
- } else {
- console.log('Error: smoothing must be between 0 and 1');
+ /**
+ * Smooth Amplitude analysis by averaging with the last analysis
+ * frame. Off by default.
+ *
+ * @method smooth
+ * @for p5.Amplitude
+ * @param {Number} set smoothing from 0.0 <= 1
+ */
+ smooth(s) {
+ if (s >= 0 && s < 1) {
+ this._workletNode.port.postMessage({ name: 'smoothing', smoothing: s });
+ } else {
+ console.log('Error: smoothing must be between 0 and 1');
+ }
}
-};
+ dispose() {
+ // remove reference from soundArray
+ var index = p5sound.soundArray.indexOf(this);
+ p5sound.soundArray.splice(index, 1);
-p5.Amplitude.prototype.dispose = function () {
- // remove reference from soundArray
- var index = p5sound.soundArray.indexOf(this);
- p5sound.soundArray.splice(index, 1);
+ if (this.input) {
+ this.input.disconnect();
+ delete this.input;
+ }
+ if (this.output) {
+ this.output.disconnect();
+ delete this.output;
+ }
- if (this.input) {
- this.input.disconnect();
- delete this.input;
- }
- if (this.output) {
- this.output.disconnect();
- delete this.output;
+ this._workletNode.disconnect();
+ delete this._workletNode;
}
+}
- this._workletNode.disconnect();
- delete this._workletNode;
-};
+export default Amplitude;
diff --git a/src/app.js b/src/app.js
index 453309d6..af09bbd2 100644
--- a/src/app.js
+++ b/src/app.js
@@ -7,9 +7,13 @@ import './errorHandler';
import './audioWorklet';
import './panner';
import './soundfile';
-import './amplitude';
+
+import Amplitude from './amplitude';
+p5.Amplitude = Amplitude;
+
import FFT from './fft';
p5.FFT = FFT;
+
import './signal';
import './oscillator';
import './envelope';
diff --git a/src/audioin.js b/src/audioin.js
index 5ab82cdf..10ab52a4 100644
--- a/src/audioin.js
+++ b/src/audioin.js
@@ -1,4 +1,5 @@
import p5sound from './master';
+import Amplitude from './amplitude';
// an array of input sources
p5sound.inputSources = [];
@@ -84,7 +85,7 @@ p5.AudioIn = function (errorCallback) {
*
* @property {p5.Amplitude} amplitude
*/
- this.amplitude = new p5.Amplitude();
+ this.amplitude = new Amplitude();
this.output.connect(this.amplitude.input);
if (