34 this.lineInterval = options.lineInterval; |
34 this.lineInterval = options.lineInterval; |
35 this.offsetMusic = options.offsetMusic || false; |
35 this.offsetMusic = options.offsetMusic || false; |
36 this.noteHeight = options.noteHeight; |
36 this.noteHeight = options.noteHeight; |
37 this.noteDict = {}; |
37 this.noteDict = {}; |
38 this.startTs = options.startTs || Date.now(); |
38 this.startTs = options.startTs || Date.now(); |
39 |
39 this.dynamicRange = options.dynamicRange; |
|
40 this.initRange = options.range; |
40 this.range = options.range; |
41 this.range = options.range; |
41 |
42 |
42 |
43 |
43 var started = false; |
44 var started = false; |
44 |
45 |
63 return color; |
64 return color; |
64 }; |
65 }; |
65 |
66 |
66 this.getNoteRect = function(note, x, y, color, alpha, width, height) { |
67 this.getNoteRect = function(note, x, y, color, alpha, width, height) { |
67 var graphics = new PIXI.Graphics(); |
68 var graphics = new PIXI.Graphics(); |
|
69 graphics.note = note; |
68 graphics.beginFill(color, alpha); |
70 graphics.beginFill(color, alpha); |
69 graphics.drawRect(0, 0, width, height); |
71 graphics.drawRect(0, 0, width, height); |
70 graphics.endFill(); |
72 graphics.endFill(); |
71 graphics.x = x; |
73 graphics.x = x; |
72 graphics.y = y; |
74 graphics.y = y; |
73 graphics.width = width; |
75 graphics.width = width; |
74 graphics.height = height; |
76 graphics.height = height; |
75 graphics.note = note; |
|
76 return graphics; |
77 return graphics; |
77 }; |
78 }; |
78 |
79 |
79 this.addNoteRaw = function(data) { |
80 this.addNoteRaw = function(data) { |
80 var note = data.content[3]; |
81 var note = data.content[3]; |
124 var x = (ts-this.startTs) * this.pixelsPerSecond / 1000; |
125 var x = (ts-this.startTs) * this.pixelsPerSecond / 1000; |
125 if((x+width) < (Math.abs(this.container.x) - this.width)) { |
126 if((x+width) < (Math.abs(this.container.x) - this.width)) { |
126 // not visible. do nothing |
127 // not visible. do nothing |
127 return; |
128 return; |
128 } |
129 } |
129 if (this.range.bottom > note || note > this.range.top){ |
130 if (this.dynamicRange && (this.range.bottom > note || note > this.range.top)){ |
130 if (note < this.range.bottom) |
131 var newScale = {}; |
131 this.range.bottom = note; |
132 newScale['bottom'] = Math.min(note, this.range.bottom); |
132 else |
133 newScale['top'] = Math.max(note, this.range.top); |
133 this.range.top = note; |
134 this.rescaleScene(newScale); |
134 this.noteHeight = this.height / (this.range.top - this.range.bottom); |
|
135 this.rescaleScene(); |
|
136 } |
135 } |
137 var y = Math.floor(((this.range.top-this.range.bottom)-(note-this.range.bottom)+0.5) * (this.height / (this.range.top-this.range.bottom)) - (this.noteHeight/2)); |
136 var y = Math.floor(((this.range.top-this.range.bottom)-(note-this.range.bottom)+0.5) * (this.noteHeight) - (this.noteHeight/2)); |
138 var color = this.getColor(channel); |
137 var color = this.getColor(channel); |
139 //128 hardecoded because its the maximum velocity of MIDI |
138 |
140 var alpha = (noteVelocity / 128); |
139 var alpha = (noteVelocity / 128); |
141 |
140 |
142 graphics = this.getNoteRect(note, x, y, color, alpha, width, this.noteHeight); |
141 graphics = this.getNoteRect(note, x, y, color, alpha, width, this.noteHeight); |
143 this.container.addChild(graphics); |
142 this.container.addChild(graphics); |
144 } |
143 } |
150 this.noteDict[channel][note].graphics = graphics; |
149 this.noteDict[channel][note].graphics = graphics; |
151 } |
150 } |
152 } |
151 } |
153 }; |
152 }; |
154 |
153 |
155 this.rescaleScene = function(){ |
154 //rescale scene in case a note out of range is added or a note out of the range is removed |
|
155 this.rescaleScene = function(newScale){ |
156 var _this = this; |
156 var _this = this; |
157 var childrenToUpdate = []; |
157 var childrenToUpdate = []; |
|
158 var top = this.initRange.top; |
|
159 var bottom = this.initRange.bottom; |
158 _(_this.container.children).forEach(function(child) { |
160 _(_this.container.children).forEach(function(child) { |
159 return typeof(child) === 'undefined' || |
161 if (typeof(child) !== 'undefined' && child.note && !isHidden(child)){ |
160 (!isHidden(child) && childrenToUpdate.push(child)); |
162 top = Math.max(child.note, top); |
161 }); |
163 bottom = Math.min(child.note, bottom); |
|
164 return childrenToUpdate.push(child); |
|
165 } |
|
166 }); |
|
167 if (newScale){ |
|
168 this.range = newScale; |
|
169 }else{ |
|
170 this.range.top = top; |
|
171 this.range.bottom = bottom; |
|
172 } |
|
173 this.noteHeight = this.height / (this.range.top - this.range.bottom + 1); |
162 childrenToUpdate.forEach(function(child) { |
174 childrenToUpdate.forEach(function(child) { |
163 child.y = Math.floor(((_this.range.top-_this.range.bottom)-(child.note-_this.range.bottom)+0.5) * (_this.height / (_this.range.top-_this.range.bottom)) - (_this.noteHeight/2)); |
175 child.y = Math.floor(((_this.range.top-_this.range.bottom)-(child.note-_this.range.bottom)+0.5) * (_this.noteHeight) - (_this.noteHeight/2)); |
164 child.height = _this.noteHeight; |
176 child.height = _this.noteHeight; |
165 }); |
177 }); |
166 } |
178 }; |
167 |
179 |
168 this.addLine = function(ts){ |
180 this.addLine = function(ts){ |
169 |
181 |
170 if(typeof(ts) === 'undefined') { |
182 if(typeof(ts) === 'undefined') { |
171 ts = new Date(); |
183 ts = new Date(); |
221 this.moveTo(diff); |
233 this.moveTo(diff); |
222 }; |
234 }; |
223 |
235 |
224 this.removePassedObjets = function(){ |
236 this.removePassedObjets = function(){ |
225 var childrenToRemove = []; |
237 var childrenToRemove = []; |
|
238 var rescale = false; |
226 _(_this.container.children).forEach(function(child) { |
239 _(_this.container.children).forEach(function(child) { |
227 return typeof(child) === 'undefined' || |
240 return typeof(child) === 'undefined' || |
228 (isHidden(child) && childrenToRemove.push(child)); |
241 (isHidden(child) && childrenToRemove.push(child)); |
229 }); |
242 }); |
230 childrenToRemove.forEach(function(child) { |
243 childrenToRemove.forEach(function(child) { |
|
244 if (_this.dynamicRange && (_this.range.bottom === child.note || child.note === _this.range.top)){ |
|
245 rescale = true; |
|
246 } |
231 _this.container.removeChild(child); |
247 _this.container.removeChild(child); |
232 }); |
248 }); |
|
249 //externalize this test to avoid repeated call to the function rescaleScene in the previous loop |
|
250 if (rescale){ |
|
251 _this.rescaleScene(); |
|
252 } |
233 }; |
253 }; |
234 |
254 |
235 this.start = function() { |
255 this.start = function() { |
236 if(!started) { |
256 if(!started) { |
237 this.startTs = Date.now(); |
257 this.startTs = Date.now(); |
241 this.verticalLinesInterval = setInterval(function() { _this.addLine(); }, this.lineInterval); |
261 this.verticalLinesInterval = setInterval(function() { _this.addLine(); }, this.lineInterval); |
242 this.cleanInterval = setInterval(function () { _this.removePassedObjets(); }, 1000 * this.width / this.pixelsPerSecond ); |
262 this.cleanInterval = setInterval(function () { _this.removePassedObjets(); }, 1000 * this.width / this.pixelsPerSecond ); |
243 }; |
263 }; |
244 |
264 |
245 this.stop = function() { |
265 this.stop = function() { |
246 //window.clearInterval(this.moveInterval); |
|
247 clearInterval(this.verticalLinesInterval); |
266 clearInterval(this.verticalLinesInterval); |
248 clearInterval(this.cleanInterval); |
267 clearInterval(this.cleanInterval); |
249 }; |
268 }; |
250 |
269 |
251 |
|
252 } |
270 } |
253 |
271 |
254 module.exports = PianoRoll; |
272 module.exports = PianoRoll; |