Recording a MIDI score

Hey everyone,

The way I’m achieving this now is through MIDIdef's which continuously redefine a running global ~record_string

I’m would truly value any input for recording a MIDI score in a more advanced way.

~record_string = 

(
	~record_string ++
	
	(
		format
		
		(
			"%.wait;\n\n\t\tMIDIIn.doNoteOnAction(veloc: %, num: %);\n\n\t\t"
			
			,
			
			SystemClock.seconds - ~logical_time - currentEnvironment.putGet
			
			(
				\elapsed_time , SystemClock.seconds - ~logical_time
			)
			
			, 
		
			veloc
		
			, 
		
			note
		)
	)
)

Hi Rainer,

I think a sane approach would be to register a noteOn and noteOff handler and store the received events in a list. When the note on is received, register the note as a candidate note in a map of midi note numer → (velocity, time). When the note off is received, look up the note number in the map, subtract the current time from the noteon time and you have the duration of the midi note. Now you have a fully defined note which you can store in some list of notes (a “score” or a “recording” if you like).

Once recording is done, you can iterate over the list and transform it to any format you can think of (if you know how to implement it of course :slight_smile: ).

You can see an example of such approach in my “proof of concept” midi looper here: sc-midi-recorder/recorder.scd at main · shimpe/sc-midi-recorder · GitHub

Thanks @shiihs.

Right now the response defs keep pushing the notes, velocs, & .wait times into an execute file.

Task
{
    MIDIIn.doNoteOnAction(veloc: 80, num: 37);

    0.01587326100811579.wait;

    // ...
}
.play

Would you be able to shed some light on how to implement a collection of note, velocity, and interval values into a simplified working stream, like in the above example?

a = [36, 127, 0.111, 36, 0, 0.115]

I’m certain one could do this with only one line of code… allowing a stream to consistently iterate over the values, creating a strobe light?

I’m sorry I think I do not understand your question.
In any case you can simply iterate a list of data and do with its contents as you please.

Here are some examples but as I didn’t understand your intention, I’m afraid they might not be relevant :slight_smile:

// with internal synth
(
s.waitForBoot {
	var list_of_notes = [
		(\evtype: \noteOn, \evnote: 60, \evdur: 1, \evvel: 0.7),
		(\evtype: \noteOn, \evnote: 67, \evdur: 0.5, \evvel: 0.6),
		(\evtype: \noteOn, \evnote: 65, \evdur: 0.5, \evvel: 0.5),
		(\evtype: \noteOn, \evnote: 60, \evdur: 1, \evvel: 0.4),
		(\evtype: \noteOn, \evnote: 62, \evdur: 2, \evvel: 0.2),
	];
	
	var notes = list_of_notes.collect({|el| el[\evnote] });
	var durs = list_of_notes.collect({ |el| el[\evdur] });
	var vels = list_of_notes.collect({ |el| el[\evvel] });
	
	Pbind(
		\instrument, \default,
		\midinote, Pseq(notes, 1),
		\dur, Pseq(durs, 1),
		\amp, Pseq(vels, 1),
		//...
	).play;
};
)

// with hardware synth
(
s.waitForBoot {
	var list_of_notes = [
		(\evtype: \noteOn, \evnote: 60, \evdur: 1, \evvel: 0.7),
		(\evtype: \noteOn, \evnote: 67, \evdur: 0.5, \evvel: 0.6),
		(\evtype: \noteOn, \evnote: 65, \evdur: 0.5, \evvel: 0.5),
		(\evtype: \noteOn, \evnote: 60, \evdur: 1, \evvel: 0.4),
		(\evtype: \noteOn, \evnote: 62, \evdur: 2, \evvel: 0.2),
	];
	
	var notes = list_of_notes.collect({|el| el[\evnote] });
	var durs = list_of_notes.collect({ |el| el[\evdur] });
	var vels = list_of_notes.collect({ |el| el[\evvel] });
	var midiout;
	if (MIDIClient.initialized.not) { MIDIClient.init; };
	midiout = MIDIOut.newByName("Rev2", "Rev1 MIDI 1"); // some hardware device you have connected
	
	Pbind(
		\type, \midi,
		\midicmd, \noteOn,
		\midiout, midiout,    // must provide the MIDI target here
		\chan, 0,
		\midinote, Pseq(notes, 1),
		\dur, Pseq(durs, 1),
		\amp, Pseq(vels, 1),
		//...
	).play;
};
)

// something perhaps more similar to what you asked, but I do not really understand
// your intention
(
s.waitForBoot {
	var list_of_notes = [
		(\evtype: \noteOn, \evnote: 60, \evdur: 1, \evvel: 0.7),
		(\evtype: \noteOn, \evnote: 67, \evdur: 0.5, \evvel: 0.6),
		(\evtype: \noteOn, \evnote: 65, \evdur: 0.5, \evvel: 0.5),
		(\evtype: \noteOn, \evnote: 60, \evdur: 1, \evvel: 0.4),
		(\evtype: \noteOn, \evnote: 62, \evdur: 2, \evvel: 0.2),
	];
	
	fork {
		list_of_notes.do {
			| note |
			MIDIIn.doNoteOnAction(chan:0, num: note[\evnote], veloc: note[\evvel]);
			note[\evdur].wait;
			MIDIIn.doNoteOffAction(chan:0, num:note[\evnote]);
		}
	}	
};
)
1 Like

Thanks again @shiihs