diff -r 9611905b58fe -r 79ae42ad97d4 client/annotviz/app/js/pianoroll.js --- a/client/annotviz/app/js/pianoroll.js Tue Jan 13 15:27:20 2015 +0100 +++ b/client/annotviz/app/js/pianoroll.js Fri Jan 16 03:16:19 2015 +0100 @@ -5,40 +5,38 @@ * */ +/* global window: false */ 'use strict'; + var PIXI = require('pixi'); var randomColor = require('randomColor'); +var _ = require('lodash'); -function PianoRoll(parentContainer, xInit, yInit, height, linesDown, pixelsPerSecond, width, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, noteHeight){ + +function PianoRoll(options) { var _this = this; this.container = new PIXI.DisplayObjectContainer(); - this.container.position.x = xInit; - this.container.position.y = yInit; - parentContainer.addChild(this.container); + this.container.position.x = options.xInit; + this.container.position.y = options.yInit; + options.parentContainer.addChild(this.container); - this.linesDown = linesDown; - this.height = height; - this.pixelsPerSecond = pixelsPerSecond; - this.width = width; - this.noteColors = noteColors; - this.colorsReg = colorsReg || {}; - this.lineColor = lineColor; - this.lineInterval = lineInterval; - this.offsetMusic = offsetMusic || 0; - this.noteHeight = noteHeight; + this.linesDown = options.linesDown; + this.height = options.height; + this.pixelsPerSecond = options.pixelsPerSecond; + this.width = options.width; + this.noteColors = options.noteColors; + this.colorsReg = options.colorsReg || {}; + this.lineColor = options.lineColor; + this.lineInterval = options.lineInterval; + this.offsetMusic = options.offsetMusic || false; + this.noteHeight = options.noteHeight; + this.noteDict = {}; + this.startTs = options.startTs || Date.now(); - this.addNote = function(note, startTime, duration, velocity, canal){ - //console.log("coucou 1", note, timeFromZero, ts, velocity, pixelsPerSecond, container, prHeight); - var beginX = (this.offsetMusic + startTime) * this.pixelsPerSecond / 1000; - var width = duration * this.pixelsPerSecond / 1000; - if((beginX+width) < (Math.abs(this.container.x) - this.width)) { - // not visible. do nothing - return; - } - // We draw the rectangle - var graphics = new PIXI.Graphics(); - //console.log("beginX = ", beginX, "canal = ", canal, "color = ", noteColor[canal], "width = ", width, "note = ", note, "velocity = ", velocity); + + //TODO: I do not like the "regColor" object. This should not be global, but local + this.getColor = function(canal) { var color = this.colorsReg[canal]; if(typeof(color) === 'undefined') { var colorsRegSize = Object.keys(this.colorsReg).length; @@ -49,15 +47,85 @@ color = this.colorsReg[canal] = parseInt(randomColor({ luminosity: 'light', hue: 'random', format:'hex'}).replace(/^#/, ''), 16); } } - graphics.beginFill(color, (velocity / 128)); - var y = (128-note) * this.height / 128; // (128-note) because y = 0 is for note = 128 and y = 128 for note = 0 - graphics.drawRect(0, Math.floor(y - (noteHeight/2) + ((this.height / 128)/2)), width, noteHeight); + return color; + }; + + this.getNoteRect = function(x, y, color, alpha, width, height) { + var graphics = new PIXI.Graphics(); + //console.log("beginX = ", beginX, "canal = ", canal, "color = ", noteColor[canal], "width = ", width, "note = ", note, "velocity = ", velocity); + graphics.beginFill(color, alpha); + graphics.drawRect(0, 0, width, height); graphics.endFill(); - graphics.x = beginX; - this.container.addChild(graphics); + graphics.x = x; + graphics.y = y; + graphics.width = width; + graphics.height = height; + return graphics; + }; + + this.addNote = function(note, startTime, sessionTs, velocity, channel, duration) { + + var ts = startTime; + if(this.offsetMusic) { + ts = this.startTs + sessionTs; + } + + var noteDuration = duration; + var noteVelocity = velocity; + var graphics; + if(!duration) { + if(typeof this.noteDict[channel]==='undefined'){ + this.noteDict[channel] = {}; + } + if(velocity===0) { + if(typeof this.noteDict[channel][note] !== 'undefined') { + var noteDef = this.noteDict[channel][note]; + delete this.noteDict[channel][note]; + noteDuration = sessionTs - noteDef.sessionTs; + graphics = noteDef.graphics; + noteVelocity = noteDef.velocity; + ts = noteDef.ts; + } + } + else { + noteDuration = Date.now() - ts; + this.noteDict[channel][note] = { ts: ts, velocity: velocity, sessionTs: sessionTs}; + } + } + + + if(!this.offsetMusic || velocity===0) { + + var width = noteDuration * this.pixelsPerSecond / 1000; + if(!graphics) { + var x = (ts-this.startTs) * this.pixelsPerSecond / 1000; + if((x+width) < (Math.abs(this.container.x) - this.width)) { + // not visible. do nothing + return; + } + var y = Math.floor((128-note+0.5) * this.height / 128 - (this.noteHeight/2)); + var color = this.getColor(channel); + var alpha = (noteVelocity / 128); + + graphics = this.getNoteRect(x, y, color, alpha, width, this.noteHeight); + this.container.addChild(graphics); + //console.log(color, alpha, graphics.lineColor, graphics.fillAlpha); + } + else { + graphics.width = width; + } + + if(!duration && velocity) { + this.noteDict[channel][note].graphics = graphics; + } + } }; this.addLine = function(ts){ + + if(typeof(ts) === 'undefined') { + ts = new Date(); + } var graphics = new PIXI.Graphics(); var x = -this.container.x; graphics.beginFill(0xFFFF00); @@ -82,7 +150,21 @@ }; this.moveTo = function(diffTime){ + var oldX = this.container.x; this.container.x = Math.floor(diffTime*this.pixelsPerSecond); + var deltaX = Math.abs(oldX-this.container.x); + _.forOwn(this.noteDict, function(channelDict) { + _.forOwn(channelDict, function(noteDef) { + if(noteDef.graphics) { + noteDef.graphics.width = noteDef.graphics.width + deltaX; + } + }); + }); + }; + + this.move = function() { + var diff = (this.startTs - Date.now())/1000; + this.moveTo(diff); }; this.removePassedObjets = function(){ @@ -91,7 +173,7 @@ while(i