From 76c97155ceff296978be04c48b3f9b3ec2a232ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20B=C3=A4dorf?= Date: Fri, 7 Jun 2019 20:07:24 +0200 Subject: [PATCH] Pitched random location bars --- src/index.js | 73 +++++++++++++++++++++++++++-------------------- webpack.config.js | 7 +---- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/index.js b/src/index.js index 3dbd84d..bd48cca 100644 --- a/src/index.js +++ b/src/index.js @@ -1,15 +1,7 @@ import p5 from 'p5'; import './index.scss'; -const VOLUME_THRESHOLD = 0; -const FFT_SIZE = 1024; - -function getColorValue(volume) { - const normalizedVolume = volume * VOLUME_NORMALIZATION; - const color = Math.floor(normalizedVolume); - const opacity = (normalizedVolume > VOLUME_MAX ? normalizedVolume : VOLUME_MAX) / 100; - return `rgba(${color}, ${color}, ${color}, ${opacity})`; -} +const FFT_SIZE = 256; function getRMS(spectrum) { let rms = 0; @@ -21,8 +13,14 @@ function getRMS(spectrum) { return rms; } -function getWidth(volume) { - return volume * VOLUME_NORMALIZATION; +function getPitch(spectrum) { + let cg = 0; + let weight = 0; + for (let i = 0; i < spectrum.length; i++) { + cg += spectrum[i] * i; + weight += spectrum[i]; + } + return Math.floor(cg / weight); } function getRandomX() { @@ -38,28 +36,34 @@ async function main() { const audioCtx = new AudioContext(); const microphone = await navigator.mediaDevices.getUserMedia({ audio: true }); const analyser = new AnalyserNode(audioCtx); - - let fresh = false; - let spectrum = []; - let volume = 0; analyser.smoothingTimeConstant = 0.2; analyser.fftSize = FFT_SIZE; - const audioProcessor = audioCtx.createScriptProcessor(FFT_SIZE*2, 1, 1); + let fresh = false; + let spectrum = []; + let pitch = 0; + let volume = 0; + let volumeThreshold = 0; + let bars = []; + + const audioProcessor = audioCtx.createScriptProcessor(FFT_SIZE * 2, 1, 1); audioProcessor.onaudioprocess = () => { fresh = true; // bitcount returns array which is half the FFT_SIZE spectrum = new Uint8Array(analyser.frequencyBinCount); // getByteFrequencyData returns amplitude for each bin - // analyser.getByteFrequencyData(spectrum); + analyser.getByteFrequencyData(spectrum); // getByteTimeDomainData gets volumes over the sample time // analyser.getByteTimeDomainData(self.spectrum); + + spectrum.reverse(); - volume = getRMS(spectrum); + const currentVolume = getRMS(spectrum); // get peak - a hack when our volumes are low - if (volume > VOLUME_THRESHOLD) VOLUME_THRESHOLD = volume; - volume = self.vol; + if (currentVolume > volumeThreshold) volumeThreshold = currentVolume; + volume = currentVolume; + pitch = getPitch(spectrum, volume, volumeThreshold); } const input = audioCtx.createMediaStreamSource(microphone); @@ -67,30 +71,37 @@ async function main() { analyser.connect(audioProcessor); // audioProcessor.connect(audioCtx.destination); - const instance = new p5(( sketch ) => { sketch.setup = () => { sketch.createCanvas(window.innerWidth, window.innerHeight); + sketch.colorMode(sketch.HSL, 255); }; - function drawBar(bar) { - sketch.fill(getColorValue(bar.volume)); - sketch.rect(bar.x, 0, getWidth(bar.volume), window.innerHeight); - } - - let bars = []; - sketch.draw = () => { if (!fresh) { return; } fresh = false; + sketch.background(sketch.color(0, 0, 0)); - sketch.background(0); - - for (const pitch of spectrum) { + bars.push({ + x: getRandomX(), + volume, + pitch, + age: 1, + }); + const newBars = []; + for (const bar of bars) { + sketch.fill(sketch.color(0, (bar.volume / volumeThreshold) * 255, 255)); + sketch.rect(bar.x, 0, bar.age * bar.volume * 2, window.innerHeight); + bar.age /= 2; + if (bar.age > 0.1) { + newBars.push(bar); + } } + + bars = newBars; }; }); } diff --git a/webpack.config.js b/webpack.config.js index a5e91ba..5fc1667 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -14,12 +14,7 @@ module.exports = { use: [ { loader: "style-loader" }, { loader: "css-loader" }, - { - loader: "sass-loader", - options: { - includePaths: ["absolute/path/a", "absolute/path/b"], - }, - }, + { loader: "sass-loader" }, ], }, ],