forked from jsantell/dancer.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdancer.min.js
8 lines (8 loc) · 6.98 KB
/
dancer.min.js
1
2
3
4
5
6
7
8
/*
* Dancer.js (c) 2012 Jordan Santell
* MIT License
* http://github.com/jsantell/dancer.js
*
* v0.1.0
*/
function FourierTransform(a,b){this.bufferSize=a,this.sampleRate=b,this.bandwidth=2/a*b/2,this.spectrum=new Float32Array(a/2),this.real=new Float32Array(a),this.imag=new Float32Array(a),this.peakBand=0,this.peak=0,this.getBandFrequency=function(a){return this.bandwidth*a+this.bandwidth/2},this.calculateSpectrum=function(){var b=this.spectrum,c=this.real,d=this.imag,e=2/this.bufferSize,f=Math.sqrt,g,h,i;for(var j=0,k=a/2;j<k;j++)g=c[j],h=d[j],i=e*f(g*g+h*h),i>this.peak&&(this.peakBand=j,this.peak=i),b[j]=i}}function FFT(a,b){FourierTransform.call(this,a,b),this.reverseTable=new Uint32Array(a);var c=1,d=a>>1,e;while(c<a){for(e=0;e<c;e++)this.reverseTable[e+c]=this.reverseTable[e]+d;c<<=1,d>>=1}this.sinTable=new Float32Array(a),this.cosTable=new Float32Array(a);for(e=0;e<a;e++)this.sinTable[e]=Math.sin(-Math.PI/e),this.cosTable[e]=Math.cos(-Math.PI/e)}(function(){function b(){for(var a in this.sections)this.sections[a].condition()&&this.sections[a].callback.call(this)}var a=function(c){this.audioAdapter=window.webkitAudioContext?new a.adapters.webkit(this):new a.adapters.moz(this),this.events={},this.sections=[],this.bind("update",b),this.audioAdapter.load(c)};a.adapters={},a.prototype={play:function(){return this.audioAdapter.play(),this},stop:function(){return this.audioAdapter.stop(),this},createBeat:function(b,c,d,e,f){return new a.Beat(this,b,c,d,e,f)},bind:function(a,b){return this.events[a]||(this.events[a]=[]),this.events[a].push(b),this},unbind:function(a){return this.events[a]&&delete this.events[a],this},trigger:function(a){var b=this;return this.events[a]&&this.events[a].forEach(function(a){a.call(b)}),this},getTime:function(){return this.audioAdapter.getTime()},getFrequency:function(a,b){var c=0;if(b!==undefined){for(var d=a;d<=b;d++)c+=this.getSpectrum()[d];return c/(b-a+1)}return this.getSpectrum()[a]},getSpectrum:function(){return this.audioAdapter.getSpectrum()},isLoaded:function(){return this.audioAdapter.isLoaded},isPlaying:function(){return this.audioAdapter.isPlaying},after:function(a,b){var c=this;return this.sections.push({condition:function(){return c.getTime()>a},callback:b}),this},before:function(a,b){var c=this;return this.sections.push({condition:function(){return c.getTime()<a},callback:b}),this},between:function(a,b,c){var d=this;return this.sections.push({condition:function(){return d.getTime()>a&&d.getTime()<b},callback:c}),this},onceAt:function(a,b){var c=this,d=null;return this.sections.push({condition:function(){return c.getTime()>a&&!this.called},callback:function(){b.call(this),d.called=!0},called:!1}),d=this.sections[this.sections.length-1],this}},a.addPlugin=function(b,c){a.prototype[b]===undefined&&(a.prototype[b]=c)},a.isSupported=function(){return!!(window.AudioContext||window.webkitAudioContext||window.Audio&&(new window.Audio).mozSetup)},window.Dancer=a})(),function(){var a=function(a,b){b=b||{},this.dancer=a,this.frequency=b.frequency||[0,10],this.threshold=b.threshold||.3,this.decay=b.decay||.02,this.onBeat=b.onBeat,this.offBeat=b.offBeat,this.isOn=!1,this.currentThreshold=this.threshold;var c=this;this.dancer.bind("update",function(){c.onUpdate()})};a.prototype={on:function(){return this.isOn=!0,this},off:function(){return this.isOn=!1,this},onUpdate:function(){if(!this.isOn)return;var a=this.maxAmplitude(this.frequency);a>=this.currentThreshold&&a>=this.threshold?(this.currentThreshold=a,this.onBeat&&this.onBeat.call(this.dancer,a)):(this.offBeat&&this.offBeat.call(this.dancer,a),this.currentThreshold-=this.decay)},maxAmplitude:function(a){var b=0,c=this.dancer.getSpectrum();if(!a.length)return a<c.length?c[~~a]:null;for(var d=a[0],e=a[1];d<=e;d++)c[d]>b&&(b=c[d]);return b}},window.Dancer.Beat=a}(),function(){function d(){this.source=this.context.createBufferSource(),this.source.buffer=this.buffer,this.source.connect(this.context.destination),this.source.connect(this.proc),this.source.connect(this.context.destination)}function e(a,b){return a[i]+b[i]}var a=2048,b=44100,c=function(a){this.dancer=a,this.context=window.AudioContext?new window.AudioContext:new window.webkitAudioContext,this.isLoaded=!1,this.isPlaying=!1,this.isDisconnected=!1};c.prototype={load:function(c,e){var f=new XMLHttpRequest,g=this;f.open("GET",c,!0),f.responseType="arraybuffer",f.onload=function(){g.context.decodeAudioData?g.context.decodeAudioData(f.response,function(a){g.buffer=a,d.call(g),g.isLoaded=!0,g.dancer.trigger("loaded")},function(a){console.log(a)}):(g.buffer=g.context.createBuffer(f.response,!1),d.call(g),g.isLoaded=!0,g.dancer.trigger("loaded"))},f.send(),this.proc=this.context.createJavaScriptNode(a/2,1,1),this.proc.onaudioprocess=function(a){g.update.call(g,a)},this.proc.connect(this.context.destination),this.fft=new FFT(a/2,b),this.signal=new Float32Array(a/2)},play:function(){function b(){a.isDisconnected&&d.call(a),a.source.noteOn(0),a.isPlaying=!0}var a=this;this.isLoaded?b():this.dancer.bind("loaded",b)},stop:function(){this.isPlaying&&(this.source.noteOff(0),this.isDisconnected=!0),this.isPlaying=!1},getSpectrum:function(){return this.fft.spectrum},getTime:function(){return this.context.currentTime},update:function(b){if(!this.isPlaying)return;var c=[],d=b.inputBuffer.numberOfChannels,f=a/d;for(i=d;i--;)c.push(b.inputBuffer.getChannelData(i));for(i=0;i<f;i++)this.signal[i]=d>1?c.reduce(e)/d:c[0][i];this.fft.forward(this.signal),this.dancer.trigger("update")}},Dancer.adapters.webkit=c}(),function(){var a=function(a){this.dancer=a,this.audio=new Audio,this.isLoaded=this.isPlaying=!1};a.prototype={load:function(a){var b=this;this.audio.src=a,this.audio.addEventListener("loadedmetadata",function(a){b.fbLength=b.audio.mozFrameBufferLength,b.channels=b.audio.mozChannels,b.rate=b.audio.mozSampleRate,b.fft=new FFT(b.fbLength/b.channels,b.rate),b.signal=new Float32Array(b.fbLength/b.channels),b.isLoaded=!0,b.dancer.trigger("loaded")},!1),this.audio.addEventListener("MozAudioAvailable",function(a){b.update(a)},!1)},play:function(){this.audio.play(),this.isPlaying=!0},stop:function(){this.audio.pause(),this.isPlaying=!1},getSpectrum:function(){return this.fft.spectrum},getTime:function(){return this.audio.currentTime},update:function(a){if(!this.isLoaded)return;for(var b=0,c=this.fbLength/2;b<c;b++)this.signal[b]=(a.frameBuffer[2*b]+a.frameBuffer[2*b+1])/2;this.fft.forward(this.signal),this.dancer.trigger("update")}},Dancer.adapters.moz=a}(),FFT.prototype.forward=function(a){var b=this.bufferSize,c=this.cosTable,d=this.sinTable,e=this.reverseTable,f=this.real,g=this.imag,h=this.spectrum,i=Math.floor(Math.log(b)/Math.LN2);if(Math.pow(2,i)!==b)throw"Invalid buffer size, must be a power of 2.";if(b!==a.length)throw"Supplied buffer is not the same size as defined FFT. FFT Size: "+b+" Buffer Size: "+a.length;var j=1,k,l,m,n,o,p,q,r,s;for(s=0;s<b;s++)f[s]=a[e[s]],g[s]=0;while(j<b){k=c[j],l=d[j],m=1,n=0;for(var t=0;t<j;t++){s=t;while(s<b)o=s+j,p=m*f[o]-n*g[o],q=m*g[o]+n*f[o],f[o]=f[s]-p,g[o]=g[s]-q,f[s]+=p,g[s]+=q,s+=j<<1;r=m,m=r*k-n*l,n=r*l+n*k}j<<=1}return this.calculateSpectrum()}