(
// 'note' data structure will be an event:
// (time: absolute time, midinote: num, amp: velocity/127, sustain: dur)
// you could use an array here too
~notes = Array(256);
~rows = Array(256);
t = TreeView(nil, Rect(600, 100, 400, 600)).front;
t.columns = ["Time", "Note", "Velocity", "Duration"];
4.do { |i| t.setColumnWidth(i, 100) };
MIDIdef.noteOn(\on, { |vel, num|
var time = TempoClock.beats;
~notes = ~notes.add((time: time, midinote: num, amp: vel / 127));
defer {
var row;
row = t.addItem([time.round(0.01).asString, num, vel, "--"]);
~rows = ~rows.add(row);
t.currentItem = row; // scroll to bottom
};
});
MIDIdef.noteOff(\off, { |vel, num|
var time = TempoClock.beats;
var i = ~notes.detectIndex { |note|
note[\midinote] == num and: { note[\sustain].isNil }
};
if(i.isNil) {
"Could not find note-on for note-off %".format(num).warn;
} {
~notes[i][\sustain] = time - ~notes[i][\time];
defer {
~rows[i].strings = ~rows[i].strings
.put(3, ~notes[i][\sustain].round(0.01).asString);
};
};
});
t.onClose = {
MIDIdef(\on).free;
MIDIdef(\off).free;
};
)
Now ~notes is something you could play back directly, and save to / load from disk, etc.
hjh