167 lines
6.0 KiB
JavaScript
167 lines
6.0 KiB
JavaScript
/* wormTune Audio Visualizer */
|
|
|
|
var modes = ["None", "Bars","Scope","Spectrogram","Laser Rain"];
|
|
var drawRequest = 0;
|
|
var renderInverval;
|
|
|
|
function createVisualizer(player, context) {
|
|
var audioSrc = context.createMediaElementSource(player);
|
|
analyser = context.createAnalyser();
|
|
|
|
var canvas = document.querySelector("canvas.vis");
|
|
|
|
audioSrc.connect(analyser);
|
|
analyser.connect(context.destination);
|
|
|
|
setVisualizer(canvas, analyser, 0);
|
|
|
|
return analyser;
|
|
};
|
|
|
|
function setVisualizer(canvas, analyser, mode = 0) {
|
|
if (!analyser) return;
|
|
clearInterval(renderInverval);
|
|
var ctx = canvas.getContext("2d",{antialias: false,alpha: false});
|
|
|
|
var WIDTH = canvas.width;
|
|
var HEIGHT = canvas.height;
|
|
|
|
// Set the "defaults"
|
|
analyser.smoothingTimeConstant = 0.8;
|
|
analyser.fftSize = 2048;
|
|
|
|
if (mode != -1) canvas.height = 96;
|
|
|
|
window.cancelAnimationFrame(drawRequest);
|
|
if (mode == -1) { // VIDEO MODE
|
|
canvas.height = canvas.width / 4 * 3;
|
|
renderInverval = window.setInterval(() => {
|
|
ctx.drawImage(audioPlayer, 0, 0, WIDTH, HEIGHT);
|
|
}, 1000 / 24);
|
|
} else if (mode == 0 || mode > modes.length - 1) {
|
|
function draw() {
|
|
drawRequest = window.requestAnimationFrame(draw);
|
|
|
|
ctx.clearRect(0,0,WIDTH,HEIGHT);
|
|
|
|
ctx.font = "16px Pixio";
|
|
ctx.fillStyle = "#FFF";
|
|
ctx.textAlign = "center";
|
|
ctx.fillText("Click here to cycle visualizations.", WIDTH/2,HEIGHT/2);
|
|
}
|
|
draw();
|
|
} else if (mode == 1) { // BAR
|
|
analyser.fftSize = 256;
|
|
var bufferLength = analyser.frequencyBinCount;
|
|
var dataArray = new Uint8Array(bufferLength)
|
|
|
|
var barWidth = (WIDTH / bufferLength) * 2.5;
|
|
var barHeight;
|
|
|
|
function draw() {
|
|
ctx.clearRect(0, 0, WIDTH, HEIGHT);
|
|
drawRequest = window.requestAnimationFrame(draw);
|
|
|
|
analyser.getByteFrequencyData(dataArray);
|
|
ctx.fillStyle = "#FFF";
|
|
|
|
var x = 0;
|
|
|
|
ctx.beginPath();
|
|
for (var i = 0; i < bufferLength; i++) {
|
|
barHeight = (dataArray[i] / 256) * HEIGHT;
|
|
ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight);
|
|
x += barWidth + 1;
|
|
}
|
|
ctx.closePath();
|
|
}
|
|
draw();
|
|
} else if (mode == 2) { // SCOPE
|
|
analyser.smoothingTimeConstant = 0;
|
|
var dataArray = new Uint8Array(analyser.fftSize)
|
|
|
|
function draw() {
|
|
ctx.clearRect(0, 0, WIDTH, HEIGHT);
|
|
drawRequest = window.requestAnimationFrame(draw);
|
|
|
|
analyser.getByteTimeDomainData(dataArray);
|
|
const step = WIDTH / dataArray.length;
|
|
|
|
ctx.strokeStyle = "#0F0";
|
|
|
|
ctx.beginPath();
|
|
for (let i = 0; i < dataArray.length; i += 2) {
|
|
const percent = dataArray[i] / 256;
|
|
const x = i * step;
|
|
const y = HEIGHT * percent;
|
|
ctx.lineTo(x, y);
|
|
}
|
|
ctx.stroke();
|
|
}
|
|
draw();
|
|
} else if (mode == 3) { // SPECTROGRAM
|
|
analyser.smoothingTimeConstant = 0;
|
|
|
|
var tempCanvas = document.createElement("canvas"),
|
|
tempCtx = tempCanvas.getContext("2d");
|
|
tempCanvas.width = WIDTH;
|
|
tempCanvas.height = HEIGHT;
|
|
|
|
analyser.fftSize = Math.pow(2, Math.ceil(Math.log(WIDTH)/Math.log(2)));
|
|
|
|
var bufferLength = analyser.frequencyBinCount;
|
|
var dataArray = new Uint8Array(bufferLength);
|
|
|
|
var start = new Date();
|
|
//ctx.clearRect(0,0,WIDTH,HEIGHT);
|
|
function draw() {
|
|
drawRequest = window.requestAnimationFrame(draw);
|
|
|
|
analyser.getByteFrequencyData(dataArray);
|
|
var barHeight = WIDTH/analyser.fftSize;
|
|
|
|
var now = new Date();
|
|
if (now < new Date(start.getTime() + 20)) { return; }
|
|
start = now;
|
|
|
|
tempCtx.drawImage(ctx.canvas, 0, 0, WIDTH, HEIGHT);
|
|
|
|
for (var i = 0; i < dataArray.length; i++) {
|
|
var value = dataArray[i];
|
|
ctx.fillStyle = 'rgb('+((value > 190) ? 255 : value)+', '+ ((value > 220) ? 255 : value-100) +', 0)';
|
|
ctx.fillRect(WIDTH - 1, HEIGHT - i*barHeight, 1, barHeight);
|
|
}
|
|
ctx.translate(-1, 0);
|
|
ctx.drawImage(tempCanvas, 0, 0, WIDTH, HEIGHT, 0, 0, WIDTH, HEIGHT);
|
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
}
|
|
draw();
|
|
} else if (mode == 4) { // RUNWAY
|
|
analyser.smoothingTimeConstant = 0.2;
|
|
|
|
var bufferLength = analyser.frequencyBinCount;
|
|
var dataArray = new Uint8Array(bufferLength);
|
|
|
|
//ctx.clearRect(0,0,WIDTH,HEIGHT);
|
|
function draw() {
|
|
drawRequest = window.requestAnimationFrame(draw);
|
|
|
|
analyser.getByteFrequencyData(dataArray);
|
|
|
|
ctx.clearRect(0,0,WIDTH,HEIGHT);
|
|
for (var i = 0; i < dataArray.length; i++) {
|
|
if (dataArray[i] == 0) continue;
|
|
ctx.fillStyle = 'rgb('+dataArray[i]/4+','+dataArray[i]/2+','+dataArray[i]+')';
|
|
ctx.fillRect((WIDTH / 2)+i, 0, 1, HEIGHT);
|
|
ctx.fillRect((WIDTH / 2)-(i+1), 0, 1, HEIGHT);
|
|
}
|
|
// You are probably wondering how I got here, huh? Questioning my very sanity. Or maybe you completely understand, and as a web-developer, very well know the experience of bending the knees for Chrome in order to get something working that already works everywhere else. Since I've explained it, I think regardless, you understand now.
|
|
ctx.font = "16px Pixio";
|
|
ctx.fillStyle = "#4080FF0A";
|
|
ctx.textAlign = "center";
|
|
ctx.fillText("0x4655434B204348524F4D45",WIDTH/2,HEIGHT/2);
|
|
}
|
|
draw();
|
|
}
|
|
}
|