Arpeggiator | Pbindef

Hi guys,
I’m trying to create an arpeggiator to be used in live coding performances.
The idea is to have a MIDI keyb connected to SC and code to automatically fill an array of midi-notes (keeping also track of the order the keys are pressed).
Then to pass the array to an always-playing Pbindef.

I took inspiration from the work of @shiihs and I came up with this (buggy code) this code I would like to submit to you:

// start the server
s.boot;
// initialize MIDI
MIDIClient.init;
MIDIIn.connectAll;

// define a simple synth to play with
(
SynthDef(\sinfb, {
	|freq=400,atk=0.1,rel=0.1,amp=1.0,pan=0.0,fb=0.0|
	var env = EnvGen.ar(Env.perc(atk,rel),doneAction:2);
	var sig = SinOscFB.ar(freq, fb) * env * amp;
	Out.ar(0, Pan2.ar(sig, pan));
}).add;
);

// define an empty list to be filled with midinote from MIDI Keyb
~noteList = []

// define the MIDI handlers
(
MIDIdef.noteOn(\myNoteOn, {
	arg vel, note, ch, src;
	//[note, vel, "ON"].postln;
	~noteList = ~noteList.add(note);
	~noteList.postln;
});

MIDIdef.noteOff(\myNoteOff, {
	arg vel, note, ch, src;
	//[note, vel, "OFF"].postln;
	~noteList.collect({ |x| if(x==note) { ~noteList.remove(x); } { x } });
	~noteList.postln;
});
)

Then, when I use this Pbindef to play the midinote list, even if it works for single notes, it seems to work worse sometimes when I release a chord. Actually the pbindef stops working:

(
Pbindef(\arpeggiator,
	\instrument, \sinfb,
	\midinote, Pn(
		Plazy({
			if(~noteList.isEmpty,
				{ Pseq([Rest(1)]) },
				{ Pseq(~noteList)}
			);
		}),
	inf),
	\dur, 1,
	\atk, 0.0,
	\rel, 0.25
).quant_([4,0]).play;
)
Pbindef(\arpeggiator).stop

What am I doing wrong?
Thank you for your support

somewhat off-topic but this

can be written as

~noteList.remove(note);

I suspect some kind of timing problem where ~noteList is not empty yet when the if is evaluated, but becomes empty by the time the Pseq(~noteList) is created.

To avoid this, I tried making a copy of ~noteList so that it doesn’t become empty while it’s being used, and so far I haven’t seen any more hangups.

(
// start the server
s.waitForBoot {
	// initialize MIDI
	MIDIClient.init;
	MIDIIn.connectAll;
	
	// define a simple synth to play with
	SynthDef(\sinfb, {
		|freq=400,atk=0.1,rel=0.1,amp=1.0,pan=0.0,fb=0.0|
		var env = EnvGen.ar(Env.perc(atk,rel),doneAction:2);
		var sig = SinOscFB.ar(freq, fb) * env * amp;
		Out.ar(0, Pan2.ar(sig, pan));
	}).add;
	
	s.sync;
	
	// define an empty list to be filled with midinote from MIDI Keyb
	~noteList = [];
	
	// define the MIDI handlers
	MIDIdef.noteOn(\myNoteOn, {
		arg vel, note, ch, src;
		//[note, vel, "ON"].postln;
		~noteList = ~noteList.add(note);
	});
	
	MIDIdef.noteOff(\myNoteOff, {
		arg vel, note, ch, src;
		//[note, vel, "OFF"].postln;
		~noteList.remove(note);
	});
	
	Pbindef(\arpeggiator,
		\instrument, \sinfb,
		\midinote, Pn(
			Plazy({
				var n = ~noteList.copy();
				if(n.isEmpty,
					{ Pseq([Rest(1)]) },
					{ Pseq(n) }
				);
			}),
			inf),
		\dur, 0.1,
		\atk, 0.0,
		\rel, 0.25
	).quant_([4,0]).play;
	
};
)
1 Like

Thank you @shiihs for this precious suggestion!
:pray: