p5(sketch => {
let audioContext;
let analyserNode;
let analyserData;
let analyserTarget;
let gainNode;
let audio;
let isFloat = false;
let interval;
sketch.setup = function() {
sketch.createCanvas(width, width/2);
};
sketch.draw = function() {
sketch.background("#001b42");
sketch.stroke("white");
sketch.noFill();
if (analyserNode) {
for (let i = 0; i < analyserData.length; i++) {
analyserData[i] = damp( analyserData[i], isFloat ? analyserTarget[i] : ( analyserTarget[i] / 256) * 2 - 1, 0.01, sketch.deltaTime );
}
sketch.beginShape();
const margin = 0.1;
for (let i = 0; i < analyserData.length; i++) {
const x = sketch.map( i,
0, analyserData.length,
width * margin, width * (1 - margin));
const signal = analyserData[i];
const amplitude = height * 4;
const y = sketch.map( signal,
-1, 1,
height / 2 - amplitude / 2, height / 2 + amplitude / 2);
sketch.vertex(x, y);
}
sketch.endShape();
} else {
const dim = sketch.min(width, height);
polygon(width / 2, height / 2, dim * 0.1, 3);
}
}
function polygon(x, y, radius, sides = 3, angle = 0) {
sketch.fill('white');
sketch.beginShape();
for (let i = 0; i < sides; i++) {
const a = angle + sketch.TWO_PI * (i / sides);
let sx = x + sketch.cos(a) * radius;
let sy = y + sketch.sin(a) * radius;
sketch.vertex(sx, sy);
}
sketch.endShape(sketch.CLOSE);
sketch.noFill()
}
sketch.mousePressed = function () {
if (!audioContext) {
const AudioContext = window.AudioContext || window.webkitAudioContext;
audioContext = new AudioContext();
audio = document.createElement("audio");
audio.addEventListener(
"canplay",
() => {
console.log('audio can play')
audioContext.resume();
audio.play();
},
{ once: true }
);
audio.loop = true;
audio.crossOrigin = "Anonymous";
audio.src = urlPiano;
console.log('audio',audio)
const source = audioContext.createMediaElementSource(audio);
source.connect(audioContext.destination);
analyserNode = audioContext.createAnalyser();
const detail = 4;
analyserNode.fftSize = 2048 * detail;
isFloat = Boolean( analyserNode.getFloatTimeDomainData);
analyserData = new Float32Array( analyserNode.fftSize);
if (isFloat) {
analyserTarget = new Float32Array( analyserData.length);
} else {
analyserTarget = new Uint8Array( analyserData.length);
analyserTarget.fill(0xff / 2);
}
source.connect( analyserNode);
const fps = 12;
interval = setInterval(() => {
if (isFloat) {
analyserNode.getFloatTimeDomainData(analyserTarget);
} else {
analyserNode.getByteTimeDomainData(analyserTarget);
}
}, (1 / fps) * 1000);
} else {
audio.pause();
audioContext.close();
clearInterval(interval);
audioContext = null;
analyserNode = null;
}
}
function damp(a, b, lambda, dt) {
return sketch.lerp(a, b, 1 - Math.exp(-lambda * dt));
}
})