diff --git a/src/index.js b/src/index.js index 37bf08e..3dbd84d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,24 @@ import p5 from 'p5'; -import 'p5/lib/addons/p5.sound'; import './index.scss'; -const VOLUME_NORMALIZATION = 1000; -const THRESHOLD = 5 / VOLUME_NORMALIZATION; +const VOLUME_THRESHOLD = 0; +const FFT_SIZE = 1024; function getColorValue(volume) { - return Math.floor(volume * VOLUME_NORMALIZATION * 256); + 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})`; +} + +function getRMS(spectrum) { + let rms = 0; + for (let i = 0; i < spectrum.length; i++) { + rms += spectrum[i] * spectrum[i]; + } + rms /= spectrum.length; + rms = Math.sqrt(rms); + return rms; } function getWidth(volume) { @@ -23,8 +35,38 @@ function getRandomY() { async function main() { - const mic = new p5.AudioIn(); - mic.start(); + 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); + 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); + // getByteTimeDomainData gets volumes over the sample time + // analyser.getByteTimeDomainData(self.spectrum); + + volume = getRMS(spectrum); + // get peak - a hack when our volumes are low + if (volume > VOLUME_THRESHOLD) VOLUME_THRESHOLD = volume; + volume = self.vol; + } + + const input = audioCtx.createMediaStreamSource(microphone); + input.connect(analyser); + analyser.connect(audioProcessor); + // audioProcessor.connect(audioCtx.destination); + const instance = new p5(( sketch ) => { sketch.setup = () => { @@ -39,27 +81,16 @@ async function main() { let bars = []; sketch.draw = () => { + if (!fresh) { + return; + } + + fresh = false; + sketch.background(0); - const volume = mic.getLevel(); - const x = getRandomX(); - bars.push({ - volume, - // pitch, - x, - }); - - const newBars = []; - for (const bar of bars) { - bar.volume = bar.volume / 1.5; - if (bar.volume <= THRESHOLD) { - continue; - } - drawBar(bar); - newBars.push(bar); - }; - - bars = newBars; + for (const pitch of spectrum) { + } }; }); }