diff --git a/src/index.js b/src/index.js index 635212f..ab9a899 100644 --- a/src/index.js +++ b/src/index.js @@ -3,6 +3,8 @@ import './index.scss'; const FFT_SIZE = 256; const VOLUME_THRESHOLD = 20; +const LINE_MARGIN = 20; +const MAX_LINES = 60; function getRMS(spectrum) { let rms = 0; @@ -40,20 +42,14 @@ async function main() { analyser.smoothingTimeConstant = 0.2; analyser.fftSize = FFT_SIZE; - let fresh = false; - let spectrum = []; - let pitch = 0; - let minPitch = 90; - let maxPitch = 90; - let volume = 0; - let volumeThreshold = 0; - let bars = []; + let lines = []; + let maxPitch = 0; + let minPitch = 0; 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); + const spectrum = new Uint8Array(analyser.frequencyBinCount); // getByteFrequencyData returns amplitude for each bin analyser.getByteFrequencyData(spectrum); @@ -62,24 +58,34 @@ async function main() { spectrum.reverse(); - const currentVolume = getRMS(spectrum); - // get peak - a hack when our volumes are low - if (currentVolume > volumeThreshold) { - volumeThreshold = currentVolume; - } - volume = currentVolume; - pitch = getPitch(spectrum, volume, volumeThreshold); + + const volume = getRMS(spectrum); + const pitch = getPitch(spectrum, volume); + lines.unshift({ + spectrum, + volume, + pitch, + }); + if (pitch > maxPitch) { - maxPitch = pitch - } else if (pitch < minPitch) { + maxPitch = pitch; + } + + if (pitch < minPitch) { minPitch = pitch; } + + if (lines.length > MAX_LINES) { + lines.pop(); + } } const input = audioCtx.createMediaStreamSource(microphone); input.connect(analyser); analyser.connect(audioProcessor); // audioProcessor.connect(audioCtx.destination); + const baseHeight = window.innerHeight * 0.8; + const spectrumPointWidth = window.innerWidth / analyser.frequencyBinCount; const instance = new p5(( sketch ) => { sketch.setup = () => { @@ -87,35 +93,35 @@ async function main() { sketch.colorMode(sketch.HSL, 255); }; + let shouldDraw = 0; + sketch.draw = () => { - if (!fresh) { + shouldDraw += 1; + if (shouldDraw > 0) { + if (shouldDraw > 3) { + shouldDraw = -1; + } return; } - fresh = false; sketch.background(sketch.color(0, 0, 0)); - - if (volume > VOLUME_THRESHOLD) { - bars.push({ - x: getRandomX(), - volume, - pitch, - age: 1, - }); - } - - const newBars = []; - for (const bar of bars) { - const normalizedPitchColor = ((bar.pitch - minPitch) / (maxPitch - minPitch)) * 220; - sketch.fill(sketch.color(normalizedPitchColor, bar.volume, (bar.volume / volumeThreshold) * 255)); - sketch.rect(bar.x, 0, bar.age * bar.volume * 2, window.innerHeight); - bar.age /= 2; - if (bar.age > 0.1) { - newBars.push(bar); + for (let l = 0; l < lines.length; l++) { + const lineBaseHeight = baseHeight - (l * LINE_MARGIN); + const line = lines[l]; + sketch.fill(`rgba(255, 255, 255, 0.2)`); + sketch.stroke(((line.pitch - minPitch) / (maxPitch - minPitch)) * 255); + sketch.strokeWeight(1); + sketch.beginShape(); + sketch.curveVertex(0, lineBaseHeight); + sketch.curveVertex(0, lineBaseHeight); + for (let i = 1; i < line.spectrum.length - 1; i++) { + const point = line.spectrum[i]; + sketch.curveVertex(i * spectrumPointWidth, lineBaseHeight - point); } + sketch.curveVertex(window.innerWidth, lineBaseHeight); + sketch.curveVertex(window.innerWidth, lineBaseHeight); + sketch.endShape(); } - - bars = newBars; }; });