"use strict";
var datastorm = datastorm || {};
datastorm.audioStorm = (function(){
var my = {};
var config = {};
var music = null;
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var analyser;
var animationActive = true;
var dataArray, bufferLength, source;
var ctx = datastorm.canvas.ctx;
var width = document.body.clientWidth;
var height = document.body.clientHeight;
var waveXSpread = 0.1;
var xScale = d3.scale.linear().domain([0, 255]).range([(0.5 - waveXSpread) * width, (0.5 + waveXSpread) * width]);
var yScale = d3.scale.linear().domain([0, 512]).range([0, height]);
var lightningWaveXSpread = 0.15;
var lightningXScale = d3.scale.linear().domain([0, 255]).range([(0.5 - lightningWaveXSpread) * width, (0.5 + lightningWaveXSpread) * width]);
var xRandomOffset = 1000;
var yStep = 100;
var frameTimer, decreaseTimeStepTimer, clearFrameTime, expandXTimer, increaseXRandomOffsetTimer, decreaseYStepTimer;
var timeInterval = 1300;
function clearFrame() {
ctx.globalAlpha = 1;
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0, 0, width, height);
}
function getSumOfDeltas(data) {
var sum = 0;
for(var i = 1; i < bufferLength; i ++) {
sum += Math.abs(dataArray[i] - dataArray[i-1]);
}
return sum;
}
function chanceOfLightning(sumOfDeltas) {
if(sumOfDeltas < 600)
return 0;
return sumOfDeltas / 15000;
}
function doFrame() {
analyser.getByteTimeDomainData(dataArray);
ctx.strokeStyle = '#689';
ctx.lineWidth = 1;
ctx.globalAlpha = 1;
var chance = chanceOfLightning(getSumOfDeltas(dataArray));
if(Math.random() > chance) {
// normal
var xOffset = (Math.random() * xRandomOffset) - 0.5 * xRandomOffset;
for(var i = 1; i < bufferLength; i += yStep) {
var ii = i - yStep ;
datastorm.canvas.drawLine(xScale(dataArray[ii]) + xOffset, yScale(ii), xScale(dataArray[i]) + xOffset, yScale(i));
}
} else {
// ctx.strokeStyle = '#7DF9FF';
ctx.globalAlpha = Math.random() * 0.5 + 0.5;
var xOffset = 0.5 * (Math.random() * width - 0.5 * width);
// ctx.lineWidth = 2;
for(var i = 1; i < bufferLength; i += yStep) {
var ii = i - yStep ;
datastorm.canvas.drawLine(lightningXScale(dataArray[ii]) + xOffset, yScale(ii), lightningXScale(dataArray[i]) + xOffset, yScale(i));
}
}
}
function expandX() {
if(waveXSpread > 0.3)
return;
waveXSpread += 0.1;
xScale.range([(0.5 - waveXSpread) * width, (0.5 + waveXSpread) * width]);
}
function increaseXRandomOffset() {
if(xRandomOffset < 1)
return;
xRandomOffset -= 50;
}
function decreaseYStep() {
yStep -= 5;
if(yStep < 1)
yStep = 1;
}
function decreaseTimeStep() {
if(timeInterval <= 100)
return;
clearInterval(frameTimer);
timeInterval -= 200;
if(timeInterval < 100)
timeInterval = 100;
frameTimer = setInterval(doFrame, timeInterval);
}
function ready(buffer) {
music = buffer;
source = context.createBufferSource();
source.buffer = music;
analyser = context.createAnalyser();
analyser.fftSize = 1024;
bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
source.connect(analyser);
analyser.connect(context.destination);
if(config.autoStart === true)
my.start();
}
my.init = function(conf) {
config = conf;
var url = config.audioUrl;
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, ready);
}
request.send();
}
my.start = function() {
source.start(0);
frameTimer = setInterval(doFrame, timeInterval);
decreaseTimeStepTimer = setInterval(decreaseTimeStep, 20000);
clearFrameTime = setInterval(clearFrame, 40);
expandXTimer = setInterval(expandX, 30000);
increaseXRandomOffsetTimer = setInterval(increaseXRandomOffset, 10000);
decreaseYStepTimer = setInterval(decreaseYStep, 5000);
}
my.stop = function() {
animationActive = false;
clearInterval(frameTimer);
clearInterval(decreaseTimeStepTimer);
clearInterval(clearFrameTime);
clearInterval(expandXTimer);
clearInterval(increaseXRandomOffsetTimer);
clearInterval(decreaseYStepTimer);
source.stop();
}
return my;
}());
datastorm.audioStorm.init({
audioUrl: 'https://d28qoto45d39ov.cloudfront.net/datastorm/visualisations/audiostorm/sounds/allegretto.mp3',
autoStart: true
});
See the Pen Datastorm - Audiostorm by Genevieve Smith-Nunes (@readysaltedcode) on CodePen.