Skip to content

Commit 9a43615

Browse files
author
laino
committed
Add HTML5 waveform parsing
1 parent 519e65f commit 9a43615

File tree

1 file changed

+198
-17
lines changed

1 file changed

+198
-17
lines changed

script/soundmanager2.js

+198-17
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,22 @@ function SoundManager(smURL, smID) {
14541454

14551455
var s = this, resetProperties, add_html5_events, remove_html5_events, stop_html5_timer, start_html5_timer, attachOnPosition, onplay_called = false, onPositionItems = [], onPositionFired = 0, detachOnPosition, applyFromTo, lastURL = null, lastHTML5State, urlOmitted;
14561456

1457+
//HTML5 audio sampling properties
1458+
this._useAdvancedHTML5 = false;
1459+
this._useMoz = false;
1460+
this._fftLeft;
1461+
this._fftRight;
1462+
this._fftRightO; //For when we set right = left but want to preserve the original
1463+
this._waveformLeft;
1464+
this._waveformRight;
1465+
this._audioContext;
1466+
this._processingNode;
1467+
this._sourceNode;
1468+
this._fbLength;
1469+
this._sample_size;
1470+
this._sample_rate;
1471+
1472+
14571473
lastHTML5State = {
14581474
// tracks duration + position (time)
14591475
duration: null,
@@ -1726,6 +1742,10 @@ function SoundManager(smURL, smID) {
17261742
} else {
17271743

17281744
stop_html5_timer();
1745+
1746+
if(s._useAdvancedHTML5 && !s._useMoz){
1747+
this._destroy_WebAudio_Waveform_Parser();
1748+
}
17291749

17301750
if (s._a) {
17311751
s._a.pause();
@@ -2767,6 +2787,87 @@ function SoundManager(smURL, smID) {
27672787

27682788
resetProperties();
27692789

2790+
var audioProcessEvent = function ( e ) {
2791+
if(s.paused) return;
2792+
//When we're processing some data through the HTML WebAudio API
2793+
var buffers = [];
2794+
var channels, resolution;
2795+
channels = s._channels = e.inputBuffer.numberOfChannels;
2796+
2797+
s._waveformLeft = e.inputBuffer.getChannelData(0);
2798+
if(s.instanceOptions.useEQData){
2799+
s._fftLeft.forward(s._waveformLeft);
2800+
}
2801+
2802+
if(channels > 1){
2803+
s._waveformRight = e.inputBuffer.getChannelData(1);
2804+
if(s.instanceOptions.useEQData){
2805+
s._fftRight = s._fftRightO;
2806+
s._fftRight.forward(s._waveformRight);
2807+
}
2808+
} else {
2809+
s._waveformRight = s._waveformLeft;
2810+
s._fftRight = s._fftLeft;
2811+
}
2812+
2813+
s._onTimer(true);
2814+
};
2815+
2816+
this._create_WebAudio_Waveform_Parser = function(){
2817+
//Initialisation for Google Chrome/Web Audio compatible browsers
2818+
2819+
s._sample_rate = 44100;
2820+
s._sample_size = 2048;
2821+
if(s.instanceOptions.useWaveformData || s.instanceOptions.useEQData || s.instanceOptions.usePeakData){
2822+
var context = s._audioContext;
2823+
2824+
var source = s._sourceNode = context.createMediaElementSource( s._a );
2825+
2826+
var proc = s._processingNode = context.createJavaScriptNode( s._sample_size / 2, 1, 1 );
2827+
2828+
source.connect( proc );
2829+
2830+
proc.connect( context.destination );
2831+
2832+
source.connect( context.destination );
2833+
2834+
proc.onaudioprocess = audioProcessEvent;
2835+
2836+
s._fftLeft = new FFT( s._sample_size / 2, s._sample_rate );
2837+
s._fftRight = s._fftRightO = new FFT( s._sample_size / 2, s._sample_rate );
2838+
}
2839+
2840+
};
2841+
2842+
this._destroy_WebAudio_Waveform_Parser = function(){
2843+
if(s._sourceNode)
2844+
s._sourceNode.disconnect(0);
2845+
2846+
if(s._processingNode)
2847+
s._processingNode.disconnect(0);
2848+
};
2849+
2850+
this._create_Mozilla_Waveform_Parser = function(){
2851+
//Initialisation for Mozilla Firefox
2852+
2853+
s._fbLength = s._a.mozFrameBufferLength;
2854+
s._channels = s._a.mozChannels;
2855+
s._sample_rate = s._a.mozSampleRate;
2856+
2857+
if(s.instanceOptions.useWaveformData || s.instanceOptions.useEQData || s.instanceOptions.usePeakData){
2858+
s._waveformLeft = new Float32Array( s._fbLength / s._channels );
2859+
s._waveformRight = new Float32Array( s._fbLength / s._channels );
2860+
}
2861+
2862+
if(s.instanceOptions.useEQData || s.instanceOptions.usePeakData){
2863+
s._fftLeft = new FFT( s._fbLength / s._channels, s._sample_rate );
2864+
s._fftRight = s._fftLeft;
2865+
if(s._channels > 1){
2866+
s._fftRight = new FFT( s._fbLength / s._channels, s._sample_rate );
2867+
}
2868+
}
2869+
};
2870+
27702871
/**
27712872
* Pseudo-private SMSound internals
27722873
* --------------------------------
@@ -2781,6 +2882,10 @@ function SoundManager(smURL, smID) {
27812882
*/
27822883

27832884
var duration, isNew = false, time, x = {};
2885+
var peakData = x;
2886+
var waveformLeft = x;
2887+
var waveformRight = x;
2888+
var eqData = x;
27842889

27852890
if (s._hasTimer || bForce) {
27862891

@@ -2812,7 +2917,18 @@ function SoundManager(smURL, smID) {
28122917

28132918
if (isNew || bForce) {
28142919

2815-
s._whileplaying(time,x,x,x,x);
2920+
if(s._useAdvancedHTML5){
2921+
if(s.instanceOptions.useWaveformData){
2922+
waveformLeft = s._waveformLeft;
2923+
waveformRight = s._waveformRight;
2924+
}
2925+
if(s.instanceOptions.useEQData){
2926+
eqData = {leftEQ: s._fftLeft.spectrum,
2927+
rightEQ: s._fftRight.spectrum};
2928+
}
2929+
}
2930+
2931+
s._whileplaying(time, peakData, waveformLeft, waveformRight, eqData);
28162932

28172933
}
28182934

@@ -2946,7 +3062,7 @@ function SoundManager(smURL, smID) {
29463062
a = s._a;
29473063

29483064
a._called_load = false;
2949-
3065+
29503066
if (useGlobalHTML5Audio) {
29513067

29523068
globalHTML5Audio = a;
@@ -2956,6 +3072,21 @@ function SoundManager(smURL, smID) {
29563072
}
29573073

29583074
s.isHTML5 = true;
3075+
3076+
if(FFT && Float32Array){
3077+
//Use html5 for spectrum/waveform (dsp.js must be available)
3078+
if(window.AudioProcessingEvent && (window.AudioContext || window.webkitAudioContext)){
3079+
//Webkit and WebAudio API
3080+
s._useAdvancedHTML5 = true;
3081+
s._audioContext = new (window.AudioContext || window.webkitAudioContext)();
3082+
sm2._wD(s.id + ': Using HTML5 Audio for eqData and waveform');
3083+
} else if(a.mozSetup) {
3084+
//Mozilla Firefox
3085+
sm2._wD(s.id + ': Using Mozilla Audio for eqData and waveform');
3086+
s._useAdvancedHTML5 = true;
3087+
s._useMoz = true;
3088+
}
3089+
}
29593090

29603091
// store a ref on the track
29613092
s._a = a;
@@ -3212,7 +3343,7 @@ function SoundManager(smURL, smID) {
32123343
this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) {
32133344

32143345
var instanceOptions = s._iO,
3215-
eqLeft;
3346+
eqLeft, eqRight;
32163347

32173348
if (isNaN(nPosition) || nPosition === null) {
32183349
// flash safety net
@@ -3224,7 +3355,7 @@ function SoundManager(smURL, smID) {
32243355

32253356
s._processOnPosition();
32263357

3227-
if (!s.isHTML5 && fV > 8) {
3358+
if (!s.isHTML5 && fV > 8 || s._useAdvancedHTML5) {
32283359

32293360
if (instanceOptions.usePeakData && oPeakData !== _undefined && oPeakData) {
32303361
s.peakData = {
@@ -3234,21 +3365,41 @@ function SoundManager(smURL, smID) {
32343365
}
32353366

32363367
if (instanceOptions.useWaveformData && oWaveformDataLeft !== _undefined && oWaveformDataLeft) {
3237-
s.waveformData = {
3238-
left: oWaveformDataLeft.split(','),
3239-
right: oWaveformDataRight.split(',')
3240-
};
3368+
if(typeof(oWaveformDataLeft) == 'string'){
3369+
s.waveformData = {
3370+
left: oWaveformDataLeft.split(','),
3371+
right: oWaveformDataRight.split(',')
3372+
};
3373+
} else {
3374+
s.waveformData = {
3375+
left: oWaveformDataLeft,
3376+
right: oWaveformDataRight
3377+
};
3378+
}
32413379
}
32423380

32433381
if (instanceOptions.useEQData) {
3382+
32443383
if (oEQData !== _undefined && oEQData && oEQData.leftEQ) {
3245-
eqLeft = oEQData.leftEQ.split(',');
3246-
s.eqData = eqLeft;
3247-
s.eqData.left = eqLeft;
3248-
if (oEQData.rightEQ !== _undefined && oEQData.rightEQ) {
3249-
s.eqData.right = oEQData.rightEQ.split(',');
3384+
if(typeof(oEQData.leftEQ) == 'string'){
3385+
eqLeft = oEQData.leftEQ.split(',');
3386+
} else {
3387+
eqLeft = oEQData.leftEQ;
3388+
eqRight = eqLeft;
32503389
}
32513390
}
3391+
3392+
if (oEQData.rightEQ !== _undefined && oEQData.rightEQ) {
3393+
if(typeof(oEQData.rightEQ) == 'string'){
3394+
eqRight = oEQData.rightEQ.split(',');
3395+
} else {
3396+
eqRight = oEQData.rightEQ;
3397+
}
3398+
}
3399+
3400+
s.eqData = {};
3401+
s.eqData.left = eqLeft;
3402+
s.eqData.right= eqRight;
32523403
}
32533404

32543405
}
@@ -3687,10 +3838,9 @@ function SoundManager(smURL, smID) {
36873838
// wrap html5 event handlers so we don't call them on destroyed and/or unloaded sounds
36883839

36893840
return function(e) {
3690-
36913841
var s = this._s,
36923842
result;
3693-
3843+
36943844
if (!s || !s._a) {
36953845
// <d>
36963846
if (s && s.id) {
@@ -3722,7 +3872,7 @@ function SoundManager(smURL, smID) {
37223872

37233873
// enough has loaded to play
37243874

3725-
canplay: html5_event(function() {
3875+
canplay: html5_event(function(e) {
37263876

37273877
var s = this._s,
37283878
position1K;
@@ -3754,6 +3904,14 @@ function SoundManager(smURL, smID) {
37543904
s._iO._oncanplay();
37553905
}
37563906

3907+
if(s._useAdvancedHTML5){
3908+
if(s._useMoz){
3909+
s._create_Mozilla_Waveform_Parser();
3910+
} else {
3911+
s._create_WebAudio_Waveform_Parser();
3912+
}
3913+
}
3914+
37573915
}),
37583916

37593917
canplaythrough: html5_event(function() {
@@ -3938,6 +4096,8 @@ function SoundManager(smURL, smID) {
39384096

39394097
timeupdate: html5_event(function() {
39404098

4099+
var s = this._s;
4100+
if(s._useAdvancedHTML5) return;
39414101
this._s._onTimer();
39424102

39434103
}),
@@ -3952,6 +4112,27 @@ function SoundManager(smURL, smID) {
39524112
// playback faster than download rate, etc.
39534113
s._onbufferchange(1);
39544114

4115+
}),
4116+
4117+
// only for firefox
4118+
MozAudioAvailable: html5_event(function(e) {
4119+
var s = this._s;
4120+
if(!s._useAdvancedHTML5 || !s._useMoz) return;
4121+
if(s._channels < 2){
4122+
s._waveformLeft = e.frameBuffer;
4123+
s._waveformRight = e.frameBuffer;
4124+
} else {
4125+
var per_channel = s._fbLength / s._channels;
4126+
for ( var i = 0; i < per_channel; i++ ) {
4127+
s._waveformLeft[i] = e.frameBuffer[i * s._channels];
4128+
s._waveformRight[i] = e.frameBuffer[i * s._channels + 1];
4129+
}
4130+
}
4131+
s._fftLeft.forward( s._waveformLeft );
4132+
if(s._channels > 1){
4133+
s._fftRight.forward( s._waveformRight );
4134+
}
4135+
s._onTimer(true);
39554136
})
39564137

39574138
};
@@ -5938,4 +6119,4 @@ if (window.SM2_DEFER === undefined || !SM2_DEFER) {
59386119
window.SoundManager = SoundManager; // constructor
59396120
window.soundManager = soundManager; // public API, flash callbacks etc.
59406121

5941-
}(window));
6122+
}(window));

0 commit comments

Comments
 (0)