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 !!!"); |