skytnt commited on
Commit
cb1e380
1 Parent(s): fe8c885

add cc curve

Browse files
Files changed (1) hide show
  1. javascript/app.js +70 -15
javascript/app.js CHANGED
@@ -229,9 +229,12 @@ class MidiVisualizer extends HTMLElement{
229
  }
230
 
231
  addTrack(id, tr, cl, name, color){
232
- const track = {id, tr, cl, name, color,
 
233
  instrument: cl===9?"Standard Drum":"Acoustic Grand",
234
- svg: document.createElementNS('http://www.w3.org/2000/svg', 'g')}
 
 
235
  this.svg.appendChild(track.svg)
236
  const trackItem = this.createTrackItem(track);
237
  this.trackList.appendChild(trackItem);
@@ -269,12 +272,18 @@ class MidiVisualizer extends HTMLElement{
269
  const content = document.createElement('div');
270
  content.style.paddingLeft = '30px';
271
  content.style.flexGrow = '1';
 
272
  content.innerHTML = `<p>${track.name}<br>${track.instrument}</p>`;
273
  trackItem.appendChild(content);
274
  track.updateInstrument = function (instrument){
275
  track.instrument = instrument;
276
  content.innerHTML = `<p>${track.name}<br>${track.instrument}</p>`;
277
  }
 
 
 
 
 
278
 
279
  const toggleSwitch = document.createElement('input');
280
  toggleSwitch.type = 'checkbox';
@@ -342,25 +351,31 @@ class MidiVisualizer extends HTMLElement{
342
  duration = midiEvent[6]
343
  }
344
  let vis_track = this.getTrack(track, channel);
345
-
346
  let x = (t/this.timePreBeat)*this.config.beatWidth
347
  let y = (127 - pitch)*this.config.noteHeight
348
  let w = (duration/this.timePreBeat)*this.config.beatWidth
349
  let h = this.config.noteHeight
350
  this.svgWidth = Math.ceil(Math.max(x + w, this.svgWidth))
351
- let color = vis_track.color
352
  let opacity = Math.min(1, velocity/127 + 0.1).toFixed(2)
353
- let rect = this.drawNote(vis_track.svg, x,y,w,h,
354
- `rgba(${color.r}, ${color.g}, ${color.b}, ${opacity})`)
355
- midiEvent.push(rect)
356
  this.setPlayTime(t);
357
  this.pianoRoll.scrollTo(this.svgWidth - this.pianoRoll.offsetWidth, this.pianoRoll.scrollTop)
358
  }else if(midiEvent[0] === "patch_change"){
359
- let track = midiEvent[2]
360
- let channel = midiEvent[3]
361
- this.patches[channel].push([t, midiEvent[4]])
362
- this.patches[channel].sort((a, b) => a[0] - b[0])
363
  this.getTrack(track, channel);
 
 
 
 
 
 
 
 
364
  }
365
  this.midiEvents.push(midiEvent);
366
  this.svg.style.width = `${this.svgWidth}px`;
@@ -368,22 +383,54 @@ class MidiVisualizer extends HTMLElement{
368
 
369
  }
370
 
371
- drawNote(svg, x, y, w, h, fill) {
372
- if (!svg) {
373
  return null;
374
  }
375
  const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
376
  rect.classList.add('note');
377
- rect.setAttribute('fill', fill);
 
378
  // Round values to the nearest integer to avoid partially filled pixels.
379
  rect.setAttribute('x', `${Math.round(x)}`);
380
  rect.setAttribute('y', `${Math.round(y)}`);
381
  rect.setAttribute('width', `${Math.round(w)}`);
382
  rect.setAttribute('height', `${Math.round(h)}`);
383
- svg.appendChild(rect);
384
  return rect
385
  }
386
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  finishAppendMidiEvent(){
388
  this.pause()
389
  let midiEvents = this.midiEvents.sort((a, b)=>a[1]-b[1])
@@ -405,6 +452,14 @@ class MidiVisualizer extends HTMLElement{
405
  }
406
  lastT = t;
407
  })
 
 
 
 
 
 
 
 
408
  }
409
 
410
  setPlayTime(t){
 
229
  }
230
 
231
  addTrack(id, tr, cl, name, color){
232
+ const track = {id, tr, cl, name, color, empty: true,
233
+ lastCC: new Map(),
234
  instrument: cl===9?"Standard Drum":"Acoustic Grand",
235
+ svg: document.createElementNS('http://www.w3.org/2000/svg', 'g'),
236
+ ccPaths: new Map()
237
+ }
238
  this.svg.appendChild(track.svg)
239
  const trackItem = this.createTrackItem(track);
240
  this.trackList.appendChild(trackItem);
 
272
  const content = document.createElement('div');
273
  content.style.paddingLeft = '30px';
274
  content.style.flexGrow = '1';
275
+ content.style.color = "grey"
276
  content.innerHTML = `<p>${track.name}<br>${track.instrument}</p>`;
277
  trackItem.appendChild(content);
278
  track.updateInstrument = function (instrument){
279
  track.instrument = instrument;
280
  content.innerHTML = `<p>${track.name}<br>${track.instrument}</p>`;
281
  }
282
+ track.setEmpty = function (empty){
283
+ if (empty!==track.empty){
284
+ content.style.color = empty?"grey":"black";
285
+ }
286
+ }
287
 
288
  const toggleSwitch = document.createElement('input');
289
  toggleSwitch.type = 'checkbox';
 
351
  duration = midiEvent[6]
352
  }
