xxxxxxxxxx
// beat detection code courtesy of https://discourse.processing.org/u/atagger/summary
// https://discourse.processing.org/t/beat-detection-algorithm-help-feedback/31588
let sound;
let beatDetect;
let spectrumBg;
let spectrumX = 0;
function preload() {
//put your sound file here
sound = loadSound("https://www.paulwheeler.us/files/Dubstep%203.mp3");
}
function setup() {
createCanvas(windowWidth, windowHeight);
spectrumBg = createGraphics(width, height);
spectrumBg.background(0);
spectrumBg.noStroke();
frameRate(60);
beatDetect = new BeatDetect();
sound.loop();
}
function draw() {
background(0);
let beat = beatDetect.detectBeat();
if (spectrumX > 0) {
image(spectrumBg, width - spectrumX, 0, spectrumX, height, 0, 0, spectrumX, height);
}
image(spectrumBg, 0, 0, width - spectrumX, height, spectrumX, 0, width - spectrumX, height);
if (beat) {
fill(255, 0, 0);
//console.log(size);
ellipse(width / 2, height / 2, 300 + beatDetect.size, 300 + beatDetect.size);
}
}
//BeatDetect constructor
function BeatDetect() {
//http://archive.gamedev.net/archive/reference/programming/features/beatdetection/
//algorithm #2 - Frequency selected sound energy
let sampleBuffer = []; //sample history buffer
let bandsAverage = []; //array of averages of the bands
let energyBuffer = []; //array of current sound energy
let fourier = new p5.FFT();
this.size = 0;
this.detectBeat = function() {
//analyze fourier
let spectrum = fourier.analyze();
let count = 0; //reset count every frame
let isBeat = false; //reset isBeat every frame
let bandsEnergy = []; //start a new array each frame, so we don't pass in an array reference :)
let bands_temp = []; //temp array to split the frequency bands
let h = height / spectrum.length;
for (let i = 0; i < spectrum.length; i++) {
spectrumBg.fill(spectrum[i]);
spectrumBg.rect(spectrumX, map(i, 0, spectrum.length, 0, height), 1, Math.max(1, h));
energyBuffer[i] = spectrum[i] * spectrum[i]; //calculate energy
bands_temp.push(energyBuffer[i]); // temp array to split into grouped bands
//collect 32 samples (one band of 1024 i.e. 1024/32 = 32 bands)
if (bands_temp.length == 32) {
let sum = 0; // init the sum to zero
for (let j = 0; j < bands_temp.length; j++) {
sum += bands_temp[j]; // get the sum of the band's samples
bandsEnergy[count] = sum; // get average energy of band's grouping
}
bands_temp = []; //clear temp bands_sum array for next set of 32 samples;
count++; //increment count index, reset this every frame;
}
}
spectrumX = (spectrumX + 1) % width;
sampleBuffer.push(bandsEnergy);
//add +1 since we remove a value each frame
if (sampleBuffer.length == 30 + (1)) {
for (let j = 0; j < bandsEnergy.length; j++) {
let bandSum = 0; //reset bandSum when we get to a new band
//loop through all arrays in the history buffer
for (let k = 0; k < sampleBuffer.length; k++) {
bandSum += sampleBuffer[k][j]; // get the sum for each freq. band in the buffer
}
//calc avg from sum in each band of the buffer
bandsAverage[j] = bandSum / sampleBuffer.length;
}
//remove the oldest sample from the array
sampleBuffer.splice(0, 1);
}
for (let k = 0; k < sampleBuffer.length; k++) {
let c = 1.095; //increase to lower sensitivity
if (bandsEnergy[k] > bandsAverage[k] * c) {
isBeat = true;
this.size = (bandsEnergy[k]) * 0.0001;
//this.size=300;
return isBeat;
}
}
//console.log(bandsEnergy.length);
//console.log(sampleBuffer.length);
//console.log( bandsAverage[14] + "bandAverage");
//console.log( bandsEnergy[14] + "bandEnergy");
} // end DETECT
} // end CONSTRUCTOR