I have some rather old code (over 12 years) that captures MIDI notes into a data structure. It probably doesn’t do everything that you want, but you could get some ideas from it.
This is all in the ddwMIDI quark.
To recheck it, I ran some MIDI notes out of Pure Data. Pd showed up as MIDIClient.sources[3].
ddwMIDI has its own way of addressing MIDI input devices (MIDIPort
). When you init MIDIPort, you can pull some devices to the front – MIDIPort.init([3])
means that the third device in MIDIClient.sources becomes device 0 (default device) in MIDIPort.
Then:
r = MIDIRecSocket(0, TempoClock.default);
r.initRecord;
Now r
is grabbing note on/off messages, until you stopRecord
. This method returns the data.
b = r.stopRecord;
-> a MIDIRecBuf
b.dumpSeq;
MIDIRecBuf("buf601.0")
0 : [ 53, 0.20010301800005, 0.30231231300002, 0.50393700787402 ]
1 : [ 60, 0.19940607499996, 0.302256296, 0.50393700787402 ]
2 : [ 51, 0.20091244800005, 0.30381891100001, 0.50393700787402 ]
3 : [ 61, 0.20090130400001, 0.30378040400001, 0.50393700787402 ]
Then, a quick and dirty template to play back:
(
p = Pbind(
\noteObj, b.asPattern, // "a Pseq"
[\midinote, \dur, \sustain, \amp], Pfunc { |ev|
var note = ev[\noteObj];
// freq is really note number
// "gate" = velocity scaled to 0.0 - 1.0
[note.freq, note.dur, note.length, note.gate]
}
).play;
)
There are some other features in there, related to quantizing, and I also had a neat idea at that time about parsing chords and grace notes. But I ended up not going in that direction for my compositional work, so at this point, it’s abandon-ware.
Since it captures notes with timing, though, it may be useful for looping. (The problem I never solved with looping is that language-side processing is earlier than what you hear by s.latency
seconds – so you’ll hit the MIDI button to stop recording and start looping based on the time you hear, but the bar line in the language has already passed. Loop playback, then, would have to skip over the first fraction of a beat and resync on the next note. It’s certainly a solvable problem; I just never finished it.)
(PS One error in the code: it’s using clock.elapsedBeats
to measure time when it really should be clock.beats
.)
I don’t recall that anyone has done this, no.
hjh