353
  let vis_track = this.getTrack(track, channel);
354
+ vis_track.setEmpty(false);
355
  let x = (t/this.timePreBeat)*this.config.beatWidth
356
  let y = (127 - pitch)*this.config.noteHeight
357
  let w = (duration/this.timePreBeat)*this.config.beatWidth
358
  let h = this.config.noteHeight
359
  this.svgWidth = Math.ceil(Math.max(x + w, this.svgWidth))
 
360
  let opacity = Math.min(1, velocity/127 + 0.1).toFixed(2)
361
+ let rect = this.drawNote(vis_track, x,y,w,h, opacity)
362
+ midiEvent.push(rect);
 
363
  this.setPlayTime(t);
364
  this.pianoRoll.scrollTo(this.svgWidth - this.pianoRoll.offsetWidth, this.pianoRoll.scrollTop)
365
  }else if(midiEvent[0] === "patch_change"){
366
+ let track = midiEvent[2];
367
+ let channel = midiEvent[3];
368
+ this.patches[channel].push([t, midiEvent[4]]);
369
+ this.patches[channel].sort((a, b) => a[0] - b[0]);
370
  this.getTrack(track, channel);
371
+ }else if(midiEvent[0] === "control_change"){
372
+ let track = midiEvent[2];
373
+ let channel = midiEvent[3];
374
+ let controller = midiEvent[4];
375
+ let value = midiEvent[5];
376
+ let vis_track = this.getTrack(track, channel);
377
+ this.drawCC(vis_track, t, controller, value);
378
+ this.setPlayTime(t);
379
  }
380
  this.midiEvents.push(midiEvent);
381
  this.svg.style.width = `${this.svgWidth}px`;
 
383
 
384
  }
385
 
386
+ drawNote(track, x, y, w, h, opacity) {
387
+ if (!track.svg) {
388
  return null;
389
  }
390
  const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
391
  rect.classList.add('note');
392
+ const color = track.color;
393
+ rect.setAttribute('fill', `rgba(${color.r}, ${color.g}, ${color.b}, ${opacity})`);
394
  // Round values to the nearest integer to avoid partially filled pixels.
395
  rect.setAttribute('x', `${Math.round(x)}`);
396
  rect.setAttribute('y', `${Math.round(y)}`);
397
  rect.setAttribute('width', `${Math.round(w)}`);
398
  rect.setAttribute('height', `${Math.round(h)}`);
399
+ track.svg.appendChild(rect);
400
  return rect
401
  }
402
 
403
+ drawCC(track, t, controller, value){
404
+ if (!track.svg) {
405
+ return null;
406
+ }
407
+ let path = track.ccPaths.get(controller);
408
+ let x = (t/this.timePreBeat)*this.config.beatWidth
409
+ let y = (127 - value)*this.config.noteHeight
410
+ if (!path){
411
+ path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
412
+ path.setAttribute('visibility',"hidden");
413
+ path.setAttribute('fill', "transparent");
414
+ const color = track.color;
415
+ path.setAttribute('stroke', `rgba(${color.r}, ${color.g}, ${color.b}, 0.6)`);
416
+ path.setAttribute('stroke-width', "1");
417
+ path.setAttribute('d',
418
+ t===0?`M ${x} ${y}`:`M 0 ${127*this.config.noteHeight} H ${x} L ${x} ${y}`);
419
+ track.svg.appendChild(path);
420
+ track.ccPaths.set(controller, path);
421
+ track.lastCC.set(controller, value);
422
+ return path;
423
+ }
424
+ let lastVal = track.lastCC.get(controller);
425
+ if(lastVal !== value){
426
+ path.removeAttribute('visibility');
427
+ }
428
+ let d = path.getAttribute("d");
429
+ d += `H ${x} L ${x} ${y}`
430
+ path.setAttribute('d', d);
431
+ return path
432
+ }
433
+
434
  finishAppendMidiEvent(){
435
  this.pause()
436
  let midiEvents = this.midiEvents.sort((a, b)=>a[1]-b[1])
 
452
  }
453
  lastT = t;
454
  })
455
+ let x = (lastT/this.timePreBeat)*this.config.beatWidth;
456
+ this.trackMap.forEach((track, id)=>{
457
+ track.ccPaths.forEach((path, controller)=>{
458
+ let d = path.getAttribute("d");
459
+ d += `H ${x}`
460
+ path.setAttribute('d', d);
461
+ })
462
+ })
463
  }
464
 
465
  setPlayTime(t){