diff --git a/media.js b/media.js index 5558f552..a2277a92 100644 --- a/media.js +++ b/media.js @@ -36,9 +36,6 @@ Media = { // Create the analyser node for the visualizer this._analyser = this._context.createAnalyser(); this._analyser.fftSize = 2048; - this._bufferLength = this._analyser.frequencyBinCount; - this._dataArray = new Uint8Array(this._bufferLength); - this._analyser.getByteTimeDomainData(this._dataArray); // Connect all the nodes in the correct way // (Note, source is created and connected later) @@ -221,8 +218,7 @@ Media = { // _updatePosition might have stoped the playing if(this._playing) { - this._analyser.getByteTimeDomainData(this._dataArray); - this._callbacks.visualizerupdate(this._bufferLength, this._dataArray); + this._callbacks.visualizerupdate(this._analyser); } } window.requestAnimationFrame(this._draw.bind(this)); diff --git a/skin.js b/skin.js index 9257c6c3..f26befcb 100644 --- a/skin.js +++ b/skin.js @@ -2,8 +2,11 @@ SkinManager = { fileManager: FileManager, font: Font, - style: document.getElementById('skin'), - visualizer: Visualizer.init(document.getElementById('visualizer')), + init: function(styleNode, visualizerNode, analyser) { + this.styleNode = styleNode; + this.visualizer = Visualizer.init(visualizerNode, analyser); + return this; + }, _skinImages: { "#winamp": "MAIN.BMP", @@ -71,7 +74,7 @@ SkinManager = { // Clear the loading state document.getElementById('winamp').classList.remove('loading'); - this.style.appendChild(document.createTextNode(cssRules)); + this.styleNode.appendChild(document.createTextNode(cssRules)); this._parseVisColors(zip); @@ -86,7 +89,7 @@ SkinManager = { for(var i = 0; i < 24; i++) { var matches = regex.exec(entries[i]); if(matches) { - this.visualizer.colors.push('rgb(' + matches.slice(1,4).join(',') + ')'); + this.visualizer.colors[i] = 'rgb(' + matches.slice(1,4).join(',') + ')'; } else { console.error('Error in VISCOLOR.TXT on line', i); this.visColors.push('rgb(255,0,0)'); diff --git a/visualizer.js b/visualizer.js index 7d421f8f..da49f50f 100644 --- a/visualizer.js +++ b/visualizer.js @@ -1,16 +1,21 @@ /* Use Canvas to recreate the simple Winamp visualizer */ Visualizer = { - init: function(canvasNode) { + init: function(canvasNode, analyser) { this.canvas = canvasNode; + this.analyser = analyser; this.canvasCtx = this.canvas.getContext("2d"); this.canvasCtx.imageSmoothingEnabled= false; this.canvasCtx.translate(1, 1); // http://stackoverflow.com/questions/13593527/canvas-make-the-line-thicker this.width = this.canvas.width; this.height = this.canvas.height; - this.colors = []; + this.colors = []; // skin.js fills this from viscolors.txt this.NONE = 0; this.OSCILLOSCOPE = 1; this.BAR = 2; + this.bufferLength = null; + this.dataArray = null; + this.setStyle(this.BAR); + return this; }, @@ -19,17 +24,31 @@ Visualizer = { this.canvasCtx.clearRect(-2, -2, this.width + 2, this.height + 2); }, - paintFrame: function(type, bufferLength, dataArray) { - this.clear(); - if(type == this.OSCILLOSCOPE) { - return this._paintOscilloscopeFrame(bufferLength, dataArray); - } else if(type == this.BAR) { - return this._paintBarFrame(bufferLength, dataArray); + setStyle: function(style) { + this.style = style; + if(this.style == this.OSCILLOSCOPE) { + this.analyser.fftSize = 2048; + this.bufferLength = this.analyser.fftSize; + this.dataArray = new Uint8Array(this.bufferLength); + } else if(this.style == this.BAR) { + this.analyser.fftSize = 64; // Must be a power of two + // Number of bins/bars we get + this.bufferLength = this.analyser.frequencyBinCount; + this.dataArray = new Uint8Array(this.bufferLength); } }, - _paintOscilloscopeFrame: function(bufferLength, dataArray) { - function avg() { + paintFrame: function() { + this.clear(); + if(this.style == this.OSCILLOSCOPE) { + return this._paintOscilloscopeFrame(); + } else if(this.style == this.BAR) { + return this._paintBarFrame(); + } + }, + + _paintOscilloscopeFrame: function() { + function avg(dataArray) { var avg = 0; var count = 0; for (var l = lastIndex; l < index + 1; l++) { @@ -39,6 +58,7 @@ Visualizer = { var v = avg / count; return h * v / 128; } + this.analyser.getByteTimeDomainData(this.dataArray); this.canvasCtx.lineWidth = 2; // 2 because were shrinking the canvas by 2 @@ -47,7 +67,7 @@ Visualizer = { this.canvasCtx.beginPath(); - var sliceWidth = bufferLength / this.width * 1; + var sliceWidth = this.bufferLength / this.width * 1; var h = this.height / 2; this.canvasCtx.moveTo(-2, h); @@ -55,17 +75,36 @@ Visualizer = { var lastIndex = 0; for (var i = 0, iEnd = this.width * 1; i < iEnd; i += 2) { index = i * sliceWidth | 0; - this.canvasCtx.lineTo(i, avg()); + this.canvasCtx.lineTo(i, avg(this.dataArray)); lastIndex = index + 1; } lastIndex = index + 1; index = i * sliceWidth | 0; - this.canvasCtx.lineTo(this.width, avg()); + this.canvasCtx.lineTo(this.width, avg(this.dataArray)); this.canvasCtx.stroke(); }, - _paintBarFrame: function(bufferLength, dataArray) { - // TODO + _paintBarFrame: function() { + var printBar = function(x, height) { + var max = height; + for(i = 0; i <= max; i++) { + var colorNumber = 17 - i; + var y = 32 - (i*2); + this.canvasCtx.fillStyle = this.colors[colorNumber]; + this.canvasCtx.fillRect(x,y,6,2); + } + + // Draw the grey peak line + this.canvasCtx.fillStyle = this.colors[23]; + var y = 32 - ((max)*2); + this.canvasCtx.fillRect(x,y,6,2); + }.bind(this); + + this.analyser.getByteFrequencyData(this.dataArray); + for(j = 0; j < this.bufferLength; j++) { + height = this.dataArray[j] * (15/256); + printBar(j*8, height); + } } } diff --git a/winamp.js b/winamp.js index a3811b23..a32a8c10 100755 --- a/winamp.js +++ b/winamp.js @@ -3,8 +3,7 @@ function Winamp () { self = this; this.fileManager = FileManager; this.media = Media.init(); - this.skin = SkinManager; - this.skin.visualizerStyle = this.skin.visualizer.OSCILLOSCOPE; + this.skin = SkinManager.init(document.getElementById('skin'), document.getElementById('visualizer'), this.media._analyser); this.fileName = ''; this.nodes = { @@ -106,8 +105,8 @@ function Winamp () { self.updateTime(); }); - this.media.addEventListener('visualizerupdate', function(bufferLength, dataArray) { - self.skin.visualizer.paintFrame(self.skin.visualizerStyle, bufferLength, dataArray); + this.media.addEventListener('visualizerupdate', function(analyser) { + self.skin.visualizer.paintFrame(self.visualizerStyle, analyser); }); this.media.addEventListener('ended', function() { @@ -139,12 +138,12 @@ function Winamp () { } this.nodes.visualizer.onclick = function() { - if(self.visualizerStyle == self.skin.visualizer.NONE) { - // self.visualizerStyle = self.visualizer.BAR; - //} else if(self.visualizerStyle == self.visualizer.BAR) { - self.visualizerStyle = self.skin.visualizer.OSCILLOSCOPE; - } else if(self.visualizerStyle == self.skin.visualizer.OSCILLOSCOPE) { - self.visualizerStyle = self.skin.visualizer.NONE; + if(self.skin.visualizer.style == self.skin.visualizer.NONE) { + self.skin.visualizer.setStyle(self.skin.visualizer.BAR); + } else if(self.skin.visualizer.style == self.skin.visualizer.BAR) { + self.skin.visualizer.setStyle(self.skin.visualizer.OSCILLOSCOPE); + } else if(self.skin.visualizer.style == self.skin.visualizer.OSCILLOSCOPE) { + self.skin.visualizer.setStyle(self.skin.visualizer.NONE); } self.skin.visualizer.clear(); }