vyx-hex/src/index.js

109 lines
2.7 KiB
JavaScript

import p5 from 'p5';
import './index.scss';
const FFT_SIZE = 256;
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 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() {
return Math.floor(Math.random() * window.innerWidth);
}
function getRandomY() {
return Math.floor(Math.random() * window.innerHeight);
}
async function main() {
const audioCtx = new AudioContext();
const microphone = await navigator.mediaDevices.getUserMedia({ audio: true });
const analyser = new AnalyserNode(audioCtx);
analyser.smoothingTimeConstant = 0.2;
analyser.fftSize = FFT_SIZE;
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);
// getByteTimeDomainData gets volumes over the sample time
// analyser.getByteTimeDomainData(self.spectrum);
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 input = audioCtx.createMediaStreamSource(microphone);
input.connect(analyser);
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);
};
sketch.draw = () => {
if (!fresh) {
return;
}
fresh = false;
sketch.background(sketch.color(0, 0, 0));
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;
};
});
}
main();