client/annotviz/app/js/pianoroll.js
changeset 93 79ae42ad97d4
parent 85 eff9460bd4f2
child 94 e0e514c5470f
equal deleted inserted replaced
87:9611905b58fe 93:79ae42ad97d4
     3 *
     3 *
     4 * pianoroll basic component
     4 * pianoroll basic component
     5 *
     5 *
     6 */
     6 */
     7 
     7 
       
     8 /* global window: false */
     8 'use strict';
     9 'use strict';
       
    10 
     9 
    11 
    10 var PIXI = require('pixi');
    12 var PIXI = require('pixi');
    11 var randomColor = require('randomColor');
    13 var randomColor = require('randomColor');
    12 
    14 var _ = require('lodash');
    13 function PianoRoll(parentContainer, xInit, yInit, height, linesDown, pixelsPerSecond, width, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, noteHeight){
    15 
       
    16 
       
    17 function PianoRoll(options) {
    14     var _this = this;
    18     var _this = this;
    15     this.container = new PIXI.DisplayObjectContainer();
    19     this.container = new PIXI.DisplayObjectContainer();
    16     this.container.position.x = xInit;
    20     this.container.position.x = options.xInit;
    17     this.container.position.y = yInit;
    21     this.container.position.y = options.yInit;
    18     parentContainer.addChild(this.container);
    22     options.parentContainer.addChild(this.container);
    19 
    23 
    20     this.linesDown = linesDown;
    24     this.linesDown = options.linesDown;
    21     this.height = height;
    25     this.height = options.height;
    22     this.pixelsPerSecond = pixelsPerSecond;
    26     this.pixelsPerSecond = options.pixelsPerSecond;
    23     this.width = width;
    27     this.width = options.width;
    24     this.noteColors = noteColors;
    28     this.noteColors = options.noteColors;
    25     this.colorsReg = colorsReg || {};
    29     this.colorsReg = options.colorsReg || {};
    26     this.lineColor = lineColor;
    30     this.lineColor = options.lineColor;
    27     this.lineInterval = lineInterval;
    31     this.lineInterval = options.lineInterval;
    28     this.offsetMusic = offsetMusic || 0;
    32     this.offsetMusic = options.offsetMusic || false;
    29     this.noteHeight = noteHeight;
    33     this.noteHeight = options.noteHeight;
    30 
    34     this.noteDict = {};
    31     this.addNote = function(note, startTime, duration, velocity, canal){
    35     this.startTs = options.startTs || Date.now();
    32         //console.log("coucou 1", note, timeFromZero, ts, velocity, pixelsPerSecond, container, prHeight);
    36 
    33         var beginX = (this.offsetMusic + startTime) * this.pixelsPerSecond / 1000;
    37 
    34         var width = duration * this.pixelsPerSecond / 1000;
    38     //TODO: I do not like the "regColor" object. This should not be global, but local
    35         if((beginX+width) <  (Math.abs(this.container.x) - this.width)) {
    39     this.getColor = function(canal) {
    36             // not visible. do nothing
       
    37             return;
       
    38         }
       
    39         // We draw the rectangle
       
    40         var graphics = new PIXI.Graphics();
       
    41         //console.log("beginX = ", beginX, "canal = ", canal, "color = ", noteColor[canal], "width = ", width, "note = ", note, "velocity = ", velocity);
       
    42         var color = this.colorsReg[canal];
    40         var color = this.colorsReg[canal];
    43         if(typeof(color) === 'undefined') {
    41         if(typeof(color) === 'undefined') {
    44             var colorsRegSize = Object.keys(this.colorsReg).length;
    42             var colorsRegSize = Object.keys(this.colorsReg).length;
    45             if(colorsRegSize < this.noteColors.length) {
    43             if(colorsRegSize < this.noteColors.length) {
    46                 color = this.colorsReg[canal] = this.noteColors[colorsRegSize];
    44                 color = this.colorsReg[canal] = this.noteColors[colorsRegSize];
    47             }
    45             }
    48             else {
    46             else {
    49                 color = this.colorsReg[canal] = parseInt(randomColor({ luminosity: 'light', hue: 'random', format:'hex'}).replace(/^#/, ''), 16);
    47                 color = this.colorsReg[canal] = parseInt(randomColor({ luminosity: 'light', hue: 'random', format:'hex'}).replace(/^#/, ''), 16);
    50             }
    48             }
    51         }
    49         }
    52         graphics.beginFill(color, (velocity / 128));
    50         return color;
    53         var y = (128-note) * this.height / 128; // (128-note) because y = 0 is for note = 128 and y = 128 for note = 0
    51     };
    54         graphics.drawRect(0, Math.floor(y - (noteHeight/2) + ((this.height / 128)/2)), width, noteHeight);
    52 
       
    53     this.getNoteRect = function(x, y, color, alpha, width, height) {
       
    54         var graphics = new PIXI.Graphics();
       
    55         //console.log("beginX = ", beginX, "canal = ", canal, "color = ", noteColor[canal], "width = ", width, "note = ", note, "velocity = ", velocity);
       
    56         graphics.beginFill(color, alpha);
       
    57         graphics.drawRect(0, 0, width, height);
    55         graphics.endFill();
    58         graphics.endFill();
    56         graphics.x = beginX;
    59         graphics.x = x;
    57         this.container.addChild(graphics);
    60         graphics.y = y;
       
    61         graphics.width = width;
       
    62         graphics.height = height;
       
    63         return graphics;
       
    64     };
       
    65 
       
    66     this.addNote = function(note, startTime, sessionTs, velocity, channel, duration) {
       
    67 
       
    68         var ts = startTime;
       
    69         if(this.offsetMusic) {
       
    70             ts = this.startTs + sessionTs;
       
    71         }
       
    72 
       
    73         var noteDuration = duration;
       
    74         var noteVelocity = velocity;
       
    75         var graphics;
       
    76         if(!duration) {
       
    77             if(typeof this.noteDict[channel]==='undefined'){
       
    78                 this.noteDict[channel] = {};
       
    79             }
       
    80             if(velocity===0) {
       
    81                 if(typeof this.noteDict[channel][note] !== 'undefined') {
       
    82                     var noteDef = this.noteDict[channel][note];
       
    83                     delete this.noteDict[channel][note];
       
    84                     noteDuration = sessionTs - noteDef.sessionTs;
       
    85                     graphics = noteDef.graphics;
       
    86                     noteVelocity = noteDef.velocity;
       
    87                     ts = noteDef.ts;
       
    88                 }
       
    89             }
       
    90             else {
       
    91                 noteDuration = Date.now() - ts;
       
    92                 this.noteDict[channel][note] = { ts: ts, velocity: velocity, sessionTs: sessionTs};
       
    93             }
       
    94         }
       
    95 
       
    96 
       
    97         if(!this.offsetMusic || velocity===0) {
       
    98 
       
    99             var width = noteDuration * this.pixelsPerSecond / 1000;
       
   100             if(!graphics) {
       
   101                 var x = (ts-this.startTs) * this.pixelsPerSecond / 1000;
       
   102                 if((x+width) <  (Math.abs(this.container.x) - this.width)) {
       
   103                     // not visible. do nothing
       
   104                     return;
       
   105                 }
       
   106                 var y = Math.floor((128-note+0.5) * this.height / 128 - (this.noteHeight/2));
       
   107                 var color = this.getColor(channel);
       
   108                 var alpha = (noteVelocity / 128);
       
   109 
       
   110                 graphics = this.getNoteRect(x, y, color, alpha, width, this.noteHeight);
       
   111                 this.container.addChild(graphics);
       
   112                 //console.log(color, alpha, graphics.lineColor, graphics.fillAlpha);
       
   113             }
       
   114             else {
       
   115                 graphics.width = width;
       
   116             }
       
   117 
       
   118             if(!duration && velocity) {
       
   119                 this.noteDict[channel][note].graphics = graphics;
       
   120             }
       
   121         }
    58     };
   122     };
    59 
   123 
    60     this.addLine = function(ts){
   124     this.addLine = function(ts){
       
   125 
       
   126         if(typeof(ts) === 'undefined') {
       
   127             ts = new Date();
       
   128         }
    61         var graphics = new PIXI.Graphics();
   129         var graphics = new PIXI.Graphics();
    62         var x = -this.container.x;
   130         var x = -this.container.x;
    63         graphics.beginFill(0xFFFF00);
   131         graphics.beginFill(0xFFFF00);
    64         graphics.lineStyle(1, this.lineColor);
   132         graphics.lineStyle(1, this.lineColor);
    65         var y = this.linesDown ? this.height - 20 : 0;
   133         var y = this.linesDown ? this.height - 20 : 0;
    80         t.y = this.linesDown ? this.height - 15 : 2;
   148         t.y = this.linesDown ? this.height - 15 : 2;
    81         this.container.addChild(t);
   149         this.container.addChild(t);
    82     };
   150     };
    83 
   151 
    84     this.moveTo = function(diffTime){
   152     this.moveTo = function(diffTime){
       
   153         var oldX = this.container.x;
    85         this.container.x = Math.floor(diffTime*this.pixelsPerSecond);
   154         this.container.x = Math.floor(diffTime*this.pixelsPerSecond);
       
   155         var deltaX = Math.abs(oldX-this.container.x);
       
   156         _.forOwn(this.noteDict, function(channelDict) {
       
   157             _.forOwn(channelDict, function(noteDef) {
       
   158                 if(noteDef.graphics) {
       
   159                     noteDef.graphics.width = noteDef.graphics.width + deltaX;
       
   160                 }
       
   161             });
       
   162         });
       
   163     };
       
   164 
       
   165     this.move = function() {
       
   166         var diff = (this.startTs - Date.now())/1000;
       
   167         this.moveTo(diff);
    86     };
   168     };
    87 
   169 
    88     this.removePassedObjets = function(){
   170     this.removePassedObjets = function(){
    89         var nbChilds = _this.container.children.length;
   171         var nbChilds = _this.container.children.length;
    90         var i = 0, childIsNowDisplayed = false, childrenToRemove = [];
   172         var i = 0, childIsNowDisplayed = false, childrenToRemove = [];
    91         while(i<nbChilds && !childIsNowDisplayed){
   173         while(i<nbChilds && !childIsNowDisplayed){
    92             var child = _this.container.children[i++];
   174             var child = _this.container.children[i++];
    93             //console.log("remove ? ", child.x, child.width, ((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)));
   175             //console.log("remove ? ", child.x, child.width, ((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)));
    94             if(typeof(child) == 'undefined') {
   176             if(typeof(child) === 'undefined') {
    95                 continue;
   177                 continue;
    96             }
   178             }
    97             if((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)){
   179             if((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)){
    98                 childrenToRemove.push(child);
   180                 childrenToRemove.push(child);
    99                 //console.log("    remove !!!");
   181                 //console.log("    remove !!!");
   107             _this.container.removeChild(child);
   189             _this.container.removeChild(child);
   108         });
   190         });
   109         //console.log("before : ", nbChilds, ", after : ", _this.container.children.length);
   191         //console.log("before : ", nbChilds, ", after : ", _this.container.children.length);
   110     };
   192     };
   111 
   193 
   112     // remove notes each scene width
   194     this.start = function() {
   113     //var removeInterval = window.setInterval(this.removePassedObjets, 1000 * sceneWidth / this.pixelsPerSecond );
   195         if(typeof(this.startTs) === 'undefined') {
   114     window.setInterval(this.removePassedObjets, 1000 * this.width / this.pixelsPerSecond );
   196             console.log('Container Started');
       
   197             this.startTs = Date.now();
       
   198             this.addLine();
       
   199         }
       
   200         var _this = this;
       
   201         this.verticalLinesInterval = window.setInterval(function() { _this.addLine(); }, this.lineInterval);
       
   202         this.cleanInterval = window.setInterval(function () { _this.removePassedObjets(); }, 1000 * this.width / this.pixelsPerSecond );
       
   203     };
       
   204 
       
   205     this.stop = function() {
       
   206         //window.clearInterval(this.moveInterval);
       
   207         window.clearInterval(this.verticalLinesInterval);
       
   208         window.clearInterval(this.cleanInterval);
       
   209     };
       
   210 
   115 
   211 
   116 }
   212 }
   117 
   213 
   118 module.exports = PianoRoll;
   214 module.exports = PianoRoll;