Pitched random location bars

This commit is contained in:
Benjamin Bädorf 2019-06-07 20:07:24 +02:00
parent ede4449de8
commit 76c97155ce
2 changed files with 43 additions and 37 deletions

View file

@ -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,12 +36,15 @@ 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;
analyser.smoothingTimeConstant = 0.2;
analyser.fftSize = FFT_SIZE;
let volumeThreshold = 0;
let bars = [];
const audioProcessor = audioCtx.createScriptProcessor(FFT_SIZE * 2, 1, 1);
audioProcessor.onaudioprocess = () => {
@ -52,14 +53,17 @@ async function main() {
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);
volume = getRMS(spectrum);
spectrum.reverse();
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;
};
});
}

View file

@ -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" },
],
},
],