/*Downloaded from https://www.codeseek.co/jhancock532/wavy-musical-visualiser-YvZNzN */
//Code for WebAudioAPI.
let context = new (window.AudioContext || window.webkitAudioContext)();
let analyser = context.createAnalyser();
let soundDataArray;
const MAX_SOUND_VALUE = 256;
audioInput.onchange = function() {
let sound = document.getElementById("soundElement");
let reader = new FileReader();
reader.onload = function(e) {
sound.src = this.result;
sound.controls = true;
sound.play();
};
reader.readAsDataURL(this.files[0]);
createAudioObjects();
};
function loadAudio() {
var media = ["https://s3-us-west-2.amazonaws.com/s.cdpn.io/9473/ivan-ibarra_-_cultos-personales.ogg"]; //stolen from another pen. I have no idea how to host music files online or access them appropriately. //I spent a couple of hours trying different things to no avail.
let sound = document.getElementById("soundElement");
sound.crossOrigin = 'anonymous';
sound.src = media[0];
sound.controls = true;
sound.play();
createAudioObjects();
}
//Connects the audio source to the analyser and creating a suitably sized array to hold the frequency data.
function createAudioObjects() {
source = context.createMediaElementSource(document.getElementById("soundElement"));
source.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 1024; //128, 256, 512, 1024 and 2048 are valid values.
let bufferLength = analyser.frequencyBinCount;
soundDataArray = new Uint8Array(bufferLength);
}
//Returns the average of a small sample of the array. Index declares which sample you want, ideal for iteration.
function getSampleOfSoundData(index, noSampleSections, soundDataArray){
let sampleSize = Math.floor((soundDataArray.length/2) / noSampleSections);
let minBound = index * sampleSize;
let maxBound = (index + 1) * sampleSize;
let sum = 0;
for (let i = minBound; i < maxBound; i++){
sum += soundDataArray[i];
}
let average = sum / sampleSize;
return average / MAX_SOUND_VALUE;
}
let cVars = {
numberOfCurves: 20,
peakXScale: 0.5,
length: 250,
reachHeightScale: 0.0,
maxHeight: 300,
leftReachScale: 1.5,
rightReachScale: 1.5,
xOffset: 0,
yOffset: 120,
TEMP: 1,
brightness: 35,
saturation: 100,
}
let gui = new dat.GUI();
let curveFolder = gui.addFolder('Curves');
let colorFolder = gui.addFolder('Colors');
colorFolder.add(cVars,'brightness',0,100).name("Brightness");
colorFolder.add(cVars,'saturation',0,100).name("Saturation");
//Add the parameters into the folder.
let numSamplesController = curveFolder.add(cVars,'numberOfCurves',1,30).name("No. Curves");
numSamplesController.onChange(function(val) {
createCurves();
});
curveFolder.add(cVars,'length',0,500).name("Curve Length");
curveFolder.add(cVars,'peakXScale',0.25,0.75).name("Peak X Scale");
curveFolder.add(cVars,'reachHeightScale',0,1).name("Reach Height");
curveFolder.add(cVars,'leftReachScale',0.5,1.6).name("Left Reach");
curveFolder.add(cVars,'rightReachScale',0.5,1.6).name("Right Reach");
curveFolder.add(cVars,'maxHeight',0,500).name("maxHeight");
curveFolder.add(cVars,'xOffset',-500,500).name("X Offset");
curveFolder.add(cVars,'yOffset',-500,500).name("Y Offset");
//curveFolder.add(cVars,'TEMP',1,3).name("TEMP");
//curveFolder.open();
let curveCollection = [];
function Curve(){
this.points = [];
this.id = 0;
this.hue = 0;
this.updatePoints = function(){
let soundLevel = 0.5;
if((soundDataArray === undefined) == false){
soundLevel = getSampleOfSoundData(this.id, cVars.numberOfCurves, soundDataArray);
}
let curveLength = cVars.length * 2;
let xCenter = windowWidth / 2 + cVars.xOffset;
let yCenter = windowHeight / 2 + cVars.yOffset;
//The left and right base points (where the curve starts and ends) are made relative to the center of the screen.
let leftBase = createVector(xCenter - cVars.length, yCenter);
let rightBase = createVector(xCenter + cVars.length, yCenter);
//The maximum turning point of the curve.
//this.id
//let relativeMaxPointX = (curveLength/2*cVars.maxPointX*2);
let relativeMaxPointX = curveLength*cVars.peakXScale*(this.id+1)/cVars.numberOfCurves*(1+(cVars.numberOfCurves-1)/(cVars.numberOfCurves+1));
//curveLength*(this.id/cVars.numberOfCurves)*cVars.peakXScale*2;
let maxPoint = createVector(leftBase.x + relativeMaxPointX, yCenter - cVars.maxHeight*soundLevel)
//The left and right reaches determine the figure of the curve, is it thick or thin?
//These points should be made relative to the maxPoint and a scale value as well.
let leftReach = createVector(
leftBase.x + relativeMaxPointX * cVars.leftReachScale/2,
yCenter - cVars.maxHeight*cVars.reachHeightScale/2
//yCenter - cVars.maxHeight*cVars.reachHeightScale/2 * (1+cVars.leftReachScale) //perhaps a function here to make this always smooth?
);
let rightReach = createVector(
rightBase.x - (curveLength-relativeMaxPointX) * cVars.rightReachScale/2,
yCenter - cVars.maxHeight*cVars.reachHeightScale/2 //perhaps a function here to make this always smooth?
);
this.points = [];
this.points.push(leftBase);
this.points.push(leftBase);
this.points.push(leftReach);
this.points.push(maxPoint);
this.points.push(rightReach);
this.points.push(rightBase);
this.points.push(rightBase);
}
this.display = function(){
fill(this.hue,cVars.saturation,cVars.brightness,1);
beginShape();
for (let i = 0; i < this.points.length; i++){
curveVertex(this.points[i].x, this.points[i].y);
}
endShape();
//stroke();
}
}
function createCurves() {
curveCollection = [];
for (let i = 0; i < cVars.numberOfCurves; i++){
curveCollection.push(new Curve());
curveCollection[i].id = i;
curveCollection[i].hue = i*360/cVars.numberOfCurves;
}
}
function setup(){
createCurves();
createCanvas(windowWidth, windowHeight);
colorMode(HSB, 360, 100, 100, 1); //default HSB colour
//blendMode(ADD);
fill(0,100,100,1);
noStroke();
}
function draw(){
blendMode(DARKEST);
background(0);
blendMode(ADD);
if((soundDataArray === undefined) == false){
analyser.getByteFrequencyData(soundDataArray);
}
for (let i = 0; i < cVars.numberOfCurves; i++){
curveCollection[i].updatePoints();
curveCollection[i].display();
}
}