mirror of
https://github.com/wahyd4/cdnjs.git
synced 2026-08-19 01:36:01 +10:00
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* Dancer.js (c) 2012 Jordan Santell
|
||||
* MIT License
|
||||
* http://github.com/jsantell/dancer.js
|
||||
*
|
||||
* v0.0.1
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var Dancer = function ( source ) {
|
||||
this.audioAdapter = window.webkitAudioContext ?
|
||||
new Dancer.adapters.webkit( this ) :
|
||||
new Dancer.adapters.moz( this );
|
||||
this.events = {};
|
||||
this.sections = [];
|
||||
|
||||
this.bind( 'update', update );
|
||||
this.audioAdapter.load( source );
|
||||
};
|
||||
Dancer.adapters = {};
|
||||
|
||||
Dancer.prototype = {
|
||||
/* Controls */
|
||||
|
||||
play : function () {
|
||||
this.audioAdapter.play();
|
||||
return this;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audioAdapter.stop();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Actions */
|
||||
|
||||
createBeat : function ( freq, threshold, decay, onBeat, offBeat ) {
|
||||
return new Dancer.Beat( this, freq, threshold, decay, onBeat, offBeat );
|
||||
},
|
||||
|
||||
bind : function ( name, callback ) {
|
||||
if ( !this.events[ name ] ) {
|
||||
this.events[ name ] = [];
|
||||
}
|
||||
this.events[ name ].push( callback );
|
||||
return this;
|
||||
},
|
||||
|
||||
unbind : function ( name ) {
|
||||
if ( this.events[ name ] ) {
|
||||
delete this.events[ name ];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
trigger : function ( name ) {
|
||||
var _this = this;
|
||||
if ( this.events[ name ] ) {
|
||||
this.events[ name ].forEach(function( callback ) {
|
||||
callback.call( _this );
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Getters */
|
||||
|
||||
getTime : function () {
|
||||
return this.audioAdapter.getTime();
|
||||
},
|
||||
|
||||
// Returns the magnitude of a frequency or average over a range of frequencies
|
||||
getFrequency : function ( freq, endFreq ) {
|
||||
var subFreq, sum = 0;
|
||||
if ( endFreq !== undefined ) {
|
||||
for ( var i = freq; i <= endFreq; i++ ) {
|
||||
sum += this.getSpectrum()[ i ];
|
||||
}
|
||||
return sum / ( endFreq - freq + 1 );
|
||||
} else {
|
||||
return this.getSpectrum()[ freq ];
|
||||
}
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.audioAdapter.getSpectrum();
|
||||
},
|
||||
|
||||
isLoaded : function () {
|
||||
return this.audioAdapter.isLoaded;
|
||||
},
|
||||
|
||||
isPlaying : function () {
|
||||
return this.audioAdapter.isPlaying;
|
||||
},
|
||||
|
||||
|
||||
/* Sections */
|
||||
|
||||
after : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
before : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() < time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
between : function ( startTime, endTime, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > startTime && _this.getTime() < endTime;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
onceAt : function ( time, callback ) {
|
||||
var
|
||||
_this = this,
|
||||
thisSection = null;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time && !this.called;
|
||||
},
|
||||
callback : function () {
|
||||
callback.call( this );
|
||||
thisSection.called = true;
|
||||
},
|
||||
called : false
|
||||
});
|
||||
// Baking the section in the closure due to callback's this being the dancer instance
|
||||
thisSection = this.sections[ this.sections.length - 1 ];
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.addPlugin = function ( name, fn ) {
|
||||
if ( Dancer.prototype[ name ] === undefined ) {
|
||||
Dancer.prototype[ name ] = fn;
|
||||
}
|
||||
};
|
||||
|
||||
function update () {
|
||||
for ( var i in this.sections ) {
|
||||
if ( this.sections[ i ].condition() )
|
||||
this.sections[ i ].callback.call( this );
|
||||
}
|
||||
}
|
||||
|
||||
window.Dancer = Dancer;
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var Beat = function ( dancer, options ) {
|
||||
options = options || {};
|
||||
this.dancer = dancer;
|
||||
this.frequency = options.frequency || [ 0, 10 ];
|
||||
this.threshold = options.threshold || 0.3;
|
||||
this.decay = options.decay || 0.02;
|
||||
this.onBeat = options.onBeat;
|
||||
this.offBeat = options.offBeat;
|
||||
this.isOn = false;
|
||||
this.currentThreshold = this.threshold;
|
||||
|
||||
var _this = this;
|
||||
this.dancer.bind( 'update', function () {
|
||||
_this.onUpdate();
|
||||
});
|
||||
};
|
||||
|
||||
Beat.prototype = {
|
||||
on : function () {
|
||||
this.isOn = true;
|
||||
return this;
|
||||
},
|
||||
off : function () {
|
||||
this.isOn = false;
|
||||
return this;
|
||||
},
|
||||
onUpdate : function () {
|
||||
if ( !this.isOn ) { return; }
|
||||
var magnitude = this.maxAmplitude( this.frequency );
|
||||
if ( magnitude >= this.currentThreshold &&
|
||||
magnitude >= this.threshold ) {
|
||||
this.currentThreshold = magnitude;
|
||||
this.onBeat && this.onBeat.call( this.dancer, magnitude );
|
||||
} else {
|
||||
this.offBeat && this.offBeat.call( this.dancer, magnitude );
|
||||
this.currentThreshold -= this.decay;
|
||||
}
|
||||
},
|
||||
maxAmplitude : function ( frequency ) {
|
||||
var
|
||||
max = 0,
|
||||
fft = this.dancer.getSpectrum();
|
||||
|
||||
// Sloppy array check
|
||||
if ( !frequency.length ) {
|
||||
return frequency < fft.length ?
|
||||
fft[ ~~frequency ] :
|
||||
null;
|
||||
}
|
||||
|
||||
for ( var i = frequency[ 0 ], l = frequency[ 1 ]; i <= l; i++ ) {
|
||||
if ( fft[ i ] > max ) { max = fft[ i ]; }
|
||||
}
|
||||
return max;
|
||||
}
|
||||
};
|
||||
|
||||
window.Dancer.Beat = Beat;
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
SAMPLE_SIZE = 2048,
|
||||
SAMPLE_RATE = 44100;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.context = window.audioContext ?
|
||||
new window.AudioContext() :
|
||||
new window.webkitAudioContext();
|
||||
this.isLoaded = false;
|
||||
this.isPlaying= false;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path, callback ) {
|
||||
var
|
||||
req = new XMLHttpRequest(),
|
||||
_this = this;
|
||||
|
||||
this.source = this.context.createBufferSource();
|
||||
|
||||
req.open( 'GET', path, true );
|
||||
req.responseType = 'arraybuffer';
|
||||
|
||||
req.onload = function () {
|
||||
if ( _this.context.decodeAudioData ) {
|
||||
_this.context.decodeAudioData( req.response, function( buffer ) {
|
||||
_this.source.buffer = buffer;
|
||||
}, function( e ) {
|
||||
console.log( e );
|
||||
});
|
||||
} else {
|
||||
_this.source.buffer = _this.context.createBuffer( req.response, false );
|
||||
}
|
||||
_this.source.connect( _this.context.destination );
|
||||
_this.source.connect( _this.proc );
|
||||
_this.proc.connect( _this.context.destination );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
};
|
||||
req.send();
|
||||
|
||||
this.proc = this.context.createJavaScriptNode( SAMPLE_SIZE / 2, 1, 1 );
|
||||
this.proc.onaudioprocess = function ( e ) {
|
||||
_this.update.call( _this, e );
|
||||
};
|
||||
this.source.connect( this.context.destination );
|
||||
this.fft = new FFT( SAMPLE_SIZE / 2, SAMPLE_RATE );
|
||||
this.signal = new Float32Array( SAMPLE_SIZE / 2 );
|
||||
},
|
||||
|
||||
play : function () {
|
||||
var _this = this;
|
||||
|
||||
this.isLoaded ?
|
||||
play() :
|
||||
this.dancer.bind( 'loaded', play );
|
||||
|
||||
function play () {
|
||||
_this.source.noteOn( 0.0 );
|
||||
_this.isPlaying = true;
|
||||
}
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.source.noteOff(0);
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.context.currentTime;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isPlaying ) { return; }
|
||||
var
|
||||
bufferL = e.inputBuffer.getChannelData(0),
|
||||
bufferR = e.inputBuffer.getChannelData(1);
|
||||
|
||||
for ( var i = 0, j = SAMPLE_SIZE / 2; i < j; i++ ) {
|
||||
this.signal[ i ] = ( bufferL[ i ] + bufferR[ i ] ) / 2;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.adapters.webkit = adapter;
|
||||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.audio = new Audio();
|
||||
this.isLoaded = this.isPlaying = false;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path ) {
|
||||
var _this = this;
|
||||
this.audio.src = path;
|
||||
this.audio.addEventListener( 'loadedmetadata', function( e ) {
|
||||
_this.fbLength = _this.audio.mozFrameBufferLength;
|
||||
_this.channels = _this.audio.mozChannels;
|
||||
_this.rate = _this.audio.mozSampleRate;
|
||||
_this.fft = new FFT( _this.fbLength / _this.channels, _this.rate );
|
||||
_this.signal = new Float32Array( _this.fbLength / _this.channels );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}, false);
|
||||
this.audio.addEventListener( 'MozAudioAvailable', function( e ) {
|
||||
_this.update( e );
|
||||
}, false);
|
||||
},
|
||||
|
||||
play : function () {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audio.pause();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.currentTime;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isLoaded ) return;
|
||||
|
||||
for ( var i = 0, j = this.fbLength / 2; i < j; i++ ) {
|
||||
this.signal[ i ] = ( e.frameBuffer[ 2 * i ] + e.frameBuffer[ 2 * i + 1 ] ) / 2;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.adapters.moz = adapter;
|
||||
|
||||
})();
|
||||
|
||||
/*
|
||||
* DSP.js - a comprehensive digital signal processing library for javascript
|
||||
*
|
||||
* Created by Corban Brook <corbanbrook@gmail.com> on 2010-01-01.
|
||||
* Copyright 2010 Corban Brook. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// Fourier Transform Module used by DFT, FFT, RFFT
|
||||
function FourierTransform(bufferSize, sampleRate) {
|
||||
this.bufferSize = bufferSize;
|
||||
this.sampleRate = sampleRate;
|
||||
this.bandwidth = 2 / bufferSize * sampleRate / 2;
|
||||
|
||||
this.spectrum = new Float32Array(bufferSize/2);
|
||||
this.real = new Float32Array(bufferSize);
|
||||
this.imag = new Float32Array(bufferSize);
|
||||
|
||||
this.peakBand = 0;
|
||||
this.peak = 0;
|
||||
|
||||
/**
|
||||
* Calculates the *middle* frequency of an FFT band.
|
||||
*
|
||||
* @param {Number} index The index of the FFT band.
|
||||
*
|
||||
* @returns The middle frequency in Hz.
|
||||
*/
|
||||
this.getBandFrequency = function(index) {
|
||||
return this.bandwidth * index + this.bandwidth / 2;
|
||||
};
|
||||
|
||||
this.calculateSpectrum = function() {
|
||||
var spectrum = this.spectrum,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
bSi = 2 / this.bufferSize,
|
||||
sqrt = Math.sqrt,
|
||||
rval,
|
||||
ival,
|
||||
mag;
|
||||
|
||||
for (var i = 0, N = bufferSize/2; i < N; i++) {
|
||||
rval = real[i];
|
||||
ival = imag[i];
|
||||
mag = bSi * sqrt(rval * rval + ival * ival);
|
||||
|
||||
if (mag > this.peak) {
|
||||
this.peakBand = i;
|
||||
this.peak = mag;
|
||||
}
|
||||
|
||||
spectrum[i] = mag;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* FFT is a class for calculating the Discrete Fourier Transform of a signal
|
||||
* with the Fast Fourier Transform algorithm.
|
||||
*
|
||||
* @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
|
||||
* @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FFT(bufferSize, sampleRate) {
|
||||
FourierTransform.call(this, bufferSize, sampleRate);
|
||||
|
||||
this.reverseTable = new Uint32Array(bufferSize);
|
||||
|
||||
var limit = 1;
|
||||
var bit = bufferSize >> 1;
|
||||
|
||||
var i;
|
||||
|
||||
while (limit < bufferSize) {
|
||||
for (i = 0; i < limit; i++) {
|
||||
this.reverseTable[i + limit] = this.reverseTable[i] + bit;
|
||||
}
|
||||
|
||||
limit = limit << 1;
|
||||
bit = bit >> 1;
|
||||
}
|
||||
|
||||
this.sinTable = new Float32Array(bufferSize);
|
||||
this.cosTable = new Float32Array(bufferSize);
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
this.sinTable[i] = Math.sin(-Math.PI/i);
|
||||
this.cosTable[i] = Math.cos(-Math.PI/i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a forward transform on the sample buffer.
|
||||
* Converts a time domain signal to frequency domain spectra.
|
||||
*
|
||||
* @param {Array} buffer The sample buffer. Buffer Length must be power of 2
|
||||
*
|
||||
* @returns The frequency spectrum array
|
||||
*/
|
||||
FFT.prototype.forward = function(buffer) {
|
||||
// Locally scope variables for speed up
|
||||
var bufferSize = this.bufferSize,
|
||||
cosTable = this.cosTable,
|
||||
sinTable = this.sinTable,
|
||||
reverseTable = this.reverseTable,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
spectrum = this.spectrum;
|
||||
|
||||
var k = Math.floor(Math.log(bufferSize) / Math.LN2);
|
||||
|
||||
if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
|
||||
if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
|
||||
|
||||
var halfSize = 1,
|
||||
phaseShiftStepReal,
|
||||
phaseShiftStepImag,
|
||||
currentPhaseShiftReal,
|
||||
currentPhaseShiftImag,
|
||||
off,
|
||||
tr,
|
||||
ti,
|
||||
tmpReal,
|
||||
i;
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
real[i] = buffer[reverseTable[i]];
|
||||
imag[i] = 0;
|
||||
}
|
||||
|
||||
while (halfSize < bufferSize) {
|
||||
//phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
|
||||
//phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
|
||||
phaseShiftStepReal = cosTable[halfSize];
|
||||
phaseShiftStepImag = sinTable[halfSize];
|
||||
|
||||
currentPhaseShiftReal = 1;
|
||||
currentPhaseShiftImag = 0;
|
||||
|
||||
for (var fftStep = 0; fftStep < halfSize; fftStep++) {
|
||||
i = fftStep;
|
||||
|
||||
while (i < bufferSize) {
|
||||
off = i + halfSize;
|
||||
tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
|
||||
ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
|
||||
|
||||
real[off] = real[i] - tr;
|
||||
imag[off] = imag[i] - ti;
|
||||
real[i] += tr;
|
||||
imag[i] += ti;
|
||||
|
||||
i += halfSize << 1;
|
||||
}
|
||||
|
||||
tmpReal = currentPhaseShiftReal;
|
||||
currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
|
||||
currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
|
||||
}
|
||||
|
||||
halfSize = halfSize << 1;
|
||||
}
|
||||
|
||||
return this.calculateSpectrum();
|
||||
};
|
||||
+8
File diff suppressed because one or more lines are too long
@@ -0,0 +1,977 @@
|
||||
/*
|
||||
* Dancer.js (c) 2012 Jordan Santell
|
||||
* MIT License
|
||||
* http://github.com/jsantell/dancer.js
|
||||
*
|
||||
* v0.2.0
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var Dancer = function ( source, codecs ) {
|
||||
this.audioAdapter = Dancer._getAdapter( this );
|
||||
this.events = {};
|
||||
this.sections = [];
|
||||
|
||||
this.bind( 'update', update );
|
||||
this.source = Dancer._makeSupportedPath( source, codecs );
|
||||
this.audioAdapter.load( this.source );
|
||||
};
|
||||
|
||||
Dancer.adapters = {};
|
||||
|
||||
Dancer.prototype = {
|
||||
/* Controls */
|
||||
|
||||
play : function () {
|
||||
this.audioAdapter.play();
|
||||
return this;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audioAdapter.stop();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Actions */
|
||||
|
||||
createBeat : function ( freq, threshold, decay, onBeat, offBeat ) {
|
||||
return new Dancer.Beat( this, freq, threshold, decay, onBeat, offBeat );
|
||||
},
|
||||
|
||||
bind : function ( name, callback ) {
|
||||
if ( !this.events[ name ] ) {
|
||||
this.events[ name ] = [];
|
||||
}
|
||||
this.events[ name ].push( callback );
|
||||
return this;
|
||||
},
|
||||
|
||||
unbind : function ( name ) {
|
||||
if ( this.events[ name ] ) {
|
||||
delete this.events[ name ];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
trigger : function ( name ) {
|
||||
var _this = this;
|
||||
if ( this.events[ name ] ) {
|
||||
this.events[ name ].forEach(function( callback ) {
|
||||
callback.call( _this );
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Getters */
|
||||
|
||||
getTime : function () {
|
||||
return this.audioAdapter.getTime();
|
||||
},
|
||||
|
||||
// Returns the magnitude of a frequency or average over a range of frequencies
|
||||
getFrequency : function ( freq, endFreq ) {
|
||||
var sum = 0;
|
||||
if ( endFreq !== undefined ) {
|
||||
for ( var i = freq; i <= endFreq; i++ ) {
|
||||
sum += this.getSpectrum()[ i ];
|
||||
}
|
||||
return sum / ( endFreq - freq + 1 );
|
||||
} else {
|
||||
return this.getSpectrum()[ freq ];
|
||||
}
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.audioAdapter.getSpectrum();
|
||||
},
|
||||
|
||||
isLoaded : function () {
|
||||
return this.audioAdapter.isLoaded;
|
||||
},
|
||||
|
||||
isPlaying : function () {
|
||||
return this.audioAdapter.isPlaying;
|
||||
},
|
||||
|
||||
|
||||
/* Sections */
|
||||
|
||||
after : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
before : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() < time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
between : function ( startTime, endTime, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > startTime && _this.getTime() < endTime;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
onceAt : function ( time, callback ) {
|
||||
var
|
||||
_this = this,
|
||||
thisSection = null;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time && !this.called;
|
||||
},
|
||||
callback : function () {
|
||||
callback.call( this );
|
||||
thisSection.called = true;
|
||||
},
|
||||
called : false
|
||||
});
|
||||
// Baking the section in the closure due to callback's this being the dancer instance
|
||||
thisSection = this.sections[ this.sections.length - 1 ];
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
function update () {
|
||||
for ( var i in this.sections ) {
|
||||
if ( this.sections[ i ].condition() )
|
||||
this.sections[ i ].callback.call( this );
|
||||
}
|
||||
}
|
||||
|
||||
window.Dancer = Dancer;
|
||||
})();
|
||||
|
||||
(function ( Dancer ) {
|
||||
|
||||
var CODECS = {
|
||||
'mp3' : 'audio/mpeg;',
|
||||
'ogg' : 'audio/ogg; codecs="vorbis"',
|
||||
'wav' : 'audio/wav; codecs="1"',
|
||||
'aac' : 'audio/mp4; codecs="mp4a.40.2"'
|
||||
},
|
||||
audioEl = document.createElement( 'audio' );
|
||||
|
||||
Dancer.options = {};
|
||||
|
||||
Dancer.setOptions = function ( o ) {
|
||||
for ( var option in o ) {
|
||||
if ( o.hasOwnProperty( option ) ) {
|
||||
Dancer.options[ option ] = o[ option ];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.isSupported = function () {
|
||||
if ( !window.Float32Array || !window.Uint32Array ) {
|
||||
return null;
|
||||
} else if ( window.AudioContext || window.webkitAudioContext ) {
|
||||
return 'webaudio';
|
||||
} else if ( window.Audio && ( new window.Audio() ).mozSetup ) {
|
||||
return 'audiodata';
|
||||
} else if ( FlashDetect.versionAtLeast( 9 ) ) {
|
||||
return 'flash';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.canPlay = function ( type ) {
|
||||
var canPlay = audioEl.canPlayType;
|
||||
return !!(
|
||||
Dancer.isSupported() === 'flash' ?
|
||||
type.toLowerCase() === 'mp3' :
|
||||
audioEl.canPlayType &&
|
||||
audioEl.canPlayType( CODECS[ type.toLowerCase() ] ).replace( /no/, ''));
|
||||
};
|
||||
|
||||
Dancer.addPlugin = function ( name, fn ) {
|
||||
if ( Dancer.prototype[ name ] === undefined ) {
|
||||
Dancer.prototype[ name ] = fn;
|
||||
}
|
||||
};
|
||||
|
||||
Dancer._makeSupportedPath = function ( source, codecs ) {
|
||||
if ( !codecs ) { return source; }
|
||||
|
||||
for ( var i = 0; i < codecs.length; i++ ) {
|
||||
if ( Dancer.canPlay( codecs[ i ] ) ) {
|
||||
return source + '.' + codecs[ i ];
|
||||
}
|
||||
}
|
||||
return source;
|
||||
};
|
||||
|
||||
Dancer._getAdapter = function ( instance ) {
|
||||
switch ( Dancer.isSupported() ) {
|
||||
case 'webaudio':
|
||||
return new Dancer.adapters.webkit( instance );
|
||||
case 'audiodata':
|
||||
return new Dancer.adapters.moz( instance );
|
||||
case 'flash':
|
||||
return new Dancer.adapters.flash( instance );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
})( window.Dancer );
|
||||
|
||||
(function() {
|
||||
var Beat = function ( dancer, options ) {
|
||||
options = options || {};
|
||||
this.dancer = dancer;
|
||||
this.frequency = options.frequency || [ 0, 10 ];
|
||||
this.threshold = options.threshold || 0.3;
|
||||
this.decay = options.decay || 0.02;
|
||||
this.onBeat = options.onBeat;
|
||||
this.offBeat = options.offBeat;
|
||||
this.isOn = false;
|
||||
this.currentThreshold = this.threshold;
|
||||
|
||||
var _this = this;
|
||||
this.dancer.bind( 'update', function () {
|
||||
_this.onUpdate();
|
||||
});
|
||||
};
|
||||
|
||||
Beat.prototype = {
|
||||
on : function () {
|
||||
this.isOn = true;
|
||||
return this;
|
||||
},
|
||||
off : function () {
|
||||
this.isOn = false;
|
||||
return this;
|
||||
},
|
||||
onUpdate : function () {
|
||||
if ( !this.isOn ) { return; }
|
||||
var magnitude = this.maxAmplitude( this.frequency );
|
||||
if ( magnitude >= this.currentThreshold &&
|
||||
magnitude >= this.threshold ) {
|
||||
this.currentThreshold = magnitude;
|
||||
this.onBeat && this.onBeat.call( this.dancer, magnitude );
|
||||
} else {
|
||||
this.offBeat && this.offBeat.call( this.dancer, magnitude );
|
||||
this.currentThreshold -= this.decay;
|
||||
}
|
||||
},
|
||||
maxAmplitude : function ( frequency ) {
|
||||
var
|
||||
max = 0,
|
||||
fft = this.dancer.getSpectrum();
|
||||
|
||||
// Sloppy array check
|
||||
if ( !frequency.length ) {
|
||||
return frequency < fft.length ?
|
||||
fft[ ~~frequency ] :
|
||||
null;
|
||||
}
|
||||
|
||||
for ( var i = frequency[ 0 ], l = frequency[ 1 ]; i <= l; i++ ) {
|
||||
if ( fft[ i ] > max ) { max = fft[ i ]; }
|
||||
}
|
||||
return max;
|
||||
}
|
||||
};
|
||||
|
||||
window.Dancer.Beat = Beat;
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
SAMPLE_SIZE = 2048,
|
||||
SAMPLE_RATE = 44100;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.context = window.AudioContext ?
|
||||
new window.AudioContext() :
|
||||
new window.webkitAudioContext();
|
||||
this.isLoaded = false;
|
||||
this.isPlaying = false;
|
||||
this.isDisconnected = false;
|
||||
};
|
||||
|
||||
function connectContext () {
|
||||
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 );
|
||||
}
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path ) {
|
||||
var
|
||||
req = new XMLHttpRequest(),
|
||||
_this = this;
|
||||
|
||||
req.open( 'GET', path, true );
|
||||
req.responseType = 'arraybuffer';
|
||||
|
||||
req.onload = function () {
|
||||
if ( _this.context.decodeAudioData ) {
|
||||
_this.context.decodeAudioData( req.response, function( buffer ) {
|
||||
_this.buffer = buffer;
|
||||
connectContext.call( _this );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}, function( e ) {
|
||||
console.log( e );
|
||||
});
|
||||
} else {
|
||||
_this.buffer = _this.context.createBuffer( req.response, false );
|
||||
connectContext.call( _this );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}
|
||||
};
|
||||
req.send();
|
||||
|
||||
this.proc = this.context.createJavaScriptNode( SAMPLE_SIZE / 2, 1, 1 );
|
||||
this.proc.onaudioprocess = function ( e ) {
|
||||
_this.update.call( _this, e );
|
||||
};
|
||||
this.proc.connect( this.context.destination );
|
||||
|
||||
this.fft = new FFT( SAMPLE_SIZE / 2, SAMPLE_RATE );
|
||||
this.signal = new Float32Array( SAMPLE_SIZE / 2 );
|
||||
},
|
||||
|
||||
play : function () {
|
||||
var _this = this;
|
||||
|
||||
this.isLoaded ? play() : this.dancer.bind( 'loaded', play );
|
||||
|
||||
function play () {
|
||||
if ( _this.isDisconnected ) {
|
||||
connectContext.call( _this );
|
||||
}
|
||||
_this.source.noteOn( 0.0 );
|
||||
_this.startTime = _this.context.currentTime;
|
||||
_this.isPlaying = true;
|
||||
}
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
if ( this.isPlaying ) {
|
||||
this.source.noteOff( 0.0 );
|
||||
this.isDisconnected = true;
|
||||
this.endTime = this.getTime();
|
||||
}
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.isPlaying ?
|
||||
this.context.currentTime - ( this.startTime || 0 ) :
|
||||
this.endTime || 0;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isPlaying ) { return; }
|
||||
|
||||
var
|
||||
buffers = [],
|
||||
channels = e.inputBuffer.numberOfChannels,
|
||||
resolution = SAMPLE_SIZE / channels;
|
||||
|
||||
for ( i = channels; i--; ) {
|
||||
buffers.push( e.inputBuffer.getChannelData( i ) );
|
||||
}
|
||||
|
||||
for ( i = 0; i < resolution; i++ ) {
|
||||
this.signal[ i ] = channels > 1 ?
|
||||
buffers.reduce( bufferReduce ) / channels :
|
||||
buffers[ 0 ][ i ];
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
function bufferReduce ( prev, curr ) {
|
||||
return prev[ i ] + curr[ i ];
|
||||
}
|
||||
|
||||
Dancer.adapters.webkit = adapter;
|
||||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.audio = new Audio();
|
||||
this.isLoaded = this.isPlaying = false;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path ) {
|
||||
var _this = this;
|
||||
this.audio.src = path;
|
||||
this.audio.addEventListener( 'loadedmetadata', function( e ) {
|
||||
_this.fbLength = _this.audio.mozFrameBufferLength;
|
||||
_this.channels = _this.audio.mozChannels;
|
||||
_this.rate = _this.audio.mozSampleRate;
|
||||
_this.fft = new FFT( _this.fbLength / _this.channels, _this.rate );
|
||||
_this.signal = new Float32Array( _this.fbLength / _this.channels );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}, false);
|
||||
this.audio.addEventListener( 'MozAudioAvailable', function( e ) {
|
||||
_this.update( e );
|
||||
}, false);
|
||||
},
|
||||
|
||||
play : function () {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audio.pause();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.currentTime;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isLoaded ) return;
|
||||
|
||||
for ( var i = 0, j = this.fbLength / 2; i < j; i++ ) {
|
||||
this.signal[ i ] = ( e.frameBuffer[ 2 * i ] + e.frameBuffer[ 2 * i + 1 ] ) / 2;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.adapters.moz = adapter;
|
||||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
DEBUG_MODE = false,
|
||||
SAMPLE_SIZE = 1024,
|
||||
SAMPLE_RATE = 44100,
|
||||
smLoaded = false,
|
||||
smLoading = false,
|
||||
CONVERSION_COEFFICIENT = 0.93;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.isLoaded = this.isPlaying = false;
|
||||
this.wave_L = [];
|
||||
this.wave_R = [];
|
||||
this.spectrum = [];
|
||||
|
||||
window.SM2_DEFER = true;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
load : function ( path ) {
|
||||
var _this = this;
|
||||
this.path = path || this.path;
|
||||
|
||||
!window.soundManager && !smLoading && loadSM.call( this );
|
||||
|
||||
if ( window.soundManager ) {
|
||||
this.audio = soundManager.createSound({
|
||||
id : 'dancer' + Math.random() + '',
|
||||
url : this.path,
|
||||
stream : true,
|
||||
autoPlay : false,
|
||||
autoLoad : true,
|
||||
whileplaying : function () {
|
||||
_this.update();
|
||||
},
|
||||
onload : function () {
|
||||
_this.fft = new FFT( SAMPLE_SIZE, SAMPLE_RATE );
|
||||
_this.signal = new Float32Array( SAMPLE_SIZE );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
play : function () {
|
||||
if ( !this.isPlaying && this.isLoaded ) {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
}
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audio.stop();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.position / 1000;
|
||||
},
|
||||
|
||||
update : function () {
|
||||
if ( !this.isLoaded ) return;
|
||||
this.wave_L = this.audio.waveformData.left;
|
||||
this.wave_R = this.audio.waveformData.right;
|
||||
|
||||
for ( var i = 0, j = this.wave_L.length; i < j; i++ ) {
|
||||
this.signal[ 2 * i ] = (( parseFloat(this.wave_L[ i ]) + parseFloat(this.wave_R[ i ])) * CONVERSION_COEFFICIENT );
|
||||
this.signal[ i * 2 + 1 ] = this.signal[ i * 2 ];
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
function loadSM () {
|
||||
var adapter = this;
|
||||
smLoading = true;
|
||||
loadScript( Dancer.options.flashJS, function () {
|
||||
soundManager = new SoundManager();
|
||||
soundManager.flashVersion = 9;
|
||||
soundManager.flash9Options.useWaveformData = true;
|
||||
soundManager.useWaveformData = true;
|
||||
soundManager.useHighPerformance = true;
|
||||
soundManager.useFastPolling = true;
|
||||
soundManager.multiShot = false;
|
||||
soundManager.debugMode = false;
|
||||
soundManager.debugFlash = false;
|
||||
soundManager.url = Dancer.options.flashSWF;
|
||||
soundManager.onready(function () {
|
||||
smLoaded = true;
|
||||
adapter.load();
|
||||
});
|
||||
soundManager.ontimeout(function(){
|
||||
console.error( 'Error loading SoundManager2.swf' );
|
||||
});
|
||||
soundManager.beginDelayedInit();
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript ( url, callback ) {
|
||||
var
|
||||
script = document.createElement( 'script' ),
|
||||
appender = document.getElementsByTagName( 'script' )[0];
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
script.onload = callback;
|
||||
appender.parentNode.insertBefore( script, appender );
|
||||
}
|
||||
|
||||
Dancer.adapters.flash = adapter;
|
||||
|
||||
})();
|
||||
|
||||
/*
|
||||
* DSP.js - a comprehensive digital signal processing library for javascript
|
||||
*
|
||||
* Created by Corban Brook <corbanbrook@gmail.com> on 2010-01-01.
|
||||
* Copyright 2010 Corban Brook. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// Fourier Transform Module used by DFT, FFT, RFFT
|
||||
function FourierTransform(bufferSize, sampleRate) {
|
||||
this.bufferSize = bufferSize;
|
||||
this.sampleRate = sampleRate;
|
||||
this.bandwidth = 2 / bufferSize * sampleRate / 2;
|
||||
|
||||
this.spectrum = new Float32Array(bufferSize/2);
|
||||
this.real = new Float32Array(bufferSize);
|
||||
this.imag = new Float32Array(bufferSize);
|
||||
|
||||
this.peakBand = 0;
|
||||
this.peak = 0;
|
||||
|
||||
/**
|
||||
* Calculates the *middle* frequency of an FFT band.
|
||||
*
|
||||
* @param {Number} index The index of the FFT band.
|
||||
*
|
||||
* @returns The middle frequency in Hz.
|
||||
*/
|
||||
this.getBandFrequency = function(index) {
|
||||
return this.bandwidth * index + this.bandwidth / 2;
|
||||
};
|
||||
|
||||
this.calculateSpectrum = function() {
|
||||
var spectrum = this.spectrum,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
bSi = 2 / this.bufferSize,
|
||||
sqrt = Math.sqrt,
|
||||
rval,
|
||||
ival,
|
||||
mag;
|
||||
|
||||
for (var i = 0, N = bufferSize/2; i < N; i++) {
|
||||
rval = real[i];
|
||||
ival = imag[i];
|
||||
mag = bSi * sqrt(rval * rval + ival * ival);
|
||||
|
||||
if (mag > this.peak) {
|
||||
this.peakBand = i;
|
||||
this.peak = mag;
|
||||
}
|
||||
|
||||
spectrum[i] = mag;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* FFT is a class for calculating the Discrete Fourier Transform of a signal
|
||||
* with the Fast Fourier Transform algorithm.
|
||||
*
|
||||
* @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
|
||||
* @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FFT(bufferSize, sampleRate) {
|
||||
FourierTransform.call(this, bufferSize, sampleRate);
|
||||
|
||||
this.reverseTable = new Uint32Array(bufferSize);
|
||||
|
||||
var limit = 1;
|
||||
var bit = bufferSize >> 1;
|
||||
|
||||
var i;
|
||||
|
||||
while (limit < bufferSize) {
|
||||
for (i = 0; i < limit; i++) {
|
||||
this.reverseTable[i + limit] = this.reverseTable[i] + bit;
|
||||
}
|
||||
|
||||
limit = limit << 1;
|
||||
bit = bit >> 1;
|
||||
}
|
||||
|
||||
this.sinTable = new Float32Array(bufferSize);
|
||||
this.cosTable = new Float32Array(bufferSize);
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
this.sinTable[i] = Math.sin(-Math.PI/i);
|
||||
this.cosTable[i] = Math.cos(-Math.PI/i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a forward transform on the sample buffer.
|
||||
* Converts a time domain signal to frequency domain spectra.
|
||||
*
|
||||
* @param {Array} buffer The sample buffer. Buffer Length must be power of 2
|
||||
*
|
||||
* @returns The frequency spectrum array
|
||||
*/
|
||||
FFT.prototype.forward = function(buffer) {
|
||||
// Locally scope variables for speed up
|
||||
var bufferSize = this.bufferSize,
|
||||
cosTable = this.cosTable,
|
||||
sinTable = this.sinTable,
|
||||
reverseTable = this.reverseTable,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
spectrum = this.spectrum;
|
||||
|
||||
var k = Math.floor(Math.log(bufferSize) / Math.LN2);
|
||||
|
||||
if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
|
||||
if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
|
||||
|
||||
var halfSize = 1,
|
||||
phaseShiftStepReal,
|
||||
phaseShiftStepImag,
|
||||
currentPhaseShiftReal,
|
||||
currentPhaseShiftImag,
|
||||
off,
|
||||
tr,
|
||||
ti,
|
||||
tmpReal,
|
||||
i;
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
real[i] = buffer[reverseTable[i]];
|
||||
imag[i] = 0;
|
||||
}
|
||||
|
||||
while (halfSize < bufferSize) {
|
||||
//phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
|
||||
//phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
|
||||
phaseShiftStepReal = cosTable[halfSize];
|
||||
phaseShiftStepImag = sinTable[halfSize];
|
||||
|
||||
currentPhaseShiftReal = 1;
|
||||
currentPhaseShiftImag = 0;
|
||||
|
||||
for (var fftStep = 0; fftStep < halfSize; fftStep++) {
|
||||
i = fftStep;
|
||||
|
||||
while (i < bufferSize) {
|
||||
off = i + halfSize;
|
||||
tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
|
||||
ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
|
||||
|
||||
real[off] = real[i] - tr;
|
||||
imag[off] = imag[i] - ti;
|
||||
real[i] += tr;
|
||||
imag[i] += ti;
|
||||
|
||||
i += halfSize << 1;
|
||||
}
|
||||
|
||||
tmpReal = currentPhaseShiftReal;
|
||||
currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
|
||||
currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
|
||||
}
|
||||
|
||||
halfSize = halfSize << 1;
|
||||
}
|
||||
|
||||
return this.calculateSpectrum();
|
||||
};
|
||||
|
||||
/*
|
||||
Copyright (c) Copyright (c) 2007, Carl S. Yestrau All rights reserved.
|
||||
Code licensed under the BSD License: http://www.featureblend.com/license.txt
|
||||
Version: 1.0.4
|
||||
*/
|
||||
var FlashDetect = new function(){
|
||||
var self = this;
|
||||
self.installed = false;
|
||||
self.raw = "";
|
||||
self.major = -1;
|
||||
self.minor = -1;
|
||||
self.revision = -1;
|
||||
self.revisionStr = "";
|
||||
var activeXDetectRules = [
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.7",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.6",
|
||||
"version":function(obj){
|
||||
var version = "6,0,21";
|
||||
try{
|
||||
obj.AllowScriptAccess = "always";
|
||||
version = getActiveXVersion(obj);
|
||||
}catch(err){}
|
||||
return version;
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
}
|
||||
];
|
||||
/**
|
||||
* Extract the ActiveX version of the plugin.
|
||||
*
|
||||
* @param {Object} The flash ActiveX object.
|
||||
* @type String
|
||||
*/
|
||||
var getActiveXVersion = function(activeXObj){
|
||||
var version = -1;
|
||||
try{
|
||||
version = activeXObj.GetVariable("$version");
|
||||
}catch(err){}
|
||||
return version;
|
||||
};
|
||||
/**
|
||||
* Try and retrieve an ActiveX object having a specified name.
|
||||
*
|
||||
* @param {String} name The ActiveX object name lookup.
|
||||
* @return One of ActiveX object or a simple object having an attribute of activeXError with a value of true.
|
||||
* @type Object
|
||||
*/
|
||||
var getActiveXObject = function(name){
|
||||
var obj = -1;
|
||||
try{
|
||||
obj = new ActiveXObject(name);
|
||||
}catch(err){
|
||||
obj = {activeXError:true};
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
/**
|
||||
* Parse an ActiveX $version string into an object.
|
||||
*
|
||||
* @param {String} str The ActiveX Object GetVariable($version) return value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseActiveXVersion = function(str){
|
||||
var versionArray = str.split(",");//replace with regex
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(versionArray[0].split(" ")[1], 10),
|
||||
"minor":parseInt(versionArray[1], 10),
|
||||
"revision":parseInt(versionArray[2], 10),
|
||||
"revisionStr":versionArray[2]
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse a standard enabledPlugin.description into an object.
|
||||
*
|
||||
* @param {String} str The enabledPlugin.description value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseStandardVersion = function(str){
|
||||
var descParts = str.split(/ +/);
|
||||
var majorMinor = descParts[2].split(/\./);
|
||||
var revisionStr = descParts[3];
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(majorMinor[0], 10),
|
||||
"minor":parseInt(majorMinor[1], 10),
|
||||
"revisionStr":revisionStr,
|
||||
"revision":parseRevisionStrToInt(revisionStr)
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse the plugin revision string into an integer.
|
||||
*
|
||||
* @param {String} The revision in string format.
|
||||
* @type Number
|
||||
*/
|
||||
var parseRevisionStrToInt = function(str){
|
||||
return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision;
|
||||
};
|
||||
/**
|
||||
* Is the major version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required major version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.majorAtLeast = function(version){
|
||||
return self.major >= version;
|
||||
};
|
||||
/**
|
||||
* Is the minor version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required minor version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.minorAtLeast = function(version){
|
||||
return self.minor >= version;
|
||||
};
|
||||
/**
|
||||
* Is the revision version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.revisionAtLeast = function(version){
|
||||
return self.revision >= version;
|
||||
};
|
||||
/**
|
||||
* Is the version greater than or equal to a specified major, minor and revision.
|
||||
*
|
||||
* @param {Number} major The minimum required major version.
|
||||
* @param {Number} (Optional) minor The minimum required minor version.
|
||||
* @param {Number} (Optional) revision The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.versionAtLeast = function(major){
|
||||
var properties = [self.major, self.minor, self.revision];
|
||||
var len = Math.min(properties.length, arguments.length);
|
||||
for(i=0; i<len; i++){
|
||||
if(properties[i]>=arguments[i]){
|
||||
if(i+1<len && properties[i]==arguments[i]){
|
||||
continue;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Constructor, sets raw, major, minor, revisionStr, revision and installed public properties.
|
||||
*/
|
||||
self.FlashDetect = function(){
|
||||
if(navigator.plugins && navigator.plugins.length>0){
|
||||
var type = 'application/x-shockwave-flash';
|
||||
var mimeTypes = navigator.mimeTypes;
|
||||
if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){
|
||||
var version = mimeTypes[type].enabledPlugin.description;
|
||||
var versionObj = parseStandardVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
self.revision = versionObj.revision;
|
||||
self.installed = true;
|
||||
}
|
||||
}else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){
|
||||
var version = -1;
|
||||
for(var i=0; i<activeXDetectRules.length && version==-1; i++){
|
||||
var obj = getActiveXObject(activeXDetectRules[i].name);
|
||||
if(!obj.activeXError){
|
||||
self.installed = true;
|
||||
version = activeXDetectRules[i].version(obj);
|
||||
if(version!=-1){
|
||||
var versionObj = parseActiveXVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revision = versionObj.revision;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}();
|
||||
};
|
||||
FlashDetect.JS_RELEASE = "1.0.4";
|
||||
+8
File diff suppressed because one or more lines are too long
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* Dancer.js (c) 2012 Jordan Santell
|
||||
* MIT License
|
||||
* http://github.com/jsantell/dancer.js
|
||||
*
|
||||
* v0.2.1
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var Dancer = function ( source, codecs ) {
|
||||
this.audioAdapter = Dancer._getAdapter( this );
|
||||
this.events = {};
|
||||
this.sections = [];
|
||||
|
||||
this.bind( 'update', update );
|
||||
this.source = Dancer._makeSupportedPath( source, codecs );
|
||||
this.audioAdapter.load( this.source );
|
||||
};
|
||||
|
||||
Dancer.adapters = {};
|
||||
|
||||
Dancer.prototype = {
|
||||
|
||||
/* Controls */
|
||||
|
||||
play : function () {
|
||||
this.audioAdapter.play();
|
||||
return this;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audioAdapter.stop();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Actions */
|
||||
|
||||
createBeat : function ( freq, threshold, decay, onBeat, offBeat ) {
|
||||
return new Dancer.Beat( this, freq, threshold, decay, onBeat, offBeat );
|
||||
},
|
||||
|
||||
bind : function ( name, callback ) {
|
||||
if ( !this.events[ name ] ) {
|
||||
this.events[ name ] = [];
|
||||
}
|
||||
this.events[ name ].push( callback );
|
||||
return this;
|
||||
},
|
||||
|
||||
unbind : function ( name ) {
|
||||
if ( this.events[ name ] ) {
|
||||
delete this.events[ name ];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
trigger : function ( name ) {
|
||||
var _this = this;
|
||||
if ( this.events[ name ] ) {
|
||||
this.events[ name ].forEach(function( callback ) {
|
||||
callback.call( _this );
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Getters */
|
||||
|
||||
getTime : function () {
|
||||
return this.audioAdapter.getTime();
|
||||
},
|
||||
|
||||
// Returns the magnitude of a frequency or average over a range of frequencies
|
||||
getFrequency : function ( freq, endFreq ) {
|
||||
var sum = 0;
|
||||
if ( endFreq !== undefined ) {
|
||||
for ( var i = freq; i <= endFreq; i++ ) {
|
||||
sum += this.getSpectrum()[ i ];
|
||||
}
|
||||
return sum / ( endFreq - freq + 1 );
|
||||
} else {
|
||||
return this.getSpectrum()[ freq ];
|
||||
}
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.audioAdapter.getWaveform();
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.audioAdapter.getSpectrum();
|
||||
},
|
||||
|
||||
isLoaded : function () {
|
||||
return this.audioAdapter.isLoaded;
|
||||
},
|
||||
|
||||
isPlaying : function () {
|
||||
return this.audioAdapter.isPlaying;
|
||||
},
|
||||
|
||||
|
||||
/* Sections */
|
||||
|
||||
after : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
before : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() < time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
between : function ( startTime, endTime, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > startTime && _this.getTime() < endTime;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
onceAt : function ( time, callback ) {
|
||||
var
|
||||
_this = this,
|
||||
thisSection = null;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time && !this.called;
|
||||
},
|
||||
callback : function () {
|
||||
callback.call( this );
|
||||
thisSection.called = true;
|
||||
},
|
||||
called : false
|
||||
});
|
||||
// Baking the section in the closure due to callback's this being the dancer instance
|
||||
thisSection = this.sections[ this.sections.length - 1 ];
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
function update () {
|
||||
for ( var i in this.sections ) {
|
||||
if ( this.sections[ i ].condition() )
|
||||
this.sections[ i ].callback.call( this );
|
||||
}
|
||||
}
|
||||
|
||||
window.Dancer = Dancer;
|
||||
})();
|
||||
|
||||
(function ( Dancer ) {
|
||||
|
||||
var CODECS = {
|
||||
'mp3' : 'audio/mpeg;',
|
||||
'ogg' : 'audio/ogg; codecs="vorbis"',
|
||||
'wav' : 'audio/wav; codecs="1"',
|
||||
'aac' : 'audio/mp4; codecs="mp4a.40.2"'
|
||||
},
|
||||
audioEl = document.createElement( 'audio' );
|
||||
|
||||
Dancer.options = {};
|
||||
|
||||
Dancer.setOptions = function ( o ) {
|
||||
for ( var option in o ) {
|
||||
if ( o.hasOwnProperty( option ) ) {
|
||||
Dancer.options[ option ] = o[ option ];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.isSupported = function () {
|
||||
if ( !window.Float32Array || !window.Uint32Array ) {
|
||||
return null;
|
||||
} else if ( window.AudioContext || window.webkitAudioContext ) {
|
||||
return 'webaudio';
|
||||
} else if ( window.Audio && ( new window.Audio() ).mozSetup ) {
|
||||
return 'audiodata';
|
||||
} else if ( FlashDetect.versionAtLeast( 9 ) ) {
|
||||
return 'flash';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.canPlay = function ( type ) {
|
||||
var canPlay = audioEl.canPlayType;
|
||||
return !!(
|
||||
Dancer.isSupported() === 'flash' ?
|
||||
type.toLowerCase() === 'mp3' :
|
||||
audioEl.canPlayType &&
|
||||
audioEl.canPlayType( CODECS[ type.toLowerCase() ] ).replace( /no/, ''));
|
||||
};
|
||||
|
||||
Dancer.addPlugin = function ( name, fn ) {
|
||||
if ( Dancer.prototype[ name ] === undefined ) {
|
||||
Dancer.prototype[ name ] = fn;
|
||||
}
|
||||
};
|
||||
|
||||
Dancer._makeSupportedPath = function ( source, codecs ) {
|
||||
if ( !codecs ) { return source; }
|
||||
|
||||
for ( var i = 0; i < codecs.length; i++ ) {
|
||||
if ( Dancer.canPlay( codecs[ i ] ) ) {
|
||||
return source + '.' + codecs[ i ];
|
||||
}
|
||||
}
|
||||
return source;
|
||||
};
|
||||
|
||||
Dancer._getAdapter = function ( instance ) {
|
||||
switch ( Dancer.isSupported() ) {
|
||||
case 'webaudio':
|
||||
return new Dancer.adapters.webkit( instance );
|
||||
case 'audiodata':
|
||||
return new Dancer.adapters.moz( instance );
|
||||
case 'flash':
|
||||
return new Dancer.adapters.flash( instance );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
})( window.Dancer );
|
||||
|
||||
(function() {
|
||||
var Beat = function ( dancer, options ) {
|
||||
options = options || {};
|
||||
this.dancer = dancer;
|
||||
this.frequency = options.frequency || [ 0, 10 ];
|
||||
this.threshold = options.threshold || 0.3;
|
||||
this.decay = options.decay || 0.02;
|
||||
this.onBeat = options.onBeat;
|
||||
this.offBeat = options.offBeat;
|
||||
this.isOn = false;
|
||||
this.currentThreshold = this.threshold;
|
||||
|
||||
var _this = this;
|
||||
this.dancer.bind( 'update', function () {
|
||||
_this.onUpdate();
|
||||
});
|
||||
};
|
||||
|
||||
Beat.prototype = {
|
||||
on : function () {
|
||||
this.isOn = true;
|
||||
return this;
|
||||
},
|
||||
off : function () {
|
||||
this.isOn = false;
|
||||
return this;
|
||||
},
|
||||
onUpdate : function () {
|
||||
if ( !this.isOn ) { return; }
|
||||
var magnitude = this.maxAmplitude( this.frequency );
|
||||
if ( magnitude >= this.currentThreshold &&
|
||||
magnitude >= this.threshold ) {
|
||||
this.currentThreshold = magnitude;
|
||||
this.onBeat && this.onBeat.call( this.dancer, magnitude );
|
||||
} else {
|
||||
this.offBeat && this.offBeat.call( this.dancer, magnitude );
|
||||
this.currentThreshold -= this.decay;
|
||||
}
|
||||
},
|
||||
maxAmplitude : function ( frequency ) {
|
||||
var
|
||||
max = 0,
|
||||
fft = this.dancer.getSpectrum();
|
||||
|
||||
// Sloppy array check
|
||||
if ( !frequency.length ) {
|
||||
return frequency < fft.length ?
|
||||
fft[ ~~frequency ] :
|
||||
null;
|
||||
}
|
||||
|
||||
for ( var i = frequency[ 0 ], l = frequency[ 1 ]; i <= l; i++ ) {
|
||||
if ( fft[ i ] > max ) { max = fft[ i ]; }
|
||||
}
|
||||
return max;
|
||||
}
|
||||
};
|
||||
|
||||
window.Dancer.Beat = Beat;
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
SAMPLE_SIZE = 2048,
|
||||
SAMPLE_RATE = 44100;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.context = window.AudioContext ?
|
||||
new window.AudioContext() :
|
||||
new window.webkitAudioContext();
|
||||
this.isLoaded = false;
|
||||
this.isPlaying = false;
|
||||
this.isDisconnected = false;
|
||||
};
|
||||
|
||||
function connectContext () {
|
||||
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 );
|
||||
}
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path ) {
|
||||
var
|
||||
req = new XMLHttpRequest(),
|
||||
_this = this;
|
||||
|
||||
req.open( 'GET', path, true );
|
||||
req.responseType = 'arraybuffer';
|
||||
|
||||
req.onload = function () {
|
||||
if ( _this.context.decodeAudioData ) {
|
||||
_this.context.decodeAudioData( req.response, function( buffer ) {
|
||||
_this.buffer = buffer;
|
||||
connectContext.call( _this );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}, function( e ) {
|
||||
console.log( e );
|
||||
});
|
||||
} else {
|
||||
_this.buffer = _this.context.createBuffer( req.response, false );
|
||||
connectContext.call( _this );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}
|
||||
};
|
||||
req.send();
|
||||
|
||||
this.proc = this.context.createJavaScriptNode( SAMPLE_SIZE / 2, 1, 1 );
|
||||
this.proc.onaudioprocess = function ( e ) {
|
||||
_this.update.call( _this, e );
|
||||
};
|
||||
this.proc.connect( this.context.destination );
|
||||
|
||||
this.fft = new FFT( SAMPLE_SIZE / 2, SAMPLE_RATE );
|
||||
this.signal = new Float32Array( SAMPLE_SIZE / 2 );
|
||||
},
|
||||
|
||||
play : function () {
|
||||
var _this = this;
|
||||
|
||||
this.isLoaded ? play() : this.dancer.bind( 'loaded', play );
|
||||
|
||||
function play () {
|
||||
if ( _this.isDisconnected ) {
|
||||
connectContext.call( _this );
|
||||
}
|
||||
_this.source.noteOn( 0.0 );
|
||||
_this.startTime = _this.context.currentTime;
|
||||
_this.isPlaying = true;
|
||||
}
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
if ( this.isPlaying ) {
|
||||
this.source.noteOff( 0.0 );
|
||||
this.isDisconnected = true;
|
||||
this.endTime = this.getTime();
|
||||
}
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.signal;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.isPlaying ?
|
||||
this.context.currentTime - ( this.startTime || 0 ) :
|
||||
this.endTime || 0;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isPlaying ) { return; }
|
||||
|
||||
var
|
||||
buffers = [],
|
||||
channels = e.inputBuffer.numberOfChannels,
|
||||
resolution = SAMPLE_SIZE / channels,
|
||||
i;
|
||||
|
||||
for ( i = channels; i--; ) {
|
||||
buffers.push( e.inputBuffer.getChannelData( i ) );
|
||||
}
|
||||
|
||||
for ( i = 0; i < resolution; i++ ) {
|
||||
this.signal[ i ] = channels > 1 ?
|
||||
buffers.reduce(function ( prev, curr ) {
|
||||
return prev[ i ] + curr[ i ];
|
||||
}) / channels :
|
||||
buffers[ 0 ][ i ];
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.adapters.webkit = adapter;
|
||||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.audio = new Audio();
|
||||
this.isLoaded = this.isPlaying = false;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path ) {
|
||||
var _this = this;
|
||||
this.audio.src = path;
|
||||
this.audio.addEventListener( 'loadedmetadata', function( e ) {
|
||||
_this.fbLength = _this.audio.mozFrameBufferLength;
|
||||
_this.channels = _this.audio.mozChannels;
|
||||
_this.rate = _this.audio.mozSampleRate;
|
||||
_this.fft = new FFT( _this.fbLength / _this.channels, _this.rate );
|
||||
_this.signal = new Float32Array( _this.fbLength / _this.channels );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}, false);
|
||||
this.audio.addEventListener( 'MozAudioAvailable', function( e ) {
|
||||
_this.update( e );
|
||||
}, false);
|
||||
},
|
||||
|
||||
play : function () {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audio.pause();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.signal;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.currentTime;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isLoaded ) return;
|
||||
|
||||
for ( var i = 0, j = this.fbLength / 2; i < j; i++ ) {
|
||||
this.signal[ i ] = ( e.frameBuffer[ 2 * i ] + e.frameBuffer[ 2 * i + 1 ] ) / 2;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.adapters.moz = adapter;
|
||||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
SAMPLE_SIZE = 1024,
|
||||
SAMPLE_RATE = 44100,
|
||||
smLoaded = false,
|
||||
smLoading = false,
|
||||
CONVERSION_COEFFICIENT = 0.93;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.isLoaded = this.isPlaying = false;
|
||||
this.wave_L = [];
|
||||
this.wave_R = [];
|
||||
this.spectrum = [];
|
||||
window.SM2_DEFER = true;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
load : function ( path ) {
|
||||
var _this = this;
|
||||
this.path = path || this.path;
|
||||
|
||||
!window.soundManager && !smLoading && loadSM.call( this );
|
||||
|
||||
if ( window.soundManager ) {
|
||||
this.audio = soundManager.createSound({
|
||||
id : 'dancer' + Math.random() + '',
|
||||
url : this.path,
|
||||
stream : true,
|
||||
autoPlay : false,
|
||||
autoLoad : true,
|
||||
whileplaying : function () {
|
||||
_this.update();
|
||||
},
|
||||
onload : function () {
|
||||
_this.fft = new FFT( SAMPLE_SIZE, SAMPLE_RATE );
|
||||
_this.signal = new Float32Array( SAMPLE_SIZE );
|
||||
_this.waveform = new Float32Array( SAMPLE_SIZE );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
play : function () {
|
||||
if ( !this.isPlaying && this.isLoaded ) {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
}
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audio.stop();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.waveform;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.position / 1000;
|
||||
},
|
||||
|
||||
update : function () {
|
||||
if ( !this.isLoaded ) return;
|
||||
this.wave_L = this.audio.waveformData.left;
|
||||
this.wave_R = this.audio.waveformData.right;
|
||||
var avg;
|
||||
for ( var i = 0, j = this.wave_L.length; i < j; i++ ) {
|
||||
avg = parseFloat(this.wave_L[ i ]) + parseFloat(this.wave_R[ i ]);
|
||||
this.waveform[ 2 * i ] = avg / 2;
|
||||
this.waveform[ i * 2 + 1 ] = avg / 2;
|
||||
this.signal[ 2 * i ] = avg * CONVERSION_COEFFICIENT;
|
||||
this.signal[ i * 2 + 1 ] = avg * CONVERSION_COEFFICIENT;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
function loadSM () {
|
||||
var adapter = this;
|
||||
smLoading = true;
|
||||
loadScript( Dancer.options.flashJS, function () {
|
||||
soundManager = new SoundManager();
|
||||
soundManager.flashVersion = 9;
|
||||
soundManager.flash9Options.useWaveformData = true;
|
||||
soundManager.useWaveformData = true;
|
||||
soundManager.useHighPerformance = true;
|
||||
soundManager.useFastPolling = true;
|
||||
soundManager.multiShot = false;
|
||||
soundManager.debugMode = false;
|
||||
soundManager.debugFlash = false;
|
||||
soundManager.url = Dancer.options.flashSWF;
|
||||
soundManager.onready(function () {
|
||||
smLoaded = true;
|
||||
adapter.load();
|
||||
});
|
||||
soundManager.ontimeout(function(){
|
||||
console.error( 'Error loading SoundManager2.swf' );
|
||||
});
|
||||
soundManager.beginDelayedInit();
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript ( url, callback ) {
|
||||
var
|
||||
script = document.createElement( 'script' ),
|
||||
appender = document.getElementsByTagName( 'script' )[0];
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
script.onload = callback;
|
||||
appender.parentNode.insertBefore( script, appender );
|
||||
}
|
||||
|
||||
Dancer.adapters.flash = adapter;
|
||||
|
||||
})();
|
||||
|
||||
/*
|
||||
* DSP.js - a comprehensive digital signal processing library for javascript
|
||||
*
|
||||
* Created by Corban Brook <corbanbrook@gmail.com> on 2010-01-01.
|
||||
* Copyright 2010 Corban Brook. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// Fourier Transform Module used by DFT, FFT, RFFT
|
||||
function FourierTransform(bufferSize, sampleRate) {
|
||||
this.bufferSize = bufferSize;
|
||||
this.sampleRate = sampleRate;
|
||||
this.bandwidth = 2 / bufferSize * sampleRate / 2;
|
||||
|
||||
this.spectrum = new Float32Array(bufferSize/2);
|
||||
this.real = new Float32Array(bufferSize);
|
||||
this.imag = new Float32Array(bufferSize);
|
||||
|
||||
this.peakBand = 0;
|
||||
this.peak = 0;
|
||||
|
||||
/**
|
||||
* Calculates the *middle* frequency of an FFT band.
|
||||
*
|
||||
* @param {Number} index The index of the FFT band.
|
||||
*
|
||||
* @returns The middle frequency in Hz.
|
||||
*/
|
||||
this.getBandFrequency = function(index) {
|
||||
return this.bandwidth * index + this.bandwidth / 2;
|
||||
};
|
||||
|
||||
this.calculateSpectrum = function() {
|
||||
var spectrum = this.spectrum,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
bSi = 2 / this.bufferSize,
|
||||
sqrt = Math.sqrt,
|
||||
rval,
|
||||
ival,
|
||||
mag;
|
||||
|
||||
for (var i = 0, N = bufferSize/2; i < N; i++) {
|
||||
rval = real[i];
|
||||
ival = imag[i];
|
||||
mag = bSi * sqrt(rval * rval + ival * ival);
|
||||
|
||||
if (mag > this.peak) {
|
||||
this.peakBand = i;
|
||||
this.peak = mag;
|
||||
}
|
||||
|
||||
spectrum[i] = mag;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* FFT is a class for calculating the Discrete Fourier Transform of a signal
|
||||
* with the Fast Fourier Transform algorithm.
|
||||
*
|
||||
* @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
|
||||
* @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FFT(bufferSize, sampleRate) {
|
||||
FourierTransform.call(this, bufferSize, sampleRate);
|
||||
|
||||
this.reverseTable = new Uint32Array(bufferSize);
|
||||
|
||||
var limit = 1;
|
||||
var bit = bufferSize >> 1;
|
||||
|
||||
var i;
|
||||
|
||||
while (limit < bufferSize) {
|
||||
for (i = 0; i < limit; i++) {
|
||||
this.reverseTable[i + limit] = this.reverseTable[i] + bit;
|
||||
}
|
||||
|
||||
limit = limit << 1;
|
||||
bit = bit >> 1;
|
||||
}
|
||||
|
||||
this.sinTable = new Float32Array(bufferSize);
|
||||
this.cosTable = new Float32Array(bufferSize);
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
this.sinTable[i] = Math.sin(-Math.PI/i);
|
||||
this.cosTable[i] = Math.cos(-Math.PI/i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a forward transform on the sample buffer.
|
||||
* Converts a time domain signal to frequency domain spectra.
|
||||
*
|
||||
* @param {Array} buffer The sample buffer. Buffer Length must be power of 2
|
||||
*
|
||||
* @returns The frequency spectrum array
|
||||
*/
|
||||
FFT.prototype.forward = function(buffer) {
|
||||
// Locally scope variables for speed up
|
||||
var bufferSize = this.bufferSize,
|
||||
cosTable = this.cosTable,
|
||||
sinTable = this.sinTable,
|
||||
reverseTable = this.reverseTable,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
spectrum = this.spectrum;
|
||||
|
||||
var k = Math.floor(Math.log(bufferSize) / Math.LN2);
|
||||
|
||||
if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
|
||||
if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
|
||||
|
||||
var halfSize = 1,
|
||||
phaseShiftStepReal,
|
||||
phaseShiftStepImag,
|
||||
currentPhaseShiftReal,
|
||||
currentPhaseShiftImag,
|
||||
off,
|
||||
tr,
|
||||
ti,
|
||||
tmpReal,
|
||||
i;
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
real[i] = buffer[reverseTable[i]];
|
||||
imag[i] = 0;
|
||||
}
|
||||
|
||||
while (halfSize < bufferSize) {
|
||||
//phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
|
||||
//phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
|
||||
phaseShiftStepReal = cosTable[halfSize];
|
||||
phaseShiftStepImag = sinTable[halfSize];
|
||||
|
||||
currentPhaseShiftReal = 1;
|
||||
currentPhaseShiftImag = 0;
|
||||
|
||||
for (var fftStep = 0; fftStep < halfSize; fftStep++) {
|
||||
i = fftStep;
|
||||
|
||||
while (i < bufferSize) {
|
||||
off = i + halfSize;
|
||||
tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
|
||||
ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
|
||||
|
||||
real[off] = real[i] - tr;
|
||||
imag[off] = imag[i] - ti;
|
||||
real[i] += tr;
|
||||
imag[i] += ti;
|
||||
|
||||
i += halfSize << 1;
|
||||
}
|
||||
|
||||
tmpReal = currentPhaseShiftReal;
|
||||
currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
|
||||
currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
|
||||
}
|
||||
|
||||
halfSize = halfSize << 1;
|
||||
}
|
||||
|
||||
return this.calculateSpectrum();
|
||||
};
|
||||
|
||||
/*
|
||||
Copyright (c) Copyright (c) 2007, Carl S. Yestrau All rights reserved.
|
||||
Code licensed under the BSD License: http://www.featureblend.com/license.txt
|
||||
Version: 1.0.4
|
||||
*/
|
||||
var FlashDetect = new function(){
|
||||
var self = this;
|
||||
self.installed = false;
|
||||
self.raw = "";
|
||||
self.major = -1;
|
||||
self.minor = -1;
|
||||
self.revision = -1;
|
||||
self.revisionStr = "";
|
||||
var activeXDetectRules = [
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.7",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.6",
|
||||
"version":function(obj){
|
||||
var version = "6,0,21";
|
||||
try{
|
||||
obj.AllowScriptAccess = "always";
|
||||
version = getActiveXVersion(obj);
|
||||
}catch(err){}
|
||||
return version;
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
}
|
||||
];
|
||||
/**
|
||||
* Extract the ActiveX version of the plugin.
|
||||
*
|
||||
* @param {Object} The flash ActiveX object.
|
||||
* @type String
|
||||
*/
|
||||
var getActiveXVersion = function(activeXObj){
|
||||
var version = -1;
|
||||
try{
|
||||
version = activeXObj.GetVariable("$version");
|
||||
}catch(err){}
|
||||
return version;
|
||||
};
|
||||
/**
|
||||
* Try and retrieve an ActiveX object having a specified name.
|
||||
*
|
||||
* @param {String} name The ActiveX object name lookup.
|
||||
* @return One of ActiveX object or a simple object having an attribute of activeXError with a value of true.
|
||||
* @type Object
|
||||
*/
|
||||
var getActiveXObject = function(name){
|
||||
var obj = -1;
|
||||
try{
|
||||
obj = new ActiveXObject(name);
|
||||
}catch(err){
|
||||
obj = {activeXError:true};
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
/**
|
||||
* Parse an ActiveX $version string into an object.
|
||||
*
|
||||
* @param {String} str The ActiveX Object GetVariable($version) return value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseActiveXVersion = function(str){
|
||||
var versionArray = str.split(",");//replace with regex
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(versionArray[0].split(" ")[1], 10),
|
||||
"minor":parseInt(versionArray[1], 10),
|
||||
"revision":parseInt(versionArray[2], 10),
|
||||
"revisionStr":versionArray[2]
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse a standard enabledPlugin.description into an object.
|
||||
*
|
||||
* @param {String} str The enabledPlugin.description value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseStandardVersion = function(str){
|
||||
var descParts = str.split(/ +/);
|
||||
var majorMinor = descParts[2].split(/\./);
|
||||
var revisionStr = descParts[3];
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(majorMinor[0], 10),
|
||||
"minor":parseInt(majorMinor[1], 10),
|
||||
"revisionStr":revisionStr,
|
||||
"revision":parseRevisionStrToInt(revisionStr)
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse the plugin revision string into an integer.
|
||||
*
|
||||
* @param {String} The revision in string format.
|
||||
* @type Number
|
||||
*/
|
||||
var parseRevisionStrToInt = function(str){
|
||||
return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision;
|
||||
};
|
||||
/**
|
||||
* Is the major version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required major version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.majorAtLeast = function(version){
|
||||
return self.major >= version;
|
||||
};
|
||||
/**
|
||||
* Is the minor version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required minor version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.minorAtLeast = function(version){
|
||||
return self.minor >= version;
|
||||
};
|
||||
/**
|
||||
* Is the revision version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.revisionAtLeast = function(version){
|
||||
return self.revision >= version;
|
||||
};
|
||||
/**
|
||||
* Is the version greater than or equal to a specified major, minor and revision.
|
||||
*
|
||||
* @param {Number} major The minimum required major version.
|
||||
* @param {Number} (Optional) minor The minimum required minor version.
|
||||
* @param {Number} (Optional) revision The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.versionAtLeast = function(major){
|
||||
var properties = [self.major, self.minor, self.revision];
|
||||
var len = Math.min(properties.length, arguments.length);
|
||||
for(i=0; i<len; i++){
|
||||
if(properties[i]>=arguments[i]){
|
||||
if(i+1<len && properties[i]==arguments[i]){
|
||||
continue;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Constructor, sets raw, major, minor, revisionStr, revision and installed public properties.
|
||||
*/
|
||||
self.FlashDetect = function(){
|
||||
if(navigator.plugins && navigator.plugins.length>0){
|
||||
var type = 'application/x-shockwave-flash';
|
||||
var mimeTypes = navigator.mimeTypes;
|
||||
if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){
|
||||
var version = mimeTypes[type].enabledPlugin.description;
|
||||
var versionObj = parseStandardVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
self.revision = versionObj.revision;
|
||||
self.installed = true;
|
||||
}
|
||||
}else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){
|
||||
var version = -1;
|
||||
for(var i=0; i<activeXDetectRules.length && version==-1; i++){
|
||||
var obj = getActiveXObject(activeXDetectRules[i].name);
|
||||
if(!obj.activeXError){
|
||||
self.installed = true;
|
||||
version = activeXDetectRules[i].version(obj);
|
||||
if(version!=-1){
|
||||
var versionObj = parseActiveXVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revision = versionObj.revision;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}();
|
||||
};
|
||||
FlashDetect.JS_RELEASE = "1.0.4";
|
||||
+8
File diff suppressed because one or more lines are too long
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* Dancer.js (c) 2012 Jordan Santell
|
||||
* MIT License
|
||||
* http://github.com/jsantell/dancer.js
|
||||
*
|
||||
* v0.2.1
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var Dancer = function ( source, codecs ) {
|
||||
this.audioAdapter = Dancer._getAdapter( this );
|
||||
this.events = {};
|
||||
this.sections = [];
|
||||
|
||||
this.bind( 'update', update );
|
||||
this.source = Dancer._makeSupportedPath( source, codecs );
|
||||
this.audioAdapter.load( this.source );
|
||||
};
|
||||
|
||||
Dancer.adapters = {};
|
||||
|
||||
Dancer.prototype = {
|
||||
|
||||
/* Controls */
|
||||
|
||||
play : function () {
|
||||
this.audioAdapter.play();
|
||||
return this;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audioAdapter.stop();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Actions */
|
||||
|
||||
createBeat : function ( freq, threshold, decay, onBeat, offBeat ) {
|
||||
return new Dancer.Beat( this, freq, threshold, decay, onBeat, offBeat );
|
||||
},
|
||||
|
||||
bind : function ( name, callback ) {
|
||||
if ( !this.events[ name ] ) {
|
||||
this.events[ name ] = [];
|
||||
}
|
||||
this.events[ name ].push( callback );
|
||||
return this;
|
||||
},
|
||||
|
||||
unbind : function ( name ) {
|
||||
if ( this.events[ name ] ) {
|
||||
delete this.events[ name ];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
trigger : function ( name ) {
|
||||
var _this = this;
|
||||
if ( this.events[ name ] ) {
|
||||
this.events[ name ].forEach(function( callback ) {
|
||||
callback.call( _this );
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* Getters */
|
||||
|
||||
getTime : function () {
|
||||
return this.audioAdapter.getTime();
|
||||
},
|
||||
|
||||
// Returns the magnitude of a frequency or average over a range of frequencies
|
||||
getFrequency : function ( freq, endFreq ) {
|
||||
var sum = 0;
|
||||
if ( endFreq !== undefined ) {
|
||||
for ( var i = freq; i <= endFreq; i++ ) {
|
||||
sum += this.getSpectrum()[ i ];
|
||||
}
|
||||
return sum / ( endFreq - freq + 1 );
|
||||
} else {
|
||||
return this.getSpectrum()[ freq ];
|
||||
}
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.audioAdapter.getWaveform();
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.audioAdapter.getSpectrum();
|
||||
},
|
||||
|
||||
isLoaded : function () {
|
||||
return this.audioAdapter.isLoaded;
|
||||
},
|
||||
|
||||
isPlaying : function () {
|
||||
return this.audioAdapter.isPlaying;
|
||||
},
|
||||
|
||||
|
||||
/* Sections */
|
||||
|
||||
after : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
before : function ( time, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() < time;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
between : function ( startTime, endTime, callback ) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > startTime && _this.getTime() < endTime;
|
||||
},
|
||||
callback : callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
onceAt : function ( time, callback ) {
|
||||
var
|
||||
_this = this,
|
||||
thisSection = null;
|
||||
this.sections.push({
|
||||
condition : function () {
|
||||
return _this.getTime() > time && !this.called;
|
||||
},
|
||||
callback : function () {
|
||||
callback.call( this );
|
||||
thisSection.called = true;
|
||||
},
|
||||
called : false
|
||||
});
|
||||
// Baking the section in the closure due to callback's this being the dancer instance
|
||||
thisSection = this.sections[ this.sections.length - 1 ];
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
function update () {
|
||||
for ( var i in this.sections ) {
|
||||
if ( this.sections[ i ].condition() )
|
||||
this.sections[ i ].callback.call( this );
|
||||
}
|
||||
}
|
||||
|
||||
window.Dancer = Dancer;
|
||||
})();
|
||||
|
||||
(function ( Dancer ) {
|
||||
|
||||
var CODECS = {
|
||||
'mp3' : 'audio/mpeg;',
|
||||
'ogg' : 'audio/ogg; codecs="vorbis"',
|
||||
'wav' : 'audio/wav; codecs="1"',
|
||||
'aac' : 'audio/mp4; codecs="mp4a.40.2"'
|
||||
},
|
||||
audioEl = document.createElement( 'audio' );
|
||||
|
||||
Dancer.options = {};
|
||||
|
||||
Dancer.setOptions = function ( o ) {
|
||||
for ( var option in o ) {
|
||||
if ( o.hasOwnProperty( option ) ) {
|
||||
Dancer.options[ option ] = o[ option ];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.isSupported = function () {
|
||||
if ( !window.Float32Array || !window.Uint32Array ) {
|
||||
return null;
|
||||
} else if ( window.AudioContext || window.webkitAudioContext ) {
|
||||
return 'webaudio';
|
||||
} else if ( window.Audio && ( new window.Audio() ).mozSetup ) {
|
||||
return 'audiodata';
|
||||
} else if ( FlashDetect.versionAtLeast( 9 ) ) {
|
||||
return 'flash';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.canPlay = function ( type ) {
|
||||
var canPlay = audioEl.canPlayType;
|
||||
return !!(
|
||||
Dancer.isSupported() === 'flash' ?
|
||||
type.toLowerCase() === 'mp3' :
|
||||
audioEl.canPlayType &&
|
||||
audioEl.canPlayType( CODECS[ type.toLowerCase() ] ).replace( /no/, ''));
|
||||
};
|
||||
|
||||
Dancer.addPlugin = function ( name, fn ) {
|
||||
if ( Dancer.prototype[ name ] === undefined ) {
|
||||
Dancer.prototype[ name ] = fn;
|
||||
}
|
||||
};
|
||||
|
||||
Dancer._makeSupportedPath = function ( source, codecs ) {
|
||||
if ( !codecs ) { return source; }
|
||||
|
||||
for ( var i = 0; i < codecs.length; i++ ) {
|
||||
if ( Dancer.canPlay( codecs[ i ] ) ) {
|
||||
return source + '.' + codecs[ i ];
|
||||
}
|
||||
}
|
||||
return source;
|
||||
};
|
||||
|
||||
Dancer._getAdapter = function ( instance ) {
|
||||
switch ( Dancer.isSupported() ) {
|
||||
case 'webaudio':
|
||||
return new Dancer.adapters.webkit( instance );
|
||||
case 'audiodata':
|
||||
return new Dancer.adapters.moz( instance );
|
||||
case 'flash':
|
||||
return new Dancer.adapters.flash( instance );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
})( window.Dancer );
|
||||
|
||||
(function() {
|
||||
var Beat = function ( dancer, options ) {
|
||||
options = options || {};
|
||||
this.dancer = dancer;
|
||||
this.frequency = options.frequency || [ 0, 10 ];
|
||||
this.threshold = options.threshold || 0.3;
|
||||
this.decay = options.decay || 0.02;
|
||||
this.onBeat = options.onBeat;
|
||||
this.offBeat = options.offBeat;
|
||||
this.isOn = false;
|
||||
this.currentThreshold = this.threshold;
|
||||
|
||||
var _this = this;
|
||||
this.dancer.bind( 'update', function () {
|
||||
_this.onUpdate();
|
||||
});
|
||||
};
|
||||
|
||||
Beat.prototype = {
|
||||
on : function () {
|
||||
this.isOn = true;
|
||||
return this;
|
||||
},
|
||||
off : function () {
|
||||
this.isOn = false;
|
||||
return this;
|
||||
},
|
||||
onUpdate : function () {
|
||||
if ( !this.isOn ) { return; }
|
||||
var magnitude = this.maxAmplitude( this.frequency );
|
||||
if ( magnitude >= this.currentThreshold &&
|
||||
magnitude >= this.threshold ) {
|
||||
this.currentThreshold = magnitude;
|
||||
this.onBeat && this.onBeat.call( this.dancer, magnitude );
|
||||
} else {
|
||||
this.offBeat && this.offBeat.call( this.dancer, magnitude );
|
||||
this.currentThreshold -= this.decay;
|
||||
}
|
||||
},
|
||||
maxAmplitude : function ( frequency ) {
|
||||
var
|
||||
max = 0,
|
||||
fft = this.dancer.getSpectrum();
|
||||
|
||||
// Sloppy array check
|
||||
if ( !frequency.length ) {
|
||||
return frequency < fft.length ?
|
||||
fft[ ~~frequency ] :
|
||||
null;
|
||||
}
|
||||
|
||||
for ( var i = frequency[ 0 ], l = frequency[ 1 ]; i <= l; i++ ) {
|
||||
if ( fft[ i ] > max ) { max = fft[ i ]; }
|
||||
}
|
||||
return max;
|
||||
}
|
||||
};
|
||||
|
||||
window.Dancer.Beat = Beat;
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
SAMPLE_SIZE = 2048,
|
||||
SAMPLE_RATE = 44100;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.context = window.AudioContext ?
|
||||
new window.AudioContext() :
|
||||
new window.webkitAudioContext();
|
||||
this.isLoaded = false;
|
||||
this.isPlaying = false;
|
||||
this.isDisconnected = false;
|
||||
};
|
||||
|
||||
function connectContext () {
|
||||
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 );
|
||||
}
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path ) {
|
||||
var
|
||||
req = new XMLHttpRequest(),
|
||||
_this = this;
|
||||
|
||||
req.open( 'GET', path, true );
|
||||
req.responseType = 'arraybuffer';
|
||||
|
||||
req.onload = function () {
|
||||
if ( _this.context.decodeAudioData ) {
|
||||
_this.context.decodeAudioData( req.response, function( buffer ) {
|
||||
_this.buffer = buffer;
|
||||
connectContext.call( _this );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}, function( e ) {
|
||||
console.log( e );
|
||||
});
|
||||
} else {
|
||||
_this.buffer = _this.context.createBuffer( req.response, false );
|
||||
connectContext.call( _this );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}
|
||||
};
|
||||
req.send();
|
||||
|
||||
this.proc = this.context.createJavaScriptNode( SAMPLE_SIZE / 2, 1, 1 );
|
||||
this.proc.onaudioprocess = function ( e ) {
|
||||
_this.update.call( _this, e );
|
||||
};
|
||||
this.proc.connect( this.context.destination );
|
||||
|
||||
this.fft = new FFT( SAMPLE_SIZE / 2, SAMPLE_RATE );
|
||||
this.signal = new Float32Array( SAMPLE_SIZE / 2 );
|
||||
},
|
||||
|
||||
play : function () {
|
||||
var _this = this;
|
||||
|
||||
this.isLoaded ? play() : this.dancer.bind( 'loaded', play );
|
||||
|
||||
function play () {
|
||||
if ( _this.isDisconnected ) {
|
||||
connectContext.call( _this );
|
||||
}
|
||||
_this.source.noteOn( 0.0 );
|
||||
_this.startTime = _this.context.currentTime;
|
||||
_this.isPlaying = true;
|
||||
}
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
if ( this.isPlaying ) {
|
||||
this.source.noteOff( 0.0 );
|
||||
this.isDisconnected = true;
|
||||
this.endTime = this.getTime();
|
||||
}
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.signal;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.isPlaying ?
|
||||
this.context.currentTime - ( this.startTime || 0 ) :
|
||||
this.endTime || 0;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isPlaying ) { return; }
|
||||
|
||||
var
|
||||
buffers = [],
|
||||
channels = e.inputBuffer.numberOfChannels,
|
||||
resolution = SAMPLE_SIZE / channels,
|
||||
i;
|
||||
|
||||
for ( i = channels; i--; ) {
|
||||
buffers.push( e.inputBuffer.getChannelData( i ) );
|
||||
}
|
||||
|
||||
for ( i = 0; i < resolution; i++ ) {
|
||||
this.signal[ i ] = channels > 1 ?
|
||||
buffers.reduce(function ( prev, curr ) {
|
||||
return prev[ i ] + curr[ i ];
|
||||
}) / channels :
|
||||
buffers[ 0 ][ i ];
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.adapters.webkit = adapter;
|
||||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.audio = new Audio();
|
||||
this.isLoaded = this.isPlaying = false;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load : function ( path ) {
|
||||
var _this = this;
|
||||
this.audio.src = path;
|
||||
this.audio.addEventListener( 'loadedmetadata', function( e ) {
|
||||
_this.fbLength = _this.audio.mozFrameBufferLength;
|
||||
_this.channels = _this.audio.mozChannels;
|
||||
_this.rate = _this.audio.mozSampleRate;
|
||||
_this.fft = new FFT( _this.fbLength / _this.channels, _this.rate );
|
||||
_this.signal = new Float32Array( _this.fbLength / _this.channels );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}, false);
|
||||
this.audio.addEventListener( 'MozAudioAvailable', function( e ) {
|
||||
_this.update( e );
|
||||
}, false);
|
||||
},
|
||||
|
||||
play : function () {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audio.pause();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.signal;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.currentTime;
|
||||
},
|
||||
|
||||
update : function ( e ) {
|
||||
if ( !this.isLoaded ) return;
|
||||
|
||||
for ( var i = 0, j = this.fbLength / 2; i < j; i++ ) {
|
||||
this.signal[ i ] = ( e.frameBuffer[ 2 * i ] + e.frameBuffer[ 2 * i + 1 ] ) / 2;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
Dancer.adapters.moz = adapter;
|
||||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
SAMPLE_SIZE = 1024,
|
||||
SAMPLE_RATE = 44100,
|
||||
smLoaded = false,
|
||||
smLoading = false,
|
||||
CONVERSION_COEFFICIENT = 0.93;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.isLoaded = this.isPlaying = false;
|
||||
this.wave_L = [];
|
||||
this.wave_R = [];
|
||||
this.spectrum = [];
|
||||
window.SM2_DEFER = true;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
load : function ( path ) {
|
||||
var _this = this;
|
||||
this.path = path || this.path;
|
||||
|
||||
!window.soundManager && !smLoading && loadSM.call( this );
|
||||
|
||||
if ( window.soundManager ) {
|
||||
this.audio = soundManager.createSound({
|
||||
id : 'dancer' + Math.random() + '',
|
||||
url : this.path,
|
||||
stream : true,
|
||||
autoPlay : false,
|
||||
autoLoad : true,
|
||||
whileplaying : function () {
|
||||
_this.update();
|
||||
},
|
||||
onload : function () {
|
||||
_this.fft = new FFT( SAMPLE_SIZE, SAMPLE_RATE );
|
||||
_this.signal = new Float32Array( SAMPLE_SIZE );
|
||||
_this.waveform = new Float32Array( SAMPLE_SIZE );
|
||||
_this.isLoaded = true;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
play : function () {
|
||||
if ( !this.isPlaying && this.isLoaded ) {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
}
|
||||
},
|
||||
|
||||
stop : function () {
|
||||
this.audio.stop();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.waveform;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.position / 1000;
|
||||
},
|
||||
|
||||
update : function () {
|
||||
if ( !this.isLoaded ) return;
|
||||
this.wave_L = this.audio.waveformData.left;
|
||||
this.wave_R = this.audio.waveformData.right;
|
||||
var avg;
|
||||
for ( var i = 0, j = this.wave_L.length; i < j; i++ ) {
|
||||
avg = parseFloat(this.wave_L[ i ]) + parseFloat(this.wave_R[ i ]);
|
||||
this.waveform[ 2 * i ] = avg / 2;
|
||||
this.waveform[ i * 2 + 1 ] = avg / 2;
|
||||
this.signal[ 2 * i ] = avg * CONVERSION_COEFFICIENT;
|
||||
this.signal[ i * 2 + 1 ] = avg * CONVERSION_COEFFICIENT;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
function loadSM () {
|
||||
var adapter = this;
|
||||
smLoading = true;
|
||||
loadScript( Dancer.options.flashJS, function () {
|
||||
soundManager = new SoundManager();
|
||||
soundManager.flashVersion = 9;
|
||||
soundManager.flash9Options.useWaveformData = true;
|
||||
soundManager.useWaveformData = true;
|
||||
soundManager.useHighPerformance = true;
|
||||
soundManager.useFastPolling = true;
|
||||
soundManager.multiShot = false;
|
||||
soundManager.debugMode = false;
|
||||
soundManager.debugFlash = false;
|
||||
soundManager.url = Dancer.options.flashSWF;
|
||||
soundManager.onready(function () {
|
||||
smLoaded = true;
|
||||
adapter.load();
|
||||
});
|
||||
soundManager.ontimeout(function(){
|
||||
console.error( 'Error loading SoundManager2.swf' );
|
||||
});
|
||||
soundManager.beginDelayedInit();
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript ( url, callback ) {
|
||||
var
|
||||
script = document.createElement( 'script' ),
|
||||
appender = document.getElementsByTagName( 'script' )[0];
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
script.onload = callback;
|
||||
appender.parentNode.insertBefore( script, appender );
|
||||
}
|
||||
|
||||
Dancer.adapters.flash = adapter;
|
||||
|
||||
})();
|
||||
|
||||
/*
|
||||
* DSP.js - a comprehensive digital signal processing library for javascript
|
||||
*
|
||||
* Created by Corban Brook <corbanbrook@gmail.com> on 2010-01-01.
|
||||
* Copyright 2010 Corban Brook. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// Fourier Transform Module used by DFT, FFT, RFFT
|
||||
function FourierTransform(bufferSize, sampleRate) {
|
||||
this.bufferSize = bufferSize;
|
||||
this.sampleRate = sampleRate;
|
||||
this.bandwidth = 2 / bufferSize * sampleRate / 2;
|
||||
|
||||
this.spectrum = new Float32Array(bufferSize/2);
|
||||
this.real = new Float32Array(bufferSize);
|
||||
this.imag = new Float32Array(bufferSize);
|
||||
|
||||
this.peakBand = 0;
|
||||
this.peak = 0;
|
||||
|
||||
/**
|
||||
* Calculates the *middle* frequency of an FFT band.
|
||||
*
|
||||
* @param {Number} index The index of the FFT band.
|
||||
*
|
||||
* @returns The middle frequency in Hz.
|
||||
*/
|
||||
this.getBandFrequency = function(index) {
|
||||
return this.bandwidth * index + this.bandwidth / 2;
|
||||
};
|
||||
|
||||
this.calculateSpectrum = function() {
|
||||
var spectrum = this.spectrum,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
bSi = 2 / this.bufferSize,
|
||||
sqrt = Math.sqrt,
|
||||
rval,
|
||||
ival,
|
||||
mag;
|
||||
|
||||
for (var i = 0, N = bufferSize/2; i < N; i++) {
|
||||
rval = real[i];
|
||||
ival = imag[i];
|
||||
mag = bSi * sqrt(rval * rval + ival * ival);
|
||||
|
||||
if (mag > this.peak) {
|
||||
this.peakBand = i;
|
||||
this.peak = mag;
|
||||
}
|
||||
|
||||
spectrum[i] = mag;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* FFT is a class for calculating the Discrete Fourier Transform of a signal
|
||||
* with the Fast Fourier Transform algorithm.
|
||||
*
|
||||
* @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
|
||||
* @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FFT(bufferSize, sampleRate) {
|
||||
FourierTransform.call(this, bufferSize, sampleRate);
|
||||
|
||||
this.reverseTable = new Uint32Array(bufferSize);
|
||||
|
||||
var limit = 1;
|
||||
var bit = bufferSize >> 1;
|
||||
|
||||
var i;
|
||||
|
||||
while (limit < bufferSize) {
|
||||
for (i = 0; i < limit; i++) {
|
||||
this.reverseTable[i + limit] = this.reverseTable[i] + bit;
|
||||
}
|
||||
|
||||
limit = limit << 1;
|
||||
bit = bit >> 1;
|
||||
}
|
||||
|
||||
this.sinTable = new Float32Array(bufferSize);
|
||||
this.cosTable = new Float32Array(bufferSize);
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
this.sinTable[i] = Math.sin(-Math.PI/i);
|
||||
this.cosTable[i] = Math.cos(-Math.PI/i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a forward transform on the sample buffer.
|
||||
* Converts a time domain signal to frequency domain spectra.
|
||||
*
|
||||
* @param {Array} buffer The sample buffer. Buffer Length must be power of 2
|
||||
*
|
||||
* @returns The frequency spectrum array
|
||||
*/
|
||||
FFT.prototype.forward = function(buffer) {
|
||||
// Locally scope variables for speed up
|
||||
var bufferSize = this.bufferSize,
|
||||
cosTable = this.cosTable,
|
||||
sinTable = this.sinTable,
|
||||
reverseTable = this.reverseTable,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
spectrum = this.spectrum;
|
||||
|
||||
var k = Math.floor(Math.log(bufferSize) / Math.LN2);
|
||||
|
||||
if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
|
||||
if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
|
||||
|
||||
var halfSize = 1,
|
||||
phaseShiftStepReal,
|
||||
phaseShiftStepImag,
|
||||
currentPhaseShiftReal,
|
||||
currentPhaseShiftImag,
|
||||
off,
|
||||
tr,
|
||||
ti,
|
||||
tmpReal,
|
||||
i;
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
real[i] = buffer[reverseTable[i]];
|
||||
imag[i] = 0;
|
||||
}
|
||||
|
||||
while (halfSize < bufferSize) {
|
||||
//phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
|
||||
//phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
|
||||
phaseShiftStepReal = cosTable[halfSize];
|
||||
phaseShiftStepImag = sinTable[halfSize];
|
||||
|
||||
currentPhaseShiftReal = 1;
|
||||
currentPhaseShiftImag = 0;
|
||||
|
||||
for (var fftStep = 0; fftStep < halfSize; fftStep++) {
|
||||
i = fftStep;
|
||||
|
||||
while (i < bufferSize) {
|
||||
off = i + halfSize;
|
||||
tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
|
||||
ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
|
||||
|
||||
real[off] = real[i] - tr;
|
||||
imag[off] = imag[i] - ti;
|
||||
real[i] += tr;
|
||||
imag[i] += ti;
|
||||
|
||||
i += halfSize << 1;
|
||||
}
|
||||
|
||||
tmpReal = currentPhaseShiftReal;
|
||||
currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
|
||||
currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
|
||||
}
|
||||
|
||||
halfSize = halfSize << 1;
|
||||
}
|
||||
|
||||
return this.calculateSpectrum();
|
||||
};
|
||||
|
||||
/*
|
||||
Copyright (c) Copyright (c) 2007, Carl S. Yestrau All rights reserved.
|
||||
Code licensed under the BSD License: http://www.featureblend.com/license.txt
|
||||
Version: 1.0.4
|
||||
*/
|
||||
var FlashDetect = new function(){
|
||||
var self = this;
|
||||
self.installed = false;
|
||||
self.raw = "";
|
||||
self.major = -1;
|
||||
self.minor = -1;
|
||||
self.revision = -1;
|
||||
self.revisionStr = "";
|
||||
var activeXDetectRules = [
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.7",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.6",
|
||||
"version":function(obj){
|
||||
var version = "6,0,21";
|
||||
try{
|
||||
obj.AllowScriptAccess = "always";
|
||||
version = getActiveXVersion(obj);
|
||||
}catch(err){}
|
||||
return version;
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
}
|
||||
];
|
||||
/**
|
||||
* Extract the ActiveX version of the plugin.
|
||||
*
|
||||
* @param {Object} The flash ActiveX object.
|
||||
* @type String
|
||||
*/
|
||||
var getActiveXVersion = function(activeXObj){
|
||||
var version = -1;
|
||||
try{
|
||||
version = activeXObj.GetVariable("$version");
|
||||
}catch(err){}
|
||||
return version;
|
||||
};
|
||||
/**
|
||||
* Try and retrieve an ActiveX object having a specified name.
|
||||
*
|
||||
* @param {String} name The ActiveX object name lookup.
|
||||
* @return One of ActiveX object or a simple object having an attribute of activeXError with a value of true.
|
||||
* @type Object
|
||||
*/
|
||||
var getActiveXObject = function(name){
|
||||
var obj = -1;
|
||||
try{
|
||||
obj = new ActiveXObject(name);
|
||||
}catch(err){
|
||||
obj = {activeXError:true};
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
/**
|
||||
* Parse an ActiveX $version string into an object.
|
||||
*
|
||||
* @param {String} str The ActiveX Object GetVariable($version) return value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseActiveXVersion = function(str){
|
||||
var versionArray = str.split(",");//replace with regex
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(versionArray[0].split(" ")[1], 10),
|
||||
"minor":parseInt(versionArray[1], 10),
|
||||
"revision":parseInt(versionArray[2], 10),
|
||||
"revisionStr":versionArray[2]
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse a standard enabledPlugin.description into an object.
|
||||
*
|
||||
* @param {String} str The enabledPlugin.description value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseStandardVersion = function(str){
|
||||
var descParts = str.split(/ +/);
|
||||
var majorMinor = descParts[2].split(/\./);
|
||||
var revisionStr = descParts[3];
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(majorMinor[0], 10),
|
||||
"minor":parseInt(majorMinor[1], 10),
|
||||
"revisionStr":revisionStr,
|
||||
"revision":parseRevisionStrToInt(revisionStr)
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse the plugin revision string into an integer.
|
||||
*
|
||||
* @param {String} The revision in string format.
|
||||
* @type Number
|
||||
*/
|
||||
var parseRevisionStrToInt = function(str){
|
||||
return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision;
|
||||
};
|
||||
/**
|
||||
* Is the major version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required major version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.majorAtLeast = function(version){
|
||||
return self.major >= version;
|
||||
};
|
||||
/**
|
||||
* Is the minor version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required minor version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.minorAtLeast = function(version){
|
||||
return self.minor >= version;
|
||||
};
|
||||
/**
|
||||
* Is the revision version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.revisionAtLeast = function(version){
|
||||
return self.revision >= version;
|
||||
};
|
||||
/**
|
||||
* Is the version greater than or equal to a specified major, minor and revision.
|
||||
*
|
||||
* @param {Number} major The minimum required major version.
|
||||
* @param {Number} (Optional) minor The minimum required minor version.
|
||||
* @param {Number} (Optional) revision The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.versionAtLeast = function(major){
|
||||
var properties = [self.major, self.minor, self.revision];
|
||||
var len = Math.min(properties.length, arguments.length);
|
||||
for(i=0; i<len; i++){
|
||||
if(properties[i]>=arguments[i]){
|
||||
if(i+1<len && properties[i]==arguments[i]){
|
||||
continue;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Constructor, sets raw, major, minor, revisionStr, revision and installed public properties.
|
||||
*/
|
||||
self.FlashDetect = function(){
|
||||
if(navigator.plugins && navigator.plugins.length>0){
|
||||
var type = 'application/x-shockwave-flash';
|
||||
var mimeTypes = navigator.mimeTypes;
|
||||
if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){
|
||||
var version = mimeTypes[type].enabledPlugin.description;
|
||||
var versionObj = parseStandardVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
self.revision = versionObj.revision;
|
||||
self.installed = true;
|
||||
}
|
||||
}else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){
|
||||
var version = -1;
|
||||
for(var i=0; i<activeXDetectRules.length && version==-1; i++){
|
||||
var obj = getActiveXObject(activeXDetectRules[i].name);
|
||||
if(!obj.activeXError){
|
||||
self.installed = true;
|
||||
version = activeXDetectRules[i].version(obj);
|
||||
if(version!=-1){
|
||||
var versionObj = parseActiveXVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revision = versionObj.revision;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}();
|
||||
};
|
||||
FlashDetect.JS_RELEASE = "1.0.4";
|
||||
+8
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
+8
File diff suppressed because one or more lines are too long
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "dancer.js",
|
||||
"filename": "dancer.min.js",
|
||||
"version": "0.3.1",
|
||||
"description": "high-level audio API, designed to make sweet visualizations",
|
||||
"homepage": "http://jsantell.github.com/dancer.js",
|
||||
"keywords": [
|
||||
"audio"
|
||||
],
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Jordan Santell",
|
||||
"email": "jsantell@gmail.com"
|
||||
}
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/jsantell/dancer.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